赞
踩
上图简要描述了Apollo的总体设计,从下往上看:
上图简要描述了Apollo客户端的实现原理:
1)、客户端和服务端保持了一个长连接,从而能第一时间获得配置更新的推送(通过Http Long Polling实现)
2)、客户端还会定时从Apollo配置中心服务端拉取应用的最新配置
apollo.refreshInterval
来覆盖,单位为分钟3)、客户端从Apollo配置中心服务端获取到应用的最新配置后,会保存在内存中
4)、客户端会把从服务端获取到的配置在本地文件系统缓存一份
在遇到服务不可用,或网络不通的时候,依然能从本地恢复配置
Mac/Linux:/opt/data/{appId}/config-cache
Windows:C:\opt\data{appId}\config-cache
文件名格式如下:
{appId}+{cluster}+{namespace}.properties
5)、应用程序可以从Apollo客户端获取最新的配置、订阅配置更新通知
详细查看官方文档Apollo配置中心设计
配置项统一存储在ApolloPortalDB.ServerConfig表中,也可以在管理员工具中的系统参数页面进行配置,无特殊说明则修改完一分钟实时生效
1)、apollo.portal.envs
(可支持的环境列表)
默认值是dev,如果portal需要管理多个环境的话,以逗号分隔即可(大小写不敏感),如:
DEV,FAT,UAT,PRO
修改完需要重启生效
注1:一套Portal可以管理多个环境,但是每个环境都需要独立部署一套Config Service、Admin Service和ApolloConfigDB
注2:只在数据库添加环境是不起作用的,还需要为apollo-portal添加新增环境对应的meta server地址
2)、organizations(部门列表)
Apollo中新建的项目都需要选择部门,所以需要在这里配置可选的部门信息
[{"orgId":"HAND","orgName":"技术1部"},{"orgId":"HAND","orgName":"技术2部"},{"orgId":"HAND","orgName":"技术3部"}]
3)、superAdmin(Portal超级管理员)
超级管理员拥有所有权限,需要谨慎设置
如果没有接入自己的SSO系统的话,可以先暂时使用默认值apollo(默认用户)。等接入后,修改为实际使用的账号,多个账号以英文逗号分隔,
4)、consumer.token.salt
(consumer token salt)
如果会使用开放平台API的话,可以设置一个token salt。如果不使用,可以忽略
5)、wiki.address
portal上“帮助”链接的地址,默认是Apollo github的wiki首页,可自行设置
6)、admin.createPrivateNamespace.switch
是否允许项目管理员创建private namespace。设置为true
允许创建,设置为false
则项目管理员在页面上看不到创建private namespace的选项
7)、configView.memberOnly.envs
只对项目成员显示配置信息的环境列表,多个env以英文逗号分隔
对设定了只对项目成员显示配置信息的环境,只有该项目的管理员或拥有该namespace的编辑或发布权限的用户才能看到该私有namespace的配置信息和发布历史。公共namespace始终对所有用户可见
配置项统一存储在ApolloConfigDB.ServerConfig表中,需要注意每个环境的ApolloConfigDB.ServerConfig都需要单独配置,修改完一分钟实时生效
1)、eureka.service.url
(Eureka服务Url)
不管是apollo-configservice还是apollo-adminservice都需要向eureka服务注册,所以需要配置eureka服务地址
按照Apollo的实现,apollo-configservice本身就是一个eureka服务,所以只需要填入apollo-configservice的地址即可,如有多个,用逗号分隔
2)、namespace.lock.switch
(一次发布只能有一个人修改开关,用于发布审核)
这是一个功能开关,如果配置为true的话,那么一次配置发布只能是一个人修改,另一个发布(生产环境建议开启此选项)
3)、config-service.cache.enabled
(是否开启配置缓存)
这是一个功能开关,如果配置为true的话,config service会缓存加载过的配置信息,从而加快后续配置获取性能
默认为false,开启前请先评估总配置大小并调整config service内存配置
4)、item.key.length.limit
(配置项 key 最大长度限制)
默认配置是128
5)、item.value.length.limit
(配置项 value 最大长度限制)
默认配置是20000
1)、修改apollo-configservice工程下com.ctrip.framework.apollo.configservice包下的ConfigServiceApplication,把@EnableEurekaServer改为@EnableEurekaClient并重新打包
@EnableEurekaClient @EnableAspectJAutoProxy @EnableAutoConfiguration // (exclude = EurekaClientConfigBean.class) @Configuration @EnableTransactionManagement @PropertySource(value = {"classpath:configservice.properties"}) @ComponentScan(basePackageClasses = {ApolloCommonConfig.class, ApolloBizConfig.class, ConfigServiceApplication.class, ApolloMetaServiceConfig.class}) public class ConfigServiceApplication { public static void main(String[] args) throws Exception { SpringApplication.run(ConfigServiceApplication.class, args); } }
2)、修改ApolloConfigDB.ServerConfig表中的eureka.service.url
,指向自己的Eureka地址
效果如下图:
需要注意的是更改Eureka地址只需要改ApolloConfigDB.ServerConfig表中的eureka.service.url
即可,不需要修改meta server地址
默认情况下,meta service和config service是部署在同一个JVM进程,所以meta service的地址就是config service的地址,修改Eureka地址时不需要修改meta server地址
Apollo中存储的一些比较重要的配置信息,比如密码之类的敏感配置,我们希望将配置加密存储,保证安全性。Apollo框架本身没有提供数据加密的功能,如果想要实现数据加密的功能有两种方式,可以基于第三方的框架来对数据进行解密
jasypt-spring-boot是一个基于Spring Boot开发的框架,可以将properties中加密的内容自动解密,在Apollo中也可以借助于jasypt-spring-boot这个框架来实现数据的加解密操作
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>1.16</version>
</dependency>
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-client</artifactId>
<version>1.4.0</version>
</dependency>
spring.application.name=hello-service
app.id=hello-service
apollo.meta=http://IP:Port
apollo.cluster=default
apollo.bootstrap.enabled=true
apollo.bootstrap.namespaces=application,common
jasypt.encryptor.password=handhand
创建一个加密的工具类,用于加密配置:
public class EncryptUtil { /** * 制表符、空格、换行符 PATTERN */ private static Pattern BLANK_PATTERN = Pattern.compile("\\s*|\t|\r|\n"); /** * 加密Key */ private static String PASSWORD = "handhand"; /** * 加密算法 */ private static String ALGORITHM = "PBEWithMD5AndDES"; public static Map<String, String> getEncryptedParams(String input) { //输出流 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(1024); PrintStream cacheStream = new PrintStream(byteArrayOutputStream); //更换数据输出位置 System.setOut(cacheStream); //加密参数组装 String[] args = {"input=" + input, "password=" + PASSWORD, "algorithm=" + ALGORITHM}; JasyptPBEStringEncryptionCLI.main(args); //执行加密后的输出 String message = byteArrayOutputStream.toString(); String str = replaceBlank(message); int index = str.lastIndexOf("-"); //返回加密后的数据 Map<String, String> result = new HashMap<>(); result.put("input", str.substring(index + 1)); result.put("password", PASSWORD); return result; } /** * 替换制表符、空格、换行符 * * @param str * @return */ private static String replaceBlank(String str) { String dest = ""; if (!StringUtils.isEmpty(str)) { Matcher matcher = BLANK_PATTERN.matcher(str); dest = matcher.replaceAll(""); } return dest; } public static void main(String[] args) { System.out.println(getEncryptedParams("8081")); } }
这里执行main方法,可以得到如下输出:
{input=XcWwvgIkR0tNAGGxpXwDPQ==, password=handhand}
input就是8081加密之后的内容,将input的值复制存储到Apollo中,存储的格式需要按照一定的规则才行:
需要将加密的内容用ENC包起来,这样jasypt才会去解密这个值
jasypt整合Apollo也是有一些不足的地方,比如在配置中心修改值后,项目中的值不会刷新
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。