当前位置:   article > 正文

Apollo分布式配置中心_apollo meta server获取config service和admin service(i

apollo meta server获取config service和admin service(ip+port)失败后会一直

概览

什么是配置

  应用程序在启动和运行的时候, 往往需要读取一些配置信息, 配置基本上伴随着应用程序的整个生命周期, 比如: 数据库连接参数, 启动参数等

配置主要有一下几个特点:

  • 配置是独立于程序的只读变量
    • 配置首先是独立于程序的, 同一份程序在不同的配置下会有不同的行为
    • 其次, 配置对于程序是只读的, 程序通过读取配置来改变自己的行为, 但是程序不应该去改变配置
  • 配置伴随应用的整个生命周期
    • 配置贯穿于应用的整个生命周期, 应用在启动时通过读取配置来初始化, 在运行时根据配置调整行为. 比如: 启动时需要读取服务的端口号, 系统在运行过程中需要读取定时策略执行定时任务等.
  • 配置可以有多种加载方式
    • 常见的有程序内部硬编码. 配置文件, 环境变量, 启动参数, 基于数据库等
  • 配置需要治理
    • 权限控制: 由于配置能改变程序的行为, 不正确的配置甚至能引起灾难, 所以对配置的修改必须有比较完善的权限控制
    • 不同环境, 集群配置管理: 同一份程序在不同的环境(开发, 测试, 生成), 不同的集群(如不同的数据中心)经常需要有不同的配置, 所以需要有完善的环境, 集群配置管理

什么是配置中心

  传统单体应用存在一些潜在缺陷, 如随着规模的扩大, 部署效率降低, 团队协作效率差, 系统可靠性变差, 维护困难, 新功能上线周期长等, 所以迫切需要一种新的架构去解决这些问题, 而微服务(microservices)架构正是当下一种流行的解法
  不过, 解决一个问题的同时, 往往会诞生出很多新的问题, 所以微服务化的过程中伴随着很多的挑战, 其中一个挑战就是有关服务(应用)配置的. 当系统从一个单体应用, 被拆分成分布式系统上一个个服务节点后, 配置文件也必须跟着迁移, 分割, 这样配置就分散了, 不仅如此, 分散中还包含着冗余, 如下图
在这里插入图片描述
配置中心将配置从应用中剥离出来, 统一管理, 优雅的解决了配置的动态变更, 持久化, 运维成本等问题
应用自身既不需要去添加管理配置接口, 也不需要自己去实现配置的持久化, 更不需要引入"定时任务"以便降低运维成本
  总的来说, 配置中心就是一种统一管理各种应用配置的基础服务组件
  在系统架构中, 配置中心时整个微服务基础架构体系中的一个组件, 如下图, 它的功能看上去不起眼, 无非就是配置的管理和存取, 但它是整个微服务架构中不可或缺的一环
在这里插入图片描述
  集中管理配置,那么就要将应用的配置作为一个单独的服务抽离出来了,同理也需要解决新的问题,比如:版本管理(为了支持回滚),权限管理等。
  总结一下,在传统巨型单体应用纷纷转向细粒度微服务架构的历史进程中,配置中心是微服务化不可缺少的一个系统组件,在这种背景下中心化的配置服务即配置中心应运而生,一个合格的配置中心需要满足:

  • 配置项容易读取和修改

  • 添加新配置简单直接

  • 支持对配置的修改的检视以把控风险

  • 可以查看配置修改的历史记录

  • 不同部署环境支持隔离

Apollo简介

主流配置中心

目前市面上用的比较多的配置中心有:(按开源时间排序)

  1. Disconf: 2014年7月百度开源的配置管理中心,专注于各种「分布式系统配置管理」的「通用组件」和「通用平台」, 提供统一的「配置管理服务」。目前已经不再维护更新
  2. Spring Cloud Config: 2014年9月开源,Spring Cloud 生态组件,可以和Spring Cloud体系无缝整合。
  3. Apollo: 2016年5月,携程开源的配置管理中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。Apollo配置中心github
  4. Nacos: 2018年6月,阿里开源的配置中心,也可以做DNS和RPC的服务发现。Nacos

功能特性对比

功能点SpringCloudConfigApolloNacos
配置实时推送支持(Spring Cloud Bus)支持(HTTP长轮询1s内)支持(HTTP长轮询1s内)
版本管理支持(Git)支持支持
配置回滚支持(Git)支持支持
灰度发布支持支持不支持
权限管理支持(依赖Git)支持不支持
多集群支持支持支持
多环境支持支持支持
监听查询支持支持支持
多语言只支持Java主流语言, 提供了Open Api主流语言, 提供了Open Api
配置格式校验不支持支持支持
单机读(QPS)7(限流所致)900015000
单机写(QPS)5(限流所致)11001800
3节点读(QPS)21(限流所致)2700045000
3节点写(QPS)5(限流所致)33005600

总结

  总的来看,Apollo和Nacos相对于Spring Cloud Config的生态支持更广,在配置管理流程上做的更好。Apollo相对于Nacos在配置管理做的更加全面,Nacos则使用起来相对比较简洁,在对性能要求比较高的大规模场景更适合。但对于一个开源项目的选型,项目上的人力投入(迭代进度、文档的完整性)、社区的活跃度(issue的数量和解决速度、Contributor数量、社群的交流频次等),这些因素也比较关键,考虑到Nacos开源时间不长和社区活跃度,所以从目前来看Apollo应该是最合适的配置中心选型。

Apollo简介

在这里插入图片描述
Apollo - A reliable configuration management system
https://github.com/ctripcorp/apollo

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

Apollo包括服务端和客户端两部分:

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

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

Apollo特性

基于配置的特殊性,所以Apollo从设计之初就立志于成为一个有治理能力的配置发布平台,目前提供了以下的特性:

  • 统一管理不同环境、不同集群的配置
    • Apollo提供了一个统一界面集中式管理不同环境(environment)、不同集群(cluster)、不同命名空间(namespace)的配置。
    • 同一份代码部署在不同的集群,可以有不同的配置,比如zookeeper的地址等
    • 通过命名空间(namespace)可以很方便地支持多个不同应用共享同一份配置,同时还允许应用对共享的配置进行覆盖
  • 配置修改实时生效(热发布)
    • 用户在Apollo修改完配置并发布后,客户端能实时(1秒)接收到最新的配置,并通知到应用程序
  • 版本发布管理
    • 所有的配置发布都有版本概念,从而可以方便地支持配置的回滚
  • 灰度发布
    • 支持配置的灰度发布,比如点了发布后,只对部分应用实例生效,等观察一段时间没问题后再推给所有应用实例
  • 权限管理、发布审核、操作审计
    • 应用和配置的管理都有完善的权限管理机制,对配置的管理还分为了编辑和发布两个环节,从而减少人为的错误。
    • 所有的操作都有审计日志,可以方便地追踪问题
  • 客户端配置信息监控
    • 可以在界面上方便地看到配置在被哪些实例使用
  • 提供Java和.Net原生客户端
    • 提供了Java和.Net的原生客户端,方便应用集成
    • 支持Spring Placeholder, Annotation和Spring Boot的ConfigurationProperties,方便应用使用(需要Spring 3.1.1+)
    • 同时提供了Http接口,非Java和.Net应用也可以方便地使用
  • 提供开放平台API
    • Apollo自身提供了比较完善的统一配置管理界面,支持多环境、多数据中心配置管理、权限、流程治理等特性。不过Apollo出于通用性考虑,不会对配置的修改做过多限制,只要符合基本的格式就能保存,不会针对不同的配置值进行针对性的校验,如数据库用户名、密码,Redis服务地址等
    • 对于这类应用配置,Apollo支持应用方通过开放平台API在Apollo进行配置的修改和发布,并且具备完善的授权和权限控制

Apollo快速入门

执行流程

在这里插入图片描述
操作流程如下:

  1. 在Apollo配置中心修改配置
  2. 应用程序通过Apollo客户端从配置中心拉取配置信息

用户通过Apollo配置中心修改或发布配置后,会有两种机制来保证应用程序来获取最新配置:一种是Apollo配置中心会向客户端推送最新的配置;另外一种是Apollo客户端会定时从Apollo配置中心拉取最新的配置,通过以上两种机制共同来保证应用程序能及时获取到配置。

Windows安装Apollo

运行时环境

Java

  • Apollo服务端:1.8+
  • Apollo客户端:1.7+

由于需要同时运行服务端和客户端,所以建议安装Java 1.8+。

MySQL

  • 版本要求:5.6.5+

Apollo的表结构对timestamp使用了多个default声明,所以需要5.6.5以上版本。

下载配置

  1. 访问Apollo的官方主页获取安装包(本次使用1.3版本):https://github.com/ctripcorp/apollo/tags
  2. 打开1.3发布链接,下载必须的安装包:https://github.com/ctripcorp/apollo/releases/tag/v1.3.0
    在这里插入图片描述
  3. 解压安装包后将apollo-configservice-1.3.0.jar, apollo-adminservice-1.3.0.jar, apollo-portal-1.3.0.jar放置于apollo目录下

创建数据库

Apollo服务端共需要两个数据库:ApolloPortalDBApolloConfigDB,ApolloPortalDB只需要在生产环境部署一个即可,而ApolloConfigDB需要在每个环境部署一套。

  1. 创建ApolloPortalDB,sql脚本下载地址:https://github.com/ctripcorp/apollo/blob/v1.3.0/scripts/db/migration/configdb/V1.0.0__initialization.sql
    以MySQL原生客户端为例:soure apollo/ApolloPortalDB_initialization.sql
  2. 验证ApolloPortalDB
    导入成功后, 可以通过执行以下SQL语句来验证
    select `Id`, `Key`, `Value`, `Comment` from `ApolloPortalDB`.`ServerConfig` limit 1;

注: ApolloPortalDB只需要在生产环境部署一个即可

  1. 创建ApolloConfigDB,sql脚本下载地址:https://github.com/ctripcorp/apollo/blob/v1.3.0/scripts/db/migration/configdb/V1.0.0__initialization.sql
    以MySQL原生客户端为例:
    source apollo/ApolloConfigDB__initialization.sql
  2. 验证ApolloConfigDB
    select `Id`, `Key`, `Value`, `Comment` from `ApolloConfigDB`.`ServerConfig` limit 1;

启动Apollo

  1. 确保端口未被占用
    Apollo默认会启动3个服务,分别使用8070, 8080, 8090端口,请确保这3个端口当前没有被使用
  2. 启动apollo-configservice,在apollo目录下执行如下命令 可通过-Dserver.port=8080修改默认端口
    java -Xms256m -Xmx256m -Dspring.datasource.url=jdbc:mysql://localhost:3306/ApolloConfigDB?characterEncoding=utf8 -Dspring.datasource.username=root -Dspring.datasource.password=pbteach0430 -jar apollo-configservice-1.3.0.jar
  3. 启动apollo-adminservice 可通过-Dserver.port=8090修改默认端口
    java -Xms256m -Xmx256m -Dspring.datasource.url=jdbc:mysql://localhost:3306/ApolloConfigDB?characterEncoding=utf8 -Dspring.datasource.username=root -Dspring.datasource.password=pbteach0430 -jar apollo-adminservice-1.3.0.jar
  4. 启动apollo-portal 可通过-Dserver.port=8070修改默认端口
    java -Xms256m -Xmx256m -Ddev_meta=http://localhost:8080/ -Dserver.port=8070 -Dspring.datasource.url=jdbc:mysql://localhost:3306/ApolloPortalDB?characterEncoding=utf8 -Dspring.datasource.username=root -Dspring.datasource.password=pbteach0430 -jar apollo-portal-1.3.0.jar
  5. 也可以使用提供的runApollo.bat快速启动三个服务(修改数据库连接地址,数据库以及密码)
 echo

   set url="localhost:3306"
   set username="root"
   set password="123"

   start "configService" java -Xms256m -Xmx256m -Dapollo_profile=github -Dspring.datasource.url=jdbc:mysql://%url%/ApolloConfigDB?characterEncoding=utf8 -Dspring.datasource.username=%username% -Dspring.datasource.password=%password% -Dlogging.file=.\logs\apollo-configservice.log -jar .\apollo-configservice-1.3.0.jar
   start "adminService" java -Xms256m -Xmx256m -Dapollo_profile=github -Dspring.datasource.url=jdbc:mysql://%url%/ApolloConfigDB?characterEncoding=utf8 -Dspring.datasource.username=%username% -Dspring.datasource.password=%password% -Dlogging.file=.\logs\apollo-adminservice.log -jar .\apollo-adminservice-1.3.0.jar
   start "ApolloPortal" java -Xms256m -Xmx256m -Dapollo_profile=github,auth -Ddev_meta=http://localhost:8080/ -Dserver.port=8070 -Dspring.datasource.url=jdbc:mysql://%url%/ApolloPortalDB?characterEncoding=utf8 -Dspring.datasource.username=%username% -Dspring.datasource.password=%password% -Dlogging.file=.\logs\apollo-portal.log -jar .\apollo-portal-1.3.0.jar
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

运行runApollo.bat即可启动Apollo 待启动成功后,访问管理页面(localhost:8070) apollo/admin
在这里插入图片描述

Linux安装Apollo

  1. 下载三个压缩包在这里插入图片描述
  2. 准备3台服务器,一台安装portal 第二台作为DEV环境部署configservice和adminservice 第三台是pro环境作为生产, dev和pro环境都要部署configservice和adminservice
    portal是操作界面, 可以共用 一个
  3. 准备两个mysql数据库,一个能连接到dev环境,一个能连接到pro环境
    dev环境需要创建ApolloPortalDBApolloConfigDB pro环境只需要创建ApolloConfigDB
  4. 把portalservice压缩包上传至服务器1 configservice和adminservice都分别上传至dev 和perf环境的服务器
  5. 解压缩
  6. 修改配置
    进入到portal的文件夹, 进入到config目录
    在这里插入图片描述
    vim apollo-env.properties
    在这里插入图片描述

dev.meta是第二台服务器dev的ip加8080端口, pro.meta是第三台服务器pro的ip加8080端口,其余环境暂时没有用到
vim application-github.properties
在这里插入图片描述

修改portal对应的mysql地址username 和password
进入PortalDB数据库 修改表格(ServerConfig)在这里插入图片描述

进入到第二台服务器中,首先进入configservice的config目录
vim application-github.properties
修改成dev环境的ApolloConfigDB的数据库配置
再进入adminservice的config目录, 修改application-github.properties的数据库配置

进入到第三台服务器, 修改configservice和adminservice的mysql数据库配置

  1. 启动Apollo 顺序, 先启动dev和pro的configservice , adminservice 再启动 portal
    先进入到script目录 执行./startup.sh
  2. Apollo的运行日志在/opt/logs目录下
  3. 访问地址是portal所在的服务器的ip加8070端口, 默认username: apollo 密码: admin

代码实现

发布配置

  1. 打开apollo :新建项目apollo-quickstart
    在这里插入图片描述
  2. 新增配置项sms.enable
    在这里插入图片描述
    在这里插入图片描述
  3. 发布配置项, 只有发布过的配置才会被客户端获取到, 此次发布只会作用于当前环境dev
    在这里插入图片描述
    在这里插入图片描述

应用读取配置

  1. 新建maven 工程 新建apollo-quickstart项目
<dependencies>
        <dependency>
            <groupId>com.ctrip.framework.apollo</groupId>
            <artifactId>apollo-client</artifactId>
            <version>1.1.0</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.28</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>8</source>
                    <target>8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

编写main方法获取配置

import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigService;

public class GetConfigTest {

    //VM Options:
    //-Dapp.id=applo-quickstart -Denv=DEV -Ddev_meta=http://localhost:8080
    public static void main(String[] args) {
        Config config = ConfigService.getAppConfig();
        String someKey = "sms.enable";
        //获取配置信息, 第一个参数: 配置的key, 第二个参数: 拿不到的话配置的默认值
        //如果这样写会报警告, 找不到app.id,没有与Apollo内的项目绑定,暂时先通过VM-Options的方式加入
        String value = config.getProperty(someKey,null);
        System.out.println("sms.enable: " + value);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

修改配置

修改sms.enable的配置, 再启动main方法, 发现sms.enable输出已经改变了

热发布

修改代码, 让主方法一直取配置

import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigService;

import java.time.LocalDateTime;

public class GetConfigTest {

    //VM Options:
    //-Dapp.id=applo-quickstart -Denv=DEV -Ddev_meta=http://localhost:8080
    public static void main(String[] args) throws InterruptedException {
        Config config = ConfigService.getAppConfig();

        while(true){
            Thread.sleep(1000);
            String someKey = "sms.enable";
            //获取配置信息, 第一个参数: 配置的key, 第二个参数: 拿不到的话配置的默认值
            //如果这样写会报警告, 找不到app.id,没有与Apollo内的项目绑定,暂时先通过VM-Options的方式加入
            String value = config.getProperty(someKey,null);
            //打印带时间的日志
            System.out.printf("now: %s , sms.enable: %s%n " , LocalDateTime.now().toString(), value);
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

启动main方法后, 去Apollo管理页面修改sms.enable的值, 发现配置可以修改并自动生效

Apollo应用

Apollo工作原理

在这里插入图片描述

各模块职责

上图简要描述了Apollo的总体设计,我们可以从下往上看:

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

为什么使用Eureka

在这里插入图片描述

分布执行流程

  1. Apollo启动后,Config/Admin Service会自动注册到Eureka服务注册中心,并定期发送保活心跳。
  2. Apollo Client和Portal管理端通过配置的Meta Server的域名地址经由Software Load Balancer(软件负载均衡器)进行负载均衡后分配到某一个Meta Server
  3. Meta Server从Eureka获取Config Service和Admin Service的服务信息,相当于是一个Eureka Client
  4. Meta Server获取Config Service和Admin Service(IP+Port)失败后会进行重试
  5. 获取到正确的Config Service和Admin Service的服务信息后,Apollo Client通过Config Service为应用提供配置获取、实时更新等功能;Apollo Portal管理端通过Admin Service提供配置新增、修改、发布等功能

核心概念

  1. application(应用)
    这个很好理解, 就是实际使用配置的应用, Apollo客户端在运行时需要知道当前应用是谁, 从而可以去获取对应的配置
    关键字: appId
  2. environment(环境)
    配置对应的环境, Apollo客户端在运行时需要知道当前应用处于哪个环境, 从而可以去获取应用的配置
    关键字: env
  3. cluster(集群)
    一个应用下不同实例的分组, 比如典型的可以按照数据中心分, 把上海机房的应用实例分为一个集群, 把北京机房的应用实例分为另一个集群
    关键字: cluster
  4. namespace(命名空间)
    一个应用下不同配置的分组, 可以简单的把namespace类比为文件, 不同类型的配置存放在不同的文件中, 如数据库配置文件, RPC配置文件, 应用自身配置文件等
    关键字: namespaces
    他们的关系如下图所示
    在这里插入图片描述

项目管理

基础设置

部门管理

apollo默认的部门有两个. 要增加自己的部门, 可在系统参数中修改:

  • 进入系统参数设置
    在这里插入图片描述

  • 输入key查询以存在的部门设置: organizations
    在这里插入图片描述

  • 修改value值来添加新部门, 下面添加一个微服务部门
    在这里插入图片描述

  • 退出后重新登录, 可以使之生效

添加用户

apollo默认提供一个超级管理员: apollo, 可以自行添加用户

  • 新建用户张三
    在这里插入图片描述
    在这里插入图片描述
    下面就可以创建项目时指定负责人了

创建项目

  • 在主页点击创建项目 account-service
    在这里插入图片描述
    在这里插入图片描述
    以apollo用户登录可以看到所有的项目, 但是以zhangsan登录, 只能看到分配给他的account-service

删除项目

如果想要删除整个项目, 点击右上角的"管理员工具–> 删除应用, 集群"
在这里插入图片描述
首先查询出要删除的项目, 点击"删除应用"
在这里插入图片描述

在项目中给其他用户授权

在这里插入图片描述
在这里插入图片描述

配置管理

下边在account-service项目中进行配置

添加发布配置项

  1. key-value对添加配置
    在这里插入图片描述
    在这里插入图片描述
  2. 通过文本模式进行添加或修改 Apollo除了支持表格模式,逐个添加、修改配置外,还提供文本模式批量添加、修改。 这个对于从已有的properties文件迁移尤其有用
    在这里插入图片描述

修改配置

点击右侧修改按钮
在这里插入图片描述
在这里插入图片描述

删除配置

点击右侧删除按钮
在这里插入图片描述

注意: 无论是添加,删除, 修改 要想使其对项目生效都需要发布

添加namespace

Namespace作为配置的分类,可当成一个配置文件。
以添加rocketmq配置为例,添加“spring-rocketmq” Namespace配置rocketmq相关信息。

  1. 添加项目私有Namespace:spring-rocketmq
    进入项目首页,点击左下脚的“添加Namespace”,共包括两项:关联公共Namespace和创建Namespace,这里选择“创建Namespace”
    在这里插入图片描述
    在这里插入图片描述

创建成功后, 会跳转到针对这个namespace的权限分配页面, 可以对某些用户进行授权
在这里插入图片描述

在这里插入图片描述
想要获取到指定namespace下的配置, 需要修改java代码

import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigService;

import java.time.LocalDateTime;

public class GetConfigTest {

    //VM Options:
    //-Dapp.id=account-service -Denv=DEV -Ddev_meta=http://localhost:8080
    public static void main(String[] args) throws InterruptedException {
    	//读取默认namespace的配置信息
        //Config config = ConfigService.getAppConfig();
        
        //指定namespace获取config对象
        Config config = ConfigService.getConfig("spring-rocketmq");

        while(true){
            Thread.sleep(1000);
            String someKey = "rocketmq.name-server";
            //获取配置信息, 第一个参数: 配置的key, 第二个参数: 拿不到的话配置的默认值
            //如果这样写会报警告, 找不到app.id,没有与Apollo内的项目绑定,暂时先通过VM-Options的方式加入
            String value = config.getProperty(someKey,null);
            System.out.printf("now: %s , sms.enable: %s%n " , LocalDateTime.now().toString(), value);
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

公共配置

添加公共namespace

在项目开发中,有一些配置可能是通用的,我们可以通过把这些通用的配置放到公共的Namespace中,这样其他项目要使用时可以直接添加需要的Namespace

  1. 新建common-template项目(所有的配置都得依赖于项目进行保存, 所以先创建一个, 用于保存公共配置的项目)
    在这里插入图片描述
  2. 添加公共namespace: spring-boot-http

在这里插入图片描述
3. 添加配置项并发布

spring.http.encoding.enabled = true
spring.http.encoding.charset = UTF-8
spring.http.encoding.force = true
server.tomcat.remote_ip_header = x-forwarded-for
server.tomcat.protocol_header = x-forwarded-proto
server.use-forward-headers = true
server.servlet.context-path = /
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在这里插入图片描述

关联公共namespace
  1. 打开之前创建的account-service项目
  2. 点击左侧的添加Namespace
    在这里插入图片描述
    点击右侧按钮, 覆盖并修改公共配置为自己想要的配置
    在这里插入图片描述
    在这里插入图片描述

集群管理

在有些情况下,应用有需求对不同的集群做不同的配置,比如部署在A机房的应用连接的RocketMQ服务器地址和部署在B机房的应用连接的RocketMQ服务器地址不一样。另外在项目开发过程中,也可为不同的开发人员创建不同的集群来满足开发人员的自定义配置。

创建集群

  1. 点击页面左侧的“添加集群”按钮
  2. 输入集群名称SHAJQ, 选择环境并提交: 添加上海金桥数据中心为例
    在这里插入图片描述
  3. 切换到新的集群中, 发现新的集群只有私有namespace而没有配置项(没有关联的namespace 需要手动关联)
    在这里插入图片描述

同步集群配置

同步集群的配置是指在同一个应用中拷贝某个环境下的集群的配置到目标环境下的目标集群。

  1. 从其他集群同步已有配置到新集群 先切换到原有集群, 展开要同步的namespace 点击同步配置
    在这里插入图片描述
  2. 选择同步到的新集群, 再选择同步配置,下一步
    在这里插入图片描述
  3. 同步完成后,切换到SHAJQ集群,发布配置

读取配置

读取某个集群的配置,需要启动应用时指定具体的应用、环境和集群。
-Dapp.id=应用名称

-Denv=环境名称

-Dapollo.cluster=集群名称

-D环境_meta=meta地址

-Dapp.id=account-service -Denv=DEV -Dapollo.cluster=SHAJQ -Ddev_meta=http://localhost:8080

配置发布原理

在配置中心中,一个重要的功能就是配置发布后实时推送到客户端。下面我们简要看一下这块是怎么设计实现的。
在这里插入图片描述
上图简要描述了配置发布的主要过程:

  1. 用户在Portal操作配置发布
  2. Portal调用Admin Service的接口操作发布
  3. Admin Service发布配置后,发送ReleaseMessage给各个Config Service(Apollo的设计是自己实现了消息队列, 为了不与第三方进行整合)
  4. Config Service收到ReleaseMessage后,通知对应的客户端

发送ReleaseMessage

Admin Service在配置发布后,需要通知所有的Config Service有配置发布,从而Config Service可以通知对应的客户端来拉取最新的配置。

从概念上来看,这是一个典型的消息使用场景,Admin Service作为producer(生产者)发出消息,各个Config Service作为consumer(消费者)消费消息。通过一个消息队列组件(Message Queue)就能很好的实现Admin Service和Config Service的解耦。

在实现上,考虑到Apollo的实际使用场景,以及为了尽可能减少外部依赖,我们没有采用外部的消息中间件,而是通过数据库实现了一个简单的消息队列。

具体实现方式如下:

  1. Admin Service在配置发布后会往ReleaseMessage表插入一条消息记录,消息内容就是配置发布的AppId+Cluster+Namespace
    SELECT * FROM ApolloConfigDB.ReleaseMessage
    在这里插入图片描述
    消息发送类: DatabaseMessageSende 消息发送类的代码
    在这里插入图片描述
  2. Config Service有一个线程会每秒扫描一次ReleaseMessage表,看看是否有新的消息记录
    消息扫描类:ReleaseMessageScanner类

在这里插入图片描述
3. Config Service如果发现有新的消息记录,那么就会通知到所有的消息监听器
在这里插入图片描述
然后调用消息监听类的handleMessage方法:NotificationControllerV2
在这里插入图片描述
4. NotificationControllerV2得到配置发布的AppId+Cluster+Namespace后,会通知对应的客户端

Config Service通知客户端

上一节中简要描述了NotificationControllerV2是如何得知有配置发布的,那NotificationControllerV2在得知有配置发布后是如何通知到客户端的呢?

实现方式如下:

  1. 客户端会发起一个Http请求到Config Service的notifications/v2接口NotificationControllerV2
    在这里插入图片描述
    客户端发送请求类:RemoteConfigLongPollService
    在这里插入图片描述
  2. NotificationControllerV2不会立即返回结果,而是把请求挂起。考虑到会有数万客户端向服务端发起长连,因此在服务端使用了async servlet(Spring DeferredResult)来服务Http Long Polling请求。
  3. 如果在60秒内没有该客户端关心的配置发布,那么会返回Http状态码304给客户端。
  4. 如果有该客户端关心的配置发布,NotificationControllerV2会调用DeferredResult的setResult方法,传入有配置变化的namespace信息,同时该请求会立即返回。客户端从返回的结果中获取到配置变化的namespace后,会立即请求Config Service获取该namespace的最新配置。

客户端读取设计

除了之前介绍的客户端和服务端保持一个长连接,从而能第一时间获得配置更新的推送外,客户端还会定时从Apollo配置中心服务端拉取应用的最新配置。

  • 这是一个备用机制,为了防止推送机制失效导致配置不更新
  • 客户端定时拉取会上报本地版本,所以一般情况下,对于定时拉取的操作,服务端都会返回304 - Not Modified
  • 定时频率默认为每5分钟拉取一次,客户端也可以通过在运行时指定System Property: apollo.refreshInterval来覆盖,单位为分钟

Apollo应用于分布式系统

在微服务架构模式下,项目往往会切分成多个微服务,下面将以万信金融P2P项目为例演示如何在项目中使用。

项目场景介绍

项目概述

万信金融是一款面向互联网大众提供的理财服务和个人消费信贷服务的金融平台,依托大数据风控技术,为用户提供方便、快捷、安心的P2P金融服务。本项目包括交易平台和业务支撑两个部分,交易平台主要实现理财服务,包括:借钱、出借等模块,业务支撑包括:标的管理、对账管理、风控管理等模块。项目采用先进的互联网技术进行研发,保证了P2P双方交易的安全性、快捷性及稳定性。

各微服务介绍

本章节仅仅是为了演示配置中心,所以摘取了部分微服务,如下:

用户中心服务(consumer-service):为借款人和投资人提供用户账户管理服务,包括:注册、开户、充值、提现等

UAA认证服务(uaa-service):为用户中心的用户提供认证服务

统一账户服务(account-service):对借款人和投资人的登录平台账号进行管理,包括:注册账号、账号权限管理等

交易中心(transaction-service):负责P2P平台用户发标和投标功能

SpringBoot应用集成

下面以集成统一账户服务(account-service)为例

导入工程

参考account-service、transaction-service、uaa-service、consumer-service工程,手动创建这几个微服务。

每个工程必须添加依赖:

<dependency>
  <groupId>com.ctrip.framework.apollo</groupId>
  <artifactId>apollo-client</artifactId>
  <version>1.1.0</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5

下边是account-service依赖,其它工程参考“资料”下的“微服务”。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.pbteach</groupId>
    <artifactId>account-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

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

    </dependencies>

</project>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

必选配置

  1. AppId:application.yml中配置
app:
  id: account-service
  • 1
  • 2
  1. apollo.bootstrap
apollo:
  bootstrap: 
    enabled: true
    # namespace中间以,分隔
    namespaces: application,micro_service.spring-boot-http,spring-rocketmq,micro_service.spring-boot-druid
  • 1
  • 2
  • 3
  • 4
  • 5
  1. env 需要通过VMOPtions来指定
    在这里插入图片描述

  2. cacheDir, cluster, meta, 都可以通过yml文件的方式配置, 但是env需要通过指定VMOptions来配置

server:
  port: 19082
  servlet:
    context-path: /gbmp/bdmgmt
spring:
  application:
    name: account-service

apollo:
  bootstrap:
    enabled: true
    namespaces: application,yuecloud.mybatis,yuecloud.management,yuecloud.logging,yuecloud.pagehelper,yuecloud.datasource,yuecloud.jackson,yuecloud.redis,yuecloud.eureka,yuecloud.securityoauth2
  cacheDir: /opt/data/apollo-config
  cluster: DEFAULT
  meta: http://localhost:8080
app:
  id: account-service

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

启用配置

在主启动类上加入注解@EnableApolloConfig

import com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableApolloConfig
public class AccountMain {
    public static void main(String[] args) {
        SpringApplication.run(AccountMain.class,args);
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

应用配置

将自己的配置信息拷贝到apollo中

读取配置

在Controller上获取配置@Value方式,在Apollo上点击发布会自动刷新
@ConfigurationProperties(prefix=“dev”)配置文件方式, 需要加@RefreshScope才会自动刷新
首先需要加入pom的jar包

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-context</artifactId>
    <version>2.0.1.RELEASE</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5

再写一个配置类,配置刷新监控类ConfigRefresh
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

创建其他项目

可以把其他微服务的配置文件都放到Apollo上

生产环境部署

当一个项目要上线部署到生产环境时,项目的配置比如数据库连接、RocketMQ地址等都会发生变化,这时候就需要通过Apollo为生产环境添加自己的配置。

企业部署方案

在企业中常用的部署方案为:Apollo-adminservice和Apollo-configservice两个服务分别在线上环境(pro),仿真环境(uat)和开发环境(dev)各部署一套,Apollo-portal做为管理端只部署一套,统一管理上述三套环境。
在这里插入图片描述

  1. 部署pro环境如同上述Linux部署Apollo相同.
  2. 启动之后,点击account-service服务配置后会提示环境缺失,此时需要补全上边新增生产环境的配置
    在这里插入图片描述
  3. 点击补缺环境
    在这里插入图片描述
  4. 补缺过生产环境后,切换到PRO环境后会提示有Namespace缺失,点击补缺
    在这里插入图片描述
    在这里插入图片描述
  5. 从dev环境同步配置到pro
    在这里插入图片描述
    在这里插入图片描述

验证配置

同步完成后,切换到pro环境,修改生产环境rocketmq地址后发布配置
在这里插入图片描述

  1. 配置项目使用pro环境,测试配置是否生效
    • 在apollo-env.properties中增加pro.meta=http://localhost:8081
    • 修改account-service启动参数为:-Denv=pro
      -Denv=pro -Dapollo.cacheDir=/opt/data/apollo-config -Dapollo.cluster=DEFAULT
    • 访问http://127.0.0.1:63000/account-service/mq 验证RocketMQ地址是否为上边设置的PRO环境的值

灰度发布

定义

灰度发布是指在黑与白之间,能够平滑过渡的一种发布方式。在其上可以进行A/B testing,即让一部分用户继续用产品特性A,一部分用户开始用产品特性B,如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B上面来。

Apollo实现的功能

  1. 对于一些对程序有比较大影响的配置,可以先在一个或者多个实例生效,观察一段时间没问题后再全量发布配置。
  2. 对于一些需要调优的配置参数,可以通过灰度发布功能来实现A/B测试。可以在不同的机器上应用不同的配置,不断调整、测评一段时间后找出较优的配置再全量发布配置。

场景介绍

apollo-quickstart项目有两个客户端:

  1. 172.16.0.160
  2. 172.16.0.170
    在这里插入图片描述
    灰度目标
    当前有一个配置timeout=2000,我们希望对172.16.0.160灰度发布timeout=3000,对172.16.0.170仍然是timeout=2000。
    在这里插入图片描述

创建灰度

  1. 点击application namespace右上角的创建灰度按钮
    在这里插入图片描述
  2. 点击确定后,灰度版本就创建成功了,页面会自动切换到灰度版本Tab
    在这里插入图片描述

灰度配置

  1. 点击主版本的配置中,timeout配置最右侧的对此配置灰度按钮
    在这里插入图片描述
  2. 在弹出框中填入要灰度的值:3000,点击提交
    在这里插入图片描述
    在这里插入图片描述

配置灰度规则

  1. 切换到灰度规则Tab,点击新增规则按钮
    在这里插入图片描述
  2. 在弹出框中灰度的IP下拉框会默认展示当前使用配置的机器列表,选择我们要灰度的IP,点击完成
    在这里插入图片描述
    在这里插入图片描述
    如果下拉框中没找到需要的IP,说明机器还没从Apollo取过配置,可以点击手动输入IP来输入,输入完后点击添加按钮
    在这里插入图片描述

灰度发布

启动apollo-quickstart项目的GrayTest类输出timeout的值

public class GrayTest {

   	// VM options:
   	// -Dapp.id=apollo-quickstart -Denv=DEV -Ddev_meta=http://localhost:8080
   	public static void main(String[] args) throws InterruptedException {
   		Config config = ConfigService.getAppConfig();
   		String someKey = "timeout";

   		while (true) {
   			String value = config.getProperty(someKey, null);
   			System.out.printf("now: %s, timeout: %s%n", LocalDateTime.now().toString(), value);
   			Thread.sleep(3000L);
   		}
   	}
   }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

在这里插入图片描述

  1. 切换到配置Tab,再次检查灰度的配置部分,如果没有问题,点击灰度发布
    在这里插入图片描述
  2. 在弹出框中可以看到主版本的值是2000,灰度版本即将发布的值是3000。填入其它信息后,点击发布
    在这里插入图片描述
  3. 发布后,切换到灰度实例列表Tab,就能看到172.16.0.160已经使用了灰度发布的值
    在这里插入图片描述
    在这里插入图片描述

全量发布

如果灰度的配置测试下来比较理想,符合预期,那么就可以操作全量发布。
全量发布的效果是:

  1. 灰度版本的配置会合并回主版本,在这个例子中,就是主版本的timeout会被更新成3000
  2. 主版本的配置会自动进行一次发布
  3. 在全量发布页面,可以选择是否保留当前灰度版本,默认为不保留。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

放弃灰度

如果灰度版本不理想或者不需要了,可以点击放弃灰度
在这里插入图片描述

发布历史

点击主版本的发布历史按钮,可以看到当前namespace的主版本以及灰度版本的发布历史

搭建Apollo高可用集群

在这里插入图片描述
现在在203节点上通过修改配置文件的方式, 改成DEV环境下的集群, 202和203应该共用一套mysql的ConfigServiceDB

  1. 修改203节点的configservice和adminservice的mysql配置 改成和202节点一样
  2. 因为此时没有PRO环境了, 所以在Portal的mysql数据库的ServerConfig表中改回dev
    在这里插入图片描述
  3. 修改202节点连接的数据库的ApolloConfigDB中的ServerConfig表, 修改eureka的地址,加上203节点的eureka地址
    在这里插入图片描述
本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号