Apollo配置中心基础至案例

686 阅读7分钟

Apollo介绍

image.png Apollo(阿波罗)是一款可靠的分布式配置管理中心,诞生于携程框架研发部,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。

服务端基于Spring Boot和Spring Cloud开发,打包后可以直接运行,不需要额外安装Tomcat等应用容器。

Java客户端不依赖任何框架,能够运行于所有Java运行时环境,同时对Spring/Spring Boot环境也有较好的支持。

Apollo核心概念

  • 项目(应用)

这个很好理解,就是实际使用Apollo配置中心的应用,该应用一般指的就是我们自己的微服务工程。通过引入Apollo客户端,就可以在运行时去配置中心获取对应的配置

关键字:appId

  • environment (环境)

配置对应的环境,Apollo客户端在运行时需要知道当前应用处于哪个环境,从而可以去获取应用的配置

关键字:env

  • cluster (集群)

一个应用下不同实例的分组,比如典型的可以按照数据中心进行划分,把上海机房的应用实例分为一个集群,把北京机房的应用实例分为另一个集群。

关键字:cluster

  • namespace (命名空间)

一个应用下不同配置的分组,可以简单地把namespace类比为文件,不同类型的配置存放在不同的文件中,如数据库配置文件,RPC配置文件,应用自身的配置文件等

关键字:namespaces

Apollo特性

  • 统一管理不同环境、不同集群的配置

  • 配置修改实时生效(热发布)

    • 用户在Apollo修改完配置并发布后,客户端能实时(1秒)接收到最新的配置,并通知到应用程序
  • 版本发布管理

    • 所有的配置发布都有版本概念,从而可以方便地支持配置的回滚
  • 灰度发布

    • 支持配置的灰度发布,比如点了发布后,只对部分应用实例生效,等观察一段时间没问题后再推给所有应用实例
  • 权限管理、发布审核、操作审计

    • 应用和配置的管理都有完善的权限管理机制,对配置的管理还分为了编辑和发布两个环节,从而减少人为的错误。
    • 所有的操作都有审计日志,可以方便地追踪问题
  • 客户端配置信息监控

    • 可以在界面上方便地看到配置在被哪些实例使用

Apollo基础模型

image.png Apollo的基础模型:

  1. 用户在配置中心对配置进行修改并发布
  2. 配置中心通知Apollo客户端有配置更新
  3. Apollo客户端从配置中心拉取最新的配置、更新本地配置并通知到应用

Apollo总体设计

image.png

  • 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进程中

Apollo安装

环境

  • JDK1.8+
  • Mysql5.6.5+
  • 数据库导入ApolloPortalDBApolloConfigDB
  • 配置数据库连接信息

github.com/apolloconfi…

搭建Apollo服务端

Quick Start脚本会在本地启动3个服务,分别使用8070, 8080, 8090端口,请确保这3个端口当前没有被使用。

执行启动脚本

./demo.sh start

image.png

访问

erueka

image.png

Apollo

image.png

Springboot整合Apollo

新增应用

image.png 配置说明

部门:选择应用所在的部门。(想自定义部门,参照官方文档,这里就选择样例)

应用AppId:用来标识应用身份的唯一id,格式为string,需要和客户端。application.properties中配置的app.id对应。

应用名称:应用名,仅用于界面展示。

应用负责人:选择的人默认会成为该项目的管理员,具备项目权限管理、集群创建、Namespace创建等权限。

添加配置

image.png

Springboot项目搭建

案例github地址:github.com/Junlogz/spr…

pom.xml

添加 Apollo 客户端的依赖,主要的就是apollo依赖

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

application.yml

server:
  port: 9090

app:
  id: springboot-test-apollo
apollo:
  meta: http://127.0.0.1:8080
  bootstrap:
    enabled: true
    eagerLoad:
      enabled: true

配置说明

app.id :AppId是应用的身份信息,是配置中心获取配置的一个重要信息。

apollo.bootstrap.enabled:在应用启动阶段,向Spring容器注入被托管的application.properties文件的配置信息。

apollo.bootstrap.eagerLoad.enabled:将Apollo配置加载提到初始化日志系统之前。

TestController.java

@RestController
public class TestController {

    private static Logger log = LoggerFactory.getLogger( TestController.class );

    @Value( "${date.value}" )
    String dateValue;

    @GetMapping("test")
    public String test() {
        return "打印配置中心的 dateValue 值: "+ dateValue;
    }


    @GetMapping("test1")
    public void test1() {
        log.info("当前配置中心的 dateValue 值 = {}",dateValue);
    }

}

启动类

@SpringBootApplication
@EnableApolloConfig
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class);
    }
}

需要添加@EnableApolloConfig注解

测试

image.png

分别两次请求,中间修改一次配置文件

image.png

动态修改日志级别

yml中添加配置

#这里说明在将该项目 com目录下的日志,都采用info模式输出
logging:
  level:
    com: info

我们来思考有没有这么一种需求,我们在线上的日志级别一般是INFO级别的,主要记录业务操作或者错误的日志。那么这个时候当线上环境出现问题希望输出DEBUG

日志信息辅助排查的时候怎么办呢?

如果以前,我们可以会修改配置文件,重新打包然后上传重启线上环境,以前确实是这么做的。通过Apollo配置中心我们可以实现不用重启项目,就可以实现让日志

基本从INFO变成DEBUG。下面我们来演示一番。

在项目启动之前,我在application.yml配置了日志级别是info模式。我们来请求下面接口验证下。

image.png 可以很明显的看出,控制台只打印info级别以上的日志,并没有打印debug日志。

现在我们要做的是将打印日志级别不在交给application.yml而是交给apollo来配置。这里其实要做两步:

1)、在apollo配置一条日志数据

2)、通过监听配置的变化,来达到热更新的效果

配置类

@Configuration
public class LoggerConfig {
    private static final Logger logger = LoggerFactory.getLogger(LoggerConfig.class);
    private static final String LOGGER_TAG = "logging.level.";

    @Autowired
    private LoggingSystem loggingSystem;

    @ApolloConfig
    private Config config;

    @ApolloConfigChangeListener
    private void configChangeListter(ConfigChangeEvent changeEvent) {
        refreshLoggingLevels();
    }

    @PostConstruct
    private void refreshLoggingLevels() {
        Set<String> keyNames = config.getPropertyNames();
        for (String key : keyNames) {
            if (StringUtils.containsIgnoreCase(key, LOGGER_TAG)) {
                String strLevel = config.getProperty(key, "info");
                LogLevel level = LogLevel.valueOf(strLevel.toUpperCase());
                loggingSystem.setLogLevel(key.replace(LOGGER_TAG, ""), level);
                logger.info("{}:{}", key, strLevel);
            }
        }
    }
}

解析

@ApolloConfig注解:将Apollo服务端的中的配置注入这个类中。

@ApolloConfigChangeListener注解:监听配置中心配置的更新事件,若该事件发生,则调用refreshLoggingLevels方法,处理该事件。

ConfigChangeEvent参数:可以获取被修改配置项的key集合,以及被修改配置项的新值、旧值和修改类型等信息。

从上面可以看出,通过@PostConstruct 项目启动的时候就去获取apollo的日志级别去覆盖application.yml日志级别。我在apollo配置中心,新增加一条日志配置。

把日志级别设置error,那么在项目启动的时候,因为PostConstruct注解的原因,所以会去执行一次refreshLoggingLevels方法,把当前日志级别改成error

测试

重启项目,重新请求接口

image.png

再修改日志级别为debug,再请求接口

image.png

image.png