SpringCloud入门实战(3)-Apollo使用

Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。本文主要介绍Apollo的基本使用,文中使用到的软件版本:Apollo 1.7.0、Spring Boot 2.2.5.RELEASE、Spring Cloud Hoxton.SR3、Java 1.8.0_191、 Mysql 5.7.26。

1、apollo架构

  • Config Service提供配置的读取、推送等功能,服务对象是Apollo客户端
  • Admin Service提供配置的修改、发布等功能,服务对象是Apollo Portal(管理界面)
  • Config Service和Admin Service都是多实例、无状态部署,所以需要将自己注册到Eureka中并保持心跳
  • 在Eureka之上我们架了一层Meta Server用于封装Eureka的服务发现接口
  • Client通过域名访问Meta Server获取Config Service服务列表(IP+Port),而后直接通过IP+Port访问服务,同时在Client侧会做load balance、错误重试
  • Portal通过域名访问Meta Server获取Admin Service服务列表(IP+Port),而后直接通过IP+Port访问服务,同时在Portal侧会做load balance、错误重试
  • 为了简化部署,我们实际上会把Config Service、Eureka和Meta Server三个逻辑角色部署在同一个JVM进程中

2、服务端部署

2.1、环境

Apollo可以管理不同环境的配置:
DEV 开发环境
FAT 测试环境,相当于alpha环境(功能测试)
UAT 集成环境,相当于beta环境(回归测试)
PRO 生产环境

Apollo里不同组件部署方式不一样:

a、Portal只需部署一套,通过它来管理DEV、FAT、UAT、PRO等环境的配置
b、Meta Server、Config Service和Admin Service在每个环境都单独部署,使用独立的数据库
c、Meta Server和Config Service部署在一个JVM进程中

2.2、部署步骤

2.2.1、规划

假设所有服务都部署在10.49.196.10上,并都使用默认的端口:

服务 端口 部署目录
apollo-configservice 8080 /home/hadoop/app/apollo/apollo-configservice
apollo-adminservice 8090 /home/hadoop/app/apollo/apollo-adminservice
apollo-portal 8070 /home/hadoop/app/apollo/apollo-portal

2.2.1、创建ApolloPortalDB

通过Mysql客户端导入数据库的初始化脚本:

https://github.com/ctripcorp/apollo/blob/master/scripts/sql/apolloportaldb.sql

2.2.2、创建ApolloConfigDB

通过Mysql客户端导入数据库的初始化脚本:

https://github.com/ctripcorp/apollo/blob/master/scripts/sql/apolloconfigdb.sql

2.2.3、下载并解压安装包

https://github.com/ctripcorp/apollo/releases 下载adminservice、configservice、portal三个包,如下载1.7.0版本的安装包:apollo-adminservice-1.7.0-github.zip、apollo-configservice-1.7.0-github.zip、apollo-portal-1.7.0-github.zip。把三个安装包放到三个单独的目录(apollo-adminservice、apollo-configservice、apollo-portal)里,然后解压:

cd apollo-adminservice
unzip apollo-adminservice-1.7.0-github.zip

cd apollo-configservice
unzip apollo-configservice-1.7.0-github.zip

cd apollo-portal
unzip apollo-portal-1.7.0-github.zip

2.2.4、配置修改

2.2.4.1、ApolloPortalDB配置

配置项统一存储在ApolloPortalDB.ServerConfig表中,也可以通过管理员工具 - 系统参数页面进行配置,无特殊说明则修改完一分钟实时生效。

apollo.portal.envs 可支持的环境列表 默认值是dev,如果portal需要管理多个环境的话,以逗号分隔即可(大小写不敏感),如:DEV,FAT,UAT,PRO
apollo.portal.meta.servers 各环境Meta Service列表 Apollo Portal需要在不同的环境访问不同的meta service(apollo-configservice)地址,该配置优先级高于其它方式设置的Meta Service地址
2.2.4.2、ApolloConfigDB配置

配置项统一存储在ApolloConfigDB.ServerConfig表中,需要注意每个环境的ApolloConfigDB.ServerConfig都需要单独配置,修改完一分钟实时生效。

eureka.service.url Eureka服务Url apollo-configservice本身就是一个eureka服务,所以只需要填入apollo-configservice的地址即可,如有多个,用逗号分隔
2.2.4.3、配置数据库连接信息

修改 apollo-configservice、apollo-adminservice 两个应用包中 config/application-github.properties 配置文件,配置数据库连接:

spring.datasource.url = jdbc:mysql://localhost:3306/ApolloConfigDB?useSSL=false&characterEncoding=utf8
spring.datasource.username = someuser
spring.datasource.password = somepwd

修改 apollo-portal 应用包中 config/application-github.properties 配置文件,配置数据库连接:

pring.datasource.url = jdbc:mysql://localhost:3306/ApolloPortalDB?useSSL=false&characterEncoding=utf8
spring.datasource.username = someuser
spring.datasource.password = somepwd
2.2.4.4、修改脚本里的日志文件路径

修改apollo-configservice、apollo-adminservice、apollo-portal三个应用包中scripts/startup.sh启动脚本,修改日志文件路径:

LOG_DIR=/opt/logs/100003171

2.2.4.5、修改样例

ApolloPortalDB.ServerConfig,配置了dev和pro环境,并指向了同一个meta地址

 ApolloConfigDB.ServerConfig:

 apollo-configservice/config/application-github.properties、apollo-adminservice/config/application-github.properties:

spring.datasource.url = jdbc:mysql://10.49.196.10:3306/ApolloConfigDB?characterEncoding=utf8
spring.datasource.username = admin
spring.datasource.password = Root_123!

apollo-portal/config/application-github.properties:

spring.datasource.url = jdbc:mysql://10.49.196.10:3306/ApolloPortalDB?characterEncoding=utf8
spring.datasource.username = admin
spring.datasource.password = Root_123!

scripts/startup.sh

#apollo-configservice/scripts/startup.sh
LOG_DIR=/home/hadoop/app/appolo/apollo-configservice/scripts/logs

#apollo-adminservice/scripts/startup.sh
LOG_DIR=/home/hadoop/app/appolo/apollo-adminservice/scripts/logs

#apollo-portal/scripts/startup.sh
LOG_DIR=/home/hadoop/app/appolo/apollo-portal/scripts/logs

2.2.5、启动各应用

cd apollo-configservice/scripts
./startup.sh

cd apollo-adminservice/scripts
./startup.sh

cd apollo-portal/scripts
./startup.sh

2.2.6、portal控制台

http://10.49.196.10:8070/ (apollo/admin)

在控制台先创建项目,在项目里先选择环境,默认会有一个application的namespace,可以创建新的namespace,创建的namespace可以设置为public或private,public的namespace可以被其他的项目关联,private的只能本项目访问,客户端访问的时候需指定namespace。

3、客户端使用

3.1、引入依赖

<dependency>
    <groupId>com.ctrip.framework.apollo</groupId>
    <artifactId>apollo-client</artifactId>
    <version>1.7.0</version>
</dependency>

3.2、修改application.yml

app:
  id: general

apollo:
  meta: http://10.49.196.10:8080
  bootstrap:
    enabled: true
    namespaces: application,db,sms

3.3、在控制台增加配置信息

创建一个general的项目,里面有一个默认的namespace(application),一个关联其他项目(public)的公共namespce(db),一个新增的namespace(sms):

3.4、编写controller

package com.abc.scdemo.general.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

@RestController
public class HelloController {
    private static Logger logger = LoggerFactory.getLogger(HelloController.class);

    @Value( "${spring.application.name}" )
    private String applicationName;
    @Value( "${server.port}" )
    private String applicationPort;

    @Value("${spring.datasource.url}")
    private String dbUrl;
    @Value("${spring.datasource.driverClassName}")
    private String dbDriverClassName;

    @Value("${sms.host}")
    private String smsHost;
    @Value("${sms.port}")
    private String smsPort;

    @GetMapping("getInfo")
    public Map<String, Properties> getInfo() {
        logger.debug("getInfo start....");
        Properties application = new Properties();
        application.setProperty("name", applicationName);
        application.setProperty("port", applicationPort);

        Properties db = new Properties();
        db.setProperty("url", dbUrl);
        db.setProperty("driverClassName", dbDriverClassName);

        Properties sms = new Properties();
        sms.setProperty("host", smsHost);
        sms.setProperty("port", smsPort);

        Map<String, Properties> info = new HashMap<>();
        info.put("application", application);
        info.put("db", db);
        info.put("sms", sms);

        logger.debug("getInfo end.");

        return info;
    }
}

3.5、验证

启动应用后并访问controller可以看到获取到相关信息:

3.6、监控配置项变化

package com.abc.scdemo.general.config;

import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.model.ConfigChange;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfig;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;


@Configuration
public class ApolloConf {
    private static Logger logger = LoggerFactory.getLogger(ApolloConf.class);

    //inject config for namespace application
    @ApolloConfig("application")
    private Config anotherConfig;

    /**config change listener for namespace application*/
    @ApolloConfigChangeListener
    public void configChangeListter(ConfigChangeEvent changeEvent) {
        logger.info("配置改变。。。");
        String item = "someItem";
        if (changeEvent.isChanged(item)) {
            ConfigChange configChange = changeEvent.getChange(item);
            logger.info(item + "配置项改变,oldValue={},newValue={}", configChange.getOldValue(), configChange.getNewValue());
        }
    }
}

 

posted @ 2020-08-15 10:43  且行且码  阅读(1181)  评论(0编辑  收藏  举报