5分钟学废携程出品配置中心阿波罗的原理与搭建

Posted 代码狂魔v

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了5分钟学废携程出品配置中心阿波罗的原理与搭建相关的知识,希望对你有一定的参考价值。

目录

5分钟学废携程出品配置中心阿波罗的原理与搭建

背景

  • 随着程序功能的日益复杂,程序的配置日益增多:各种功能的开关、参数的配置、服务器的地址……
  • 对程序配置的期望值也越来越高:配置修改后实时生效,灰度发布,分环境、分集群管理配置,完善的权限、审核机制……
  • 并且随着采用分布式的开发模式,项目之间的相互引用随着服务的不断增多,相互之间的调用复杂度成指数升高,每次投产或者上线新的项目时苦不堪言,因此需要引用配置中心治理。

在这样的大环境下,传统的通过配置文件、数据库等方式已经越来越无法满足开发人员对配置管理的需求。

目前已存在的配置中心

配置中心应运而生,目前配置中心有

  • spring-cloud-config:spring出品,可以和spring cloud无缝配合
  • 淘宝 diamond:已经不维护。
  • disconf:java开发,蚂蚁金服技术专家发起,业界使用广泛。
  • ctrip apollo:Apollo(阿波罗)是携程框架部门研发的开源配置管理中心,具备规范的权限、流程治理等特性。

对比

为什么选择Apollo?下面是一个对比表

功能

几个配置中心在功能上的对比

|

功能点

|

优先级

|

spring-cloud-config

|

ctrip apollo

|

disconf

|

备注

|
|

静态配置管理

|

|

基于file

|

支持

|

支持

| |
|

动态配置管理

|

|

支持

|

支持

|

支持

| |
|

统一管理

|

|

无,需要github

|

支持

|

支持

| |
|

多环境

|

|

无,需要github

|

支持

|

支持

| |
|

本地配置缓存

|

|

|

支持

|

支持

| |
|

配置锁

|

|

支持

|

不支持

|

不支持

|

不允许动态及远程更新

|
|

配置校验

|

|

|

|

|

如:ip地址校验,配置

|
|

配置生效时间

| |

重启生效,或手动refresh生效

|

实时

|

实时

|

需要结合热加载管理, springcloudconfig需要 git webhook+rabbitmq 实时生效

|
|

配置更新推送

|

|

需要手工触发

|

支持

|

支持

| |
|

配置定时拉取

|

|

|

支持

|

配置更新目前依赖事件驱动, client重启或者server端推送操作

| |
|

用户权限管理

|

|

无,需要github

|

支持

|

支持

|

现阶段可以人工处理

|
|

授权、审核、审计

|

|

无,需要github

|

支持

|

|

现阶段可以人工处理

|
|

配置版本管理

|

|

Git做版本管理

|

界面上直接提供发布历史和回滚按钮

|

操作记录有落数据库,但无查询接口

| |
|

配置合规检测

|

|

不支持

|

支持(但还需完善)

| | |
|

实例配置监控

|

|

需要结合springadmin

|

支持

|

支持,可以查看每个配置在哪些机器上加载

| |
|

灰度发布

|

|

不支持

|

支持

|

不支持部分更新

|

现阶段可以人工处理

|
|

告警通知

|

|

不支持

|

支持,邮件方式告警

|

支持,邮件方式告警

| |
|

依赖关系

|

|

不支持

|

不支持

|

不支持

|

配置与系统版本的依赖系统运行时的依赖关系

|

兼容性

几个配置中心和其他开发框架的对比

|

功能点

|

优先级

|

spring-cloud-config

|

ctrip apollo

|

disconf

|
|

SpringBoot支持

|

|

原生支持

|

支持

|

与spring boot无相关

|
|

SpringCloud支持

|

|

原生支持

|

支持

|

与spring cloud无相关

|
|

客户端支持

|

|

Java

|

Java、.Net

|

java

|
|

业务系统侵入性

|

|

侵入性弱

|

侵入性弱

|

侵入性弱,支持注解及xml方式

|
|

依赖组件

|

|

Eureka

|

Eureka

|

zookeeper

|

可用性与易用性

| | | | | | |

功能点

|

优先级

|

spring-cloud-config

|

ctrip apollo

|

disconf

|
|

单点故障(SPOF)

|

|

支持HA部署

|

支持HA部署

|

支持HA部署,高可用由zookeeper保证

|
|

多数据中心部署

|

|

支持

|

支持

|

支持

|
|

配置获取性能

|

|

unkown

|

unkown(官方说比spring快)

| |
|

配置界面

|

|

无,需要通过git操作

|

统一界面(ng编写)

|

统一界面

|

综上,ctrip applo是较好的选择方案,最终选择applo。

  • 支持不同环境(开发、测试、生产)、不同集群
  • 完善的管理系统,权限管理、发布审核、操作审计
  • SpringBoot集成友好 ,较小的迁移成本
  • 配置修改实时生效(热发布)
  • 版本发布管理

设计

搭建之前,我们需要了解一下Apollo的设计思想,不至于搭建的时候像一个无头苍蝇

基本概念

既然定位是配置中心,那么直接作用的对象就是应用(Application),应用又可以在几个维度来观察

比如运行环境(Environment),开发、测试和生产不同环境的同一个应用的配置是不一样的

比如机房,或者叫做集群(Cluster),上海机房和北京机房的同一个应用配置也是不同的

比如配置的归类,某些配置是一些共性应用都需要的,可以集中管理起来,这叫做命名空间(Namespace)

说白了这些概念都是对应用的配置做隔离或者复用

应用

  • 这个很好理解,就是实际使用配置的应用,Apollo客户端在运行时需要知道当前应用是谁,从而可以去获取对应的配置
  • 每个应用都需要有唯一的身份标识 - appId,我们认为应用身份是跟着代码走的,所以需要在代码中配置,具体信息请参见Java客户端使用指南。

环境

  • 配置对应的环境,Apollo客户端在运行时需要知道当前应用处于哪个环境,从而可以去获取应用的配置
  • 我们认为环境和代码无关,同一份代码部署在不同的环境就应该能够获取到不同环境的配置
  • 所以环境默认是通过读取机器上的配置(server.properties中的env属性)指定的,不过为了开发方便,我们也支持运行时通过System Property等指定,具体信息请参见Java客户端使用指南。

集群

  • 一个应用下不同实例的分组,比如典型的可以按照数据中心分,把上海机房的应用实例分为一个集群,把北京机房的应用实例分为另一个集群。
  • 对不同的cluster,同一个配置可以有不一样的值,如zookeeper地址。
  • 集群默认是通过读取机器上的配置(server.properties中的idc属性)指定的,不过也支持运行时通过System Property指定,具体信息请参见Java客户端使用指南。

命名空间

  • 一个应用下不同配置的分组,可以简单地把namespace类比为文件,不同类型的配置存放在不同的文件中,如数据库配置文件,rpc配置文件,应用自身的配置文件等
  • 应用可以直接读取到公共组件的配置namespace,如DAL,RPC等
  • 应用也可以通过继承公共组件的配置namespace来对公共组件的配置做调整,如DAL的初始数据库连接数

架构

V1

这是最简单的一个架构,Apollo 分为AdminService、Portal、ConfigService与Client

[图片上传失败…(image-cc9279-1621673497412)]

  • ConfigService:既然叫配置中心,这个ConfigService就是核心,它和客户端交互,有配置变更就通过长连接把最新的配置推送给客户端,考虑的推送失败的情况,客户端默认每隔5分钟就会去配置中心拉取最新的配置(客户端也可以通过在运行时指定System Property: apollo.refreshInterval来覆盖,单位为分钟),这就叫推拉结合,最大程度保证客户端的配置是最新的。
  • AdminService:看名字大概能猜到一二,这是服务于管理员的,管理员在界面上操作各种配置,配置就会通过它写到ConfigDB里面,然后ConfigService通过每秒去轮询ConfigDB获取最新的配置推送给客户端,此处是一个典型的消费-生产场景,没有引入消息队列是为了尽量减少外部依赖!
  • Portal:统一门户,就是管理员操作的前端界面,PortalDB用于保存Portal的用户权限角色等信息。

V2

V1版架构有一个问题,假设ConfigService挂了,那么客户端的配置就得不到更新,这个问题可以通过部署多个无状态的ConfigService来解决,但是引入了多个ConfigService服务发现就成为了一个新问题,客户端怎么才能知道当前有哪些ConfigService,它们的IP是多少?所以引入了注册中心Eureka!这样客户端就可以去Eureka获取服务列表!

[图片上传失败…(image-d52579-1621673497412)]

为啥选择Eureka?作者给了回答

为什么我们采用Eureka作为服务注册中心,而不是使用传统的zk、etcd呢?我大致总结了一下,有以下几方面的原因:

它提供了完整的Service Registry和Service Discovery实现首先是提供了完整的实现,并且也经受住了Netflix自己的生产环境考验,相对使用起来会比较省心。和Spring Cloud无缝集成我们的项目本身就使用了Spring Cloud和Spring Boot,同时Spring Cloud还有一套非常完善的开源代码来整合Eureka,所以使用起来非常方便。另外,Eureka还支持在我们应用自身的容器中启动,也就是说我们的应用启动完之后,既充当了Eureka的角色,同时也是服务的提供者。这样就极大的提高了服务的可用性。**这一点是我们选择Eureka而不是zk、etcd等的主要原因,为了提高配置中心的可用性和降低部署复杂度,我们需要尽可能地减少外部依赖。**Open Source最后一点是开源,由于代码是开源的,所以非常便于我们了解它的实现原理和排查问题。

V3

V2版引入了一个新问题,Eureka是只支持Java客户端的,那么.NET咋办?因为携程一些服务是.NET的,需要考虑了.NET的接入,所以增加了一个MetaServer的角色屏蔽掉,通过HTTP的方式获取服务列表,还可以增加一个网关用于负载均衡,这样只用访问网关就可以了,如下图

[图片上传失败…(image-c6011e-1621673497412)]

实际上,MetaServer和Eureka在Apollo中都集成在ConfigService中,跑在同一个JVM进程上,端口也是同一个,后面搭建的时候就需要关心到这一点!

搭建

采用docker搭建

数据库环境(5.6.5+)

docker run --name apl-mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7.24

查看下IP,此处是172.17.0.2

docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'  apl-mysql

以下操作是在容器内操作,登录MySQL,给数据库用户授权下

grant all privileges on *.* to root@"%" identified by "123456";

导入SQL

  • ConfigDB:https://github.com/ctripcorp/apollo/blob/master/scripts/sql/apolloconfigdb.sql
  • PortalDB:https://github.com/ctripcorp/apollo/blob/master/scripts/sql/apolloportaldb.sql

登录MySQL命令行,用source命令导入即可

Java环境

docker run -dit  --name apl-java --privileged centos /usr/sbin/init

查看下IP,此处是172.17.0.3

docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'  apl-java

以下是在容器内操作,安装常用软件工具

yum install -y wget unzip 

安装java环境

yum -y install java-1.8.0-openjdk java-1.8.0-openjdk-devel which
cat > /etc/profile.d/java8.sh <<EOF
export JAVA_HOME=$(dirname $(dirname $(readlink $(readlink $(which javac)))))
export PATH=\\$PATH:\\$JAVA_HOME/bin
export CLASSPATH=.:\\$JAVA_HOME/jre/lib:\\$JAVA_HOME/lib:\\$JAVA_HOME/lib/tools.jar
EOF
source /etc/profile.d/java8.sh

去github发布页下载包:
https://github.com/ctripcorp/apollo/releases,当前最新版本是1.8.1,我们需要的文件为

  • AdminService:apollo-adminservice-1.8.1-github.zip
  • ConfigService:apollo-configservice-1.8.1-github.zip
  • Portal:apollo-portal-1.8.1-github.zip

下载好解压到你喜欢的文件夹即可,然后开始配置数据库

配置ConfigService

  • 配置数据库
vi config/application-github.properties

注意要把SSL关闭,否则可能连不上MySQL

spring.datasource.url = jdbc:mysql://172.17.0.2:3306/ApolloConfigDB?characterEncoding=utf8&useSSL=false
spring.datasource.username = root
spring.datasource.password = 123456
  • 启动

启动ConfigService,执行命令脚本,主要要在解压后的当前目录下,其他几个也是

./scripts/startup.sh

启动日志文件在: /opt/logs/100003171/apollo-configservice.log,中间的数字可能不一样,以实际为准

启动成功后默认跑在8080端口,打开浏览器看一下是否能访问注册中心

提示:

由于是在容器里面,容器的端口不一定能被外部访问到,可以添加iptables DNAT规则

iptables -t nat -A DOCKER -p tcp --dport 8080 -j DNAT --to-destination 172.17.0.3:8080

这句话的意思就是把172.17.0.3:8080端口和宿主机的8080端口映射起来,这样在外部才能访问,需要删除此条规则可以将-A换成-D即可

可以看到ConfigService已经注册好了

5分钟学废携程出品配置中心阿波罗的原理与搭建

配置AdminService

  • 配置数据库,和ConfigService配置文件一致
vi config/application-github.properties
  • 启动

启动AdminService,执行命令脚本,主要要在解压后的当前目录下,其他几个也是

./scripts/startup.sh

启动成功后默认跑在8090端口,可以在Eureka看到

[图片上传失败…(image-37e5e1-1621673497411)]

配置Portal

  • 配置数据库,和ConfigService配置文件一致
vi config/application-github.properties

配置环境

注意,Portal需要配置环境,文件位置在: config/apollo-env.properties,我们就配个开发环境,指向Eureka(上面解释过ConfigService和Eureka在一个JVM进程上),其他注释掉即可

#local.meta=http://localhost:8080
dev.meta=http://172.17.0.3:8080
#fat.meta=http://fill-in-fat-meta-server:8080
#uat.meta=http://fill-in-uat-meta-server:8080
#lpt.meta=${lpt_meta}
#pro.meta=http://fill-in-pro-meta-server:8080

这里解释下这个环境是什么意思,一个Portal可以管理多套环境,此处我们设置dev.meta标识这是开发环境。

环境的标识通过以下几种方式(针对客户端而言)

Environment可以通过以下3种方式的任意一个配置:

通过Java System Property可以通过Java的System Property env来指定环境在Java程序启动脚本中,可以指定-Denv=YOUR-ENVIRONMENT如果是运行jar文件,需要注意格式是java -Denv=YOUR-ENVIRONMENT -jar xxx.jar注意key为全小写通过操作系统的System Environment还可以通过操作系统的System Environment ENV来指定注意key为全大写通过配置文件最后一个推荐的方式是通过配置文件来指定env=YOUR-ENVIRONMENT对于Mac/Linux,文件位置为 /opt/settings/server.properties对于Windows,文件位置为C:\\opt\\settings\\server.properties

文件内容形如:

env=DEV

目前,env支持以下几个值(大小写不敏感):

DEVDevelopment environmentFATFeature Acceptance Test environmentUATUser Acceptance Test environmentPROProduction environment

启动

启动AdminService,执行命令脚本,主要要在解压后的当前目录下,其他几个也是

./scripts/startup.sh

启动成功后默认跑在8070端口,同样访问不了指定下DNAT规则

iptables -t nat -A DOCKER -p tcp --dport 8070 -j DNAT --to-destination 172.17.0.3:8070

访问http://{虚拟机IP}:8070,默认登录用户名为apollo,密码为admin

5分钟学废携程出品配置中心阿波罗的原理与搭建

客户端准备

此处以Java客户端为例,需要引入Apollo Client依赖(以Maven构建)

<dependency>
    <groupId>com.ctrip.framework.apollo</groupId>
    <artifactId>apollo-client</artifactId>
    <version>1.1.0</version>
</dependency>`
  • 指定app.id,这是这个应用的唯一标识,不可重复
  • 指定apollo.meta,指定获取元数据的地方,此处即为MetaServer:http://172.17.0.3:8080

这两个指定的配置文件为/META-INF/app.properties

一个最简单的Apollo客户端如下

[图片上传失败…(image-bf5cde-1621673497410)]

文末有代码清单

测试

部署项目

将项目打包并执行,注意设置环境为DEV

mkdir -p /opt/settings/
echo 'env=DEV' > /opt/settings/server.properties

然后访问一下

curl 'http://127.0.0.1:9000/apollo/getConfig'

值默认为default,下面我们通过Apollo,看这个值会不会动态改变

新增一个应用

登录Portal,新增一个应用,注意AppId要和配置的一样

5分钟学废携程出品配置中心阿波罗的原理与搭建

点击提交后,进入刚才新建的应用,有一个默认的application的命名空间,然后点击右边新增配置,新增一个

[图片上传失败…(image-dbd4a8-1621673497410)]

点击提交后再点击发布

5分钟学废携程出品配置中心阿波罗的原理与搭建

再访问一下

curl 'http://127.0.0.1:9000/apollo/getConfig'

如果返回的是测试变量说明动态更改成功!

再看看SpringBoot的日志

5分钟学废携程出品配置中心阿波罗的原理与搭建

也打印出了相关提示

代码清单

ApolloController

@RestController
public class ApolloController {
    //冒号后面的是默认值
    @Value("${configValue:default}")
    private String configValue;

    @RequestMapping("/apollo/getConfig")
    public String getConfig() {
        return configValue;
    }
}

SpringBootApolloClientApplication

@SpringBootApplication
//开启apollo配置
@EnableApolloConfig
public class SpringBootApolloClientApplication {

    private static Logger logger = LoggerFactory.getLogger(SpringBootApolloClientApplication.class);

    public static void main(String[] args) {
        SpringApplication.run(SpringBootApolloClientApplication.class, args);
        logger.info("=============================="+ SpringBootApolloClientApplication.class.getSimpleName()+" started==============================");
    }

}

app.properties

# 应用的唯一标识,后面创建工程需要用到
app.id=apollo-demo
apollo.meta=http://172.17.0.3:8080

application.yml

server:
  port: 9000

spring:
  application:
    name: springboot-apollo-client

pom.xml

<?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>

    <groupId>com.scriptwang</groupId>
    <artifactId>springboot-apollo-client</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!--spring boot parent 最小依赖(parent)-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.1.RELEASE</version>
    </parent>

    <dependencies>
        <!--最小依赖(Spring MVC Tomcat等)-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

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

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

参考

  • https://www.cnblogs.com/xiaoqi/p/configserver-compair.html
  • https://www.bookstack.cn/read/apollo-1.7-zh/cc8342e164e6c09c.md
  • https://cloud.tencent.com/developer/article/1063232
  • https://nobodyiam.com/2016/07/09/introduction-to-apollo/
  • https://www.infoq.cn/article/ctrip-apollo-configuration-center-architecture

以上是关于5分钟学废携程出品配置中心阿波罗的原理与搭建的主要内容,如果未能解决你的问题,请参考以下文章

CentOS 7 搭建基于携程Apollo(阿波罗)配置中心单机模式

阿波罗配置中心实战

Ubuntu 16.04下搭建基于携程Apollo(阿波罗)配置中心单机模式

携程Apollo(阿波罗)配置中心用户管理和部门管理

携程Apollo(阿波罗)配置中心用户管理和部门管理

携程Apollo(阿波罗)配置中心把现有项目的配置文件迁移到Apollo