Skip to content

配置中心选型 ​

由于网上存在很多这种选型的文章,贴一下文章链接:配置中心选型的理解,分布式配置中心。 但是别人的场景与我们的场景并不一致,还是要独立思考一下,文章内容可以用来参考。

需求解析 ​

本质上的核心需求是配置的内容。由于在集群中,服务可能会漂流到其他节点,这个时候,如果没有分布式存储,那么就需要每个节点都有一份冗余的配置,这种方式对于运维人员来说是个灾难,手工维护不同节点不同版本的配置文件。由此引入了配置中心,要求配置中心要有基本的配置发布,配置管理,版本管理功能,还要支持集群,client支持目前我们使用的golang亦或是HTTP接口,至于认证和鉴权则不是必须的。

再看其他方面的要求,由于本身管控面的服务并不庞杂,因此配置中心也要尽量轻、快,最好原生支持容器集群,部署简单等。

如果还额外的支持服务发现等可能用到的功能,那就更好了,避免因为缺失该功能而要引入新的组件来单独实现这个功能。

选择 ​

综上所述,Nacos可能更合适一些,从对比来看,nacos在基本功能上与Apollo一致,但部署相对简单,性能较好,还支持服务发现和健康监测等,并且官网也有原生容器。

当然再好也需要手工实验验证一下基本功能的使用。

果然还是得手工实验一下,看似nacos比较契合场景,但是nacos文档不全,部署失败。反而apollo有着丰富的文档,并且单机、多节点部署成功。

nacos手工实验 ​

官网的手册推荐v2.1.1版本,因此基于该版本来进行手工实验。 nacos集群模式和单机模式手工实验失败,总是提示错误,v2.2.1版本也是提示错误。 文档不足

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'memoryMonitor' defined in URL [jar:file:/home/nacos/target/nacos-server.jar!/BOOT-INF/lib/nacos-config-2.1.1.jar!/com/alibaba/nacos/config/server/monitor/MemoryMonitor.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'asyncNotifyService': Unsatisfied dependency expressed through field 'dumpService'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'externalDumpService': Invocation of init method failed; nested exception is ErrCode:500, ErrMsg:Nacos Server did not start because dumpservice bean construction failure :No DataSource set

怀疑是mariadb版本(10.6.14-MariaDB-1:10.6.14+maria~ubu2004、wsrep_26.22)过高。

Apollo手工实验 ​

目前看来,apollo有着完整详细的安装部署流程说明。 相关文档:

  1. 分布式部署指南:https://www.apolloconfig.com/#/zh/deployment/distributed-deployment-guide
  2. 其他客户端接入指南:https://www.apolloconfig.com/#/zh/usage/other-language-client-user-guide

通过github release tag页面中选择已验证的版本--2.1.0进行手工实验。 需要的镜像有apollo-adminservice、apollo-configservice、apollo-portal。

均使用mariadb galera cluster作为后端的存储数据库。

执行初始化数据库的sql时需要修改eureka url(一套环境中的所有configservice节点信息)和部门信息,config-service.cache.enabled(控制是否缓存配置,数据库宕机依然可以获取配置,会增大内存消耗)。

测试apollo docker容器无法访问自身宿主机ip的mariadb server,需要验证查找原因,与iptables防火墙有关,执行iptables -I INPUT 1 -p tcp --dport 13006 -j ACCEPT。

需要开放的端口:8080、8090、8070

apollo-portal日志提示连接ip地址失败,访问了其它容器的地址,原因是:portal需要检查admin service的服务状态,但是在另外的机器上没法adminservice所在的容器。

单环境手工部署:

shell
# deploy on 172.20.16.234
docker run -d -p 0.0.0.0:8080:8080 -e SPRING_DATASOURCE_URL="jdbc:mysql://172.20.16.234:13006/ApolloConfigDB?characterEncoding=utf8" -e SPRING_DATASOURCE_USERNAME=root -e SPRING_DATASOURCE_PASSWORD=zstack.mysql.password -e EUREKA_INSTANCE_IP_ADDRESS=172.20.16.234 -v /tmp/apollo/logs/:/opt/logs/ --name apollo-configservice 172.20.16.139:5000/apollo-configservice:2.1.0

# deploy on 172.20.16.234
docker run -d -p 0.0.0.0:8090:8090 -e SPRING_DATASOURCE_URL="jdbc:mysql://172.20.16.234:13006/ApolloConfigDB?characterEncoding=utf8" -e SPRING_DATASOURCE_USERNAME=root -e SPRING_DATASOURCE_PASSWORD=zstack.mysql.password -e EUREKA_INSTANCE_IP_ADDRESS=172.20.16.234 -v /tmp/apollo/logs/:/opt/logs/ --name apollo-adminservice 172.20.16.139:5000/apollo-adminservice:2.1.0

# deploy on 172.20.16.139
docker run -d -p 0.0.0.0:8070:8070 -e SPRING_DATASOURCE_URL="jdbc:mysql://172.20.16.234:13006/ApolloPortalDB?characterEncoding=utf8" -e SPRING_DATASOURCE_USERNAME=root -e SPRING_DATASOURCE_PASSWORD=zstack.mysql.password -e APOLLO_PORTAL_ENVS=pro -e PRO_META=http://172.20.16.234:8080 -e EUREKA_INSTANCE_IP_ADDRESS=172.20.16.234 -v /tmp/apollo/logs/:/opt/logs/ --name apollo-portal 172.20.16.139:5000/apollo-portal:2.1.0

访问htpp://172.20.16.234:8070,使用用户密码(apollo/admin)登录。创建应用后写入配置并发布。 使用以下http请求来测试获取配置内容。

http
# url format: {config_server_url}/configfiles/json/{appId}/{clusterName}/{namespaceName}?ip={clientIp}
GET http://172.20.16.234:8080/configfiles/json/abcdefg/default/application?ip=172.21.1.129  
Content-Type: application/json

两套configservice+adminservice,单个portal部署实验(也适用三节点均部署configservice+adminservice,其中一个节点部署portal):

shell
# deploy on 172.20.16.234
docker run -d -p 0.0.0.0:8080:8080 -e SPRING_DATASOURCE_URL="jdbc:mysql://172.20.16.234:13006/ApolloConfigDB?characterEncoding=utf8" -e SPRING_DATASOURCE_USERNAME=root -e SPRING_DATASOURCE_PASSWORD=zstack.mysql.password -e EUREKA_INSTANCE_IP_ADDRESS=172.20.16.234 -v /tmp/apollo/logs/:/opt/logs/ --name apollo-configservice 172.20.16.139:5000/apollo-configservice:2.1.0

docker run -d -p 0.0.0.0:8090:8090 -e SPRING_DATASOURCE_URL="jdbc:mysql://172.20.16.234:13006/ApolloConfigDB?characterEncoding=utf8" -e SPRING_DATASOURCE_USERNAME=root -e SPRING_DATASOURCE_PASSWORD=zstack.mysql.password -e EUREKA_INSTANCE_IP_ADDRESS=172.20.16.234 -v /tmp/apollo/logs/:/opt/logs/ --name apollo-adminservice 172.20.16.139:5000/apollo-adminservice:2.1.0

# deploy on 172.31.10.242
docker run -d -p 0.0.0.0:8080:8080 -e SPRING_DATASOURCE_URL="jdbc:mysql://172.20.16.234:13006/ApolloConfigDB?characterEncoding=utf8" -e SPRING_DATASOURCE_USERNAME=root -e SPRING_DATASOURCE_PASSWORD=zstack.mysql.password -e EUREKA_INSTANCE_IP_ADDRESS=172.31.10.242 -v /tmp/apollo/logs/:/opt/logs/ --name apollo-configservice 172.20.16.139:5000/apollo-configservice:2.1.0

docker run -d -p 0.0.0.0:8090:8090 -e SPRING_DATASOURCE_URL="jdbc:mysql://172.20.16.234:13006/ApolloConfigDB?characterEncoding=utf8" -e SPRING_DATASOURCE_USERNAME=root -e SPRING_DATASOURCE_PASSWORD=zstack.mysql.password -e EUREKA_INSTANCE_IP_ADDRESS=172.31.10.242 -v /tmp/apollo/logs/:/opt/logs/ --name apollo-adminservice 172.20.16.139:5000/apollo-adminservice:2.1.0


# deploy on 172.20.16.139

# docker run -d -p 0.0.0.0:8080:8080 -e SPRING_DATASOURCE_URL="jdbc:mysql://172.20.16.234:13006/ApolloConfigDB?characterEncoding=utf8" -e SPRING_DATASOURCE_USERNAME=root -e SPRING_DATASOURCE_PASSWORD=zstack.mysql.password -e EUREKA_INSTANCE_IP_ADDRESS=172.20.16.139 -v /tmp/apollo/logs/:/opt/logs/ --name apollo-configservice 172.20.16.139:5000/apollo-configservice:2.1.0

# docker run -d -p 0.0.0.0:8090:8090 -e SPRING_DATASOURCE_URL="jdbc:mysql://172.20.16.234:13006/ApolloConfigDB?characterEncoding=utf8" -e SPRING_DATASOURCE_USERNAME=root -e SPRING_DATASOURCE_PASSWORD=zstack.mysql.password -e EUREKA_INSTANCE_IP_ADDRESS=172.20.16.139 -v /tmp/apollo/logs/:/opt/logs/ --name apollo-adminservice 172.20.16.139:5000/apollo-adminservice:2.1.0

docker run -d -p 0.0.0.0:8070:8070 -e SPRING_DATASOURCE_URL="jdbc:mysql://172.20.16.234:13006/ApolloPortalDB?characterEncoding=utf8" -e SPRING_DATASOURCE_USERNAME=root -e SPRING_DATASOURCE_PASSWORD=zstack.mysql.password -e APOLLO_PORTAL_ENVS=pro -e PRO_META=http://172.20.16.234:8080,http://172.31.10.242:8080  -v /tmp/apollo/logs/:/opt/logs/ --name apollo-portal 172.20.16.139:5000/apollo-portal:2.1.0

登录portal所在节点,查看系统信息

修改并新增配置,使用api分别查看配置内容是否一致:

http
####  
GET http://172.31.10.242:8080/configfiles/json/abcdefg/default/application?ip=172.21.1.129  
Content-Type: application/json

####  
GET http://172.20.16.234:8080/configfiles/json/abcdefg/default/application?ip=172.21.1.129  
Content-Type: application/json

Questions ​

  • 处理eureka提示的自保护模式已关闭?Eureka的地址修改为负载均衡的地址。
  • 但是高可用如何切换呢?需要负载均衡服务。
  • 如何集成进服务?原生代码改造?or 服务启动时获取配置内容后写入配置文件?建议后者,可以快速兼容,后续确认全部切换到配置中心后再改造服务适配配置中心。
  • apollo支持同时管控多套环境,以DEV,FAT,UAT,PRO区分,每种环境需要独立的db,即每种环境最少需要一个db、一个configservice、一个adminservice,所有类型的环境可以部署共用一个portal,也分别部署使用各自的portal。