配置的基本概念
应用程序在启动和运行的时候往往需要读取一些配置信息,配置基本上伴随着应用程序的整个生命周期,比如:数据库连接参数、启动参数等。
这些配置往往都不是在代码中硬编码的,一般情况是在外部有配置文件,程序的运行的过程中,进行读取配置。例如:一个程序要连接数据库,但是用户名和密码不能在编写代码的时候写死,因为客户的用户名和密码得他们自己来确定。
了解如下情况,知道配置中心的重要性:
- 一个大型的项目,他的配置文件太多了,不利于管理。甚至说同一个模块都有好几种配置,例如:User模块在不同的阶段有不同的配置,开发阶段、测试阶段、正式上线阶段等。
- 配置太多,又需要经常替换。例如:假设淘宝的某个数据库有一天宕机了,需要更改配置,连接另一个数据库。或者例如:产品升级,配置信息改变等。
- 更换配置的时候有时需要重启应用程序。越大型的项目重启会浪费大量的时间,如果银行系统只为了一点点配置就要重启系统,是得不偿失的。
配置中心
当系统从一个单体应用,被拆分成分布式系统上一个个服务节点后,配置文件也必须跟着迁移(分割),这样配置就分散了,不仅如此,分散中还包含着冗余,如下图:
可以看到每个服务都有一个配置文件,服务越多,配置文件越多,而且这些配置文件里面,往往会有很多重复的信息,在更改一个配置文件的时候需要同步更改很多的配置文件。
配置中心概念
配置中心是整个微服务基础架构体系中的一个组件,配置中心将配置从应用中剥离出来,统一管理,解决了配置的动态变更、持久化、运维成本等问题。配置中心就是一种统一管理各种应用配置的基础服务组件。
总得来说,配置中心就是一种统一管理各种应用配置的基础服务组件。
配置中心的功能:
- 配置项容易读取和修改
- 添加新配置简单直接
- 支持对配置的修改的检视以把控风险
- 可以查看配置修改的历史记录
- 不同部署环境支持隔离
Apollo
Apollo简介
Apollo(阿波罗)是一款可靠的分布式配置管理中心,诞生于携程框架研发部,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。
服务端基于Spring Boot和Spring Cloud开发,打包后可以直接运行,不需要额外安装Tomcat等应用容器。
Java客户端不依赖任何框架,能够运行于所有Java运行时环境,同时对Spring/Spring Boot环境也有较好的支持。
.Net客户端不依赖任何框架,能够运行于所有.Net运行时环境。
为什么使用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对外部依赖尽可能地少- 目前唯一的外部依赖是MySQL,所以部署非常简单,只要安装好Java和MySQL就可以让Apollo跑起来- Apollo还提供了打包脚本,一键就可以生成所有需要的安装包,并且支持自定义运行时参数
基础模型
如下即是Apollo的基础模型:
- 用户在配置中心对配置进行修改并发布
- 配置中心通知Apollo客户端有配置更新
- Apollo客户端从配置中心拉取最新的配置、更新本地配置并通知到应用
Apollo快速启动
首先下载Apollo
如果想要最新版可以去GitHub上面拉取他们的项目,手动进行打包,或者根据官方文档步骤进行操作:官方文档快速启动
我准备了Apollo的jar包,放在网盘里面了:链接 提取码:ppww
下载解压就行了。
在数据库中执行sql文件
解压安装包,在sql文件夹中找到两个文件
然后在自己的数据库中执行这两个sql文件,执行成功会创建两个数据库,和诺干表
在cmd中执行txt文件的内容
在文件所在位置输入cmd,打开窗口,依次输入right.txt中的类容(启动jar包)
实际上就是用 Java -jar xxx 的命令启动这几个个spring boot项目
txt中一共有三行,每一行执行之后一定要等待加载完毕之后,再执行后面的一个
注意:要更改自己数据库信息,用户名密码等
访问8070端口,Apollo启动成功
默认账号:apollo
默认密码:admin
Apollo工作原理
这个是Apollo的工作流程图,看着复杂实际上并不难。
Apollo的总体设计,从下往上看:
- Config Service提供配置的读取、推送等功能,服务对象是Apollo客户端,就是你自己写的代码,你自己的项目就从这里拿到配置信息
- Admin Service提供配置的修改、发布等功能,服务对象是Apollo Portal(管理界面),就是快速启动的那个操作界面
- Eureka提供服务注册和发现,为了简单起见,目前Eureka在部署时和Config Service是在一个JVM进程中的,他俩就是在同一个项目中(快速启动的三个服务,就是三个boot项目)
- 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启动后,Config/Admin Service会自动注册到Eureka服务注册中心,并定期发送保活心跳。
- Apollo Client和Portal管理端通过配置的Meta Server的域名地址经由Software Load Balancer(软件负载均衡器)进行负载均衡后分配到某一个Meta Server
- Meta Server从Eureka获取Config Service和Admin Service的服务信息,相当于是一个Eureka Client
- Meta Server获取Config Service和Admin Service(IP+Port)失败后会进行重试
- 获取到正确的Config Service和Admin Service的服务信息后,Apollo Client通过Config Service为应用提供配置获取、实时更新等功能;Apollo Portal管理端通过Admin Service提供配置新增、修改、发布等功能
上面的非人话如果听不懂,可以看看下面这个简单易懂的图。
使用Apollo需要的核心概念
这些是使用Apollo配置中心需要掌握的一些概念,掌握这些之后可以针对不同的环境进行不同的配置,说白了就是用以下的东西进行配置的逻辑隔离。
application (应用)
Apollo是以应用(项目)为单位的,一个应用就是一个独立的个体,这个个体很好理解,就是实际使用配置的应用,Apollo客户端在运行时需要知道当前应用是谁,从而可以去获取对应的配置。
关键字:appId
例如:我这里有两个应用,不同应用点进去配置肯定是不同的
environment (环境)
配置对应的环境,Apollo客户端在运行时需要知道当前应用处于哪个环境,从而可以去获取相应的配置,一个应用可能有多个环境,每个环境的配置可能有些地方不一样。
关键字:env
cluster (集群)
一个应用下不同实例的分组,比如典型的可以按照数据中心分,把上海机房的应用实例分为一个集群,把北京机房的应用实例分为另一个集群。
关键字:cluster
namespace (命名空间)
一个应用下不同配置的分组,可以简单地把namespace类比为文件,不同类型的配置存放在不同的文件中,如数据库配置文件,RPC配置文件,应用自身的配置文件等
关键字:namespaces
重点是一个应用下,意思是一个应用可以有多个命名空间,说白了就是填写配置的地方,没什么高端的。就是让你不把所有配置写在同一块区域,到时候自己找的时候也麻烦。
例如:MySQL的配置用一个空间,redis的配置又用另一个,你可以随意分配
namespace另一个作用
命名空间可以分为公共的和私有的,私有的就是只能你这个应用看到,别的应用看不到,公共的就是所有的应用都能看到你这个空间里面的配置,并且所有的应用都可以引用这个空间(就是将空间弄到自己的应用中来)。
我们往往会创建一个应用,专门用来设置公共的配置,然后其他应用继承这个空间就行了,这样做的好处是:各个应用相同的配置就不需要重复配置了,也可以统一更改
使用Apollo客户端
导入客户端依赖包
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-client</artifactId>
<version>1.1.0</version>
</dependency>
配置启动参数:
-Dapp.id=account-service -Denv=DEV -Ddev_meta=http://localhost:8080
直接调用函数:
public class getConfigTest {
public static void main(String[] args) {
getConfigQuickStart();
getConfigFromNameSpace();
}
//获取默认命名空间的配置(application)
public static void getConfigQuickStart(){
Config appConfig = ConfigService.getAppConfig();
String property = appConfig.getProperty("sms.enable", null);
System.out.println("sms.enable的值是:"+property);
}
//获取自定义命名空间的参数
public static void getConfigFromNameSpace(){
Config config = ConfigService.getConfig("micro_service.test-namespace");
String port = config.getProperty("port", null);
System.out.println(port);
}
}
运行结果比对:
Springboot集成Apollo
springboot执行web项目的时候,如果使用了Apollo配置中心,会先去配置中心中读取配置,再启动的。什么意思?例如:就是你把启动的端口号放在配置中心中,然后spring会先读到这个端口号,再启动项目。
所以,springboot项目里面只需要配置Apollo的一些信息就行了:
- appId(读取哪个应用中的配置)
- namespace(应用中的哪些命名空间)
- meta-server(meta的地址,在哪个ip和端口读取配置)
- 环境(读取哪个环境的配置:开发、测试、生产)- 在Java程序启动脚本中,可以指定-Denv=YOUR-ENVIRONMENT- 还可以通过操作系统的System Environment ENV来指定- 通过配置文件来指定env=YOUR-ENVIRONMENT;(windows C:\opt\settings\server.properties)(linux /opt/settings/server.properties)
- 集群(哪个集群的配制)- 在Java程序启动脚本中,可以指定-Dapollo.cluster=SomeCluster- 过Spring Boot的配置文件,apollo.cluster=SomeCluster- 可以在server.properties配置文件中指定idc=xxx
1.导入Apollo的依赖
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-client</artifactId>
<version>1.1.0</version>
</dependency>
2.在application.properties里面配置
配置appid
在指定的appid下面拉取相应的配置
app.id=account-service
开启启用apollo,和配置namespace
namespace之间用逗号隔开
apollo.bootstrap.enabled = true
apollo.bootstrap.namespaces = application,micro_service.test-namespace
3.配置meta-Server
第一种:通过Java System Property的apollo.meta:
-Dapollo.meta=http://localhost:8080
第二种:在在resources目录下新建apollo-env.properties文件
dev.meta=http://localhost:8080
4.指定环境和集群
通过Java System Property的env来指定环境:
-Denv=DEV
通过Java System Property的apollo.cluste来指定集群:
-Dapollo.cluster=DEFAULT
-Denv=DEV -Dapollo.cluster=DEFAULT
5.使用@value注解来读取配置
@RestController
public class TestController {
@Value("${port}")
private String port;
@RequestMapping("test")
public String test(){
return port;
}
}
可以看到在配置中心中的值是:
然后我们测试拿到的值是:
成功
版权归原作者 black_pp 所有, 如有侵权,请联系我们删除。