使用
数据库初始化
apolloconfigdb.sql
apolloportaldb.sql
构建
先配置JDK环境变量,再配置MAVEN环境变量,MAVEN_HOME和PATH。build.bat中修改数据库地址和用户名密码,构建之后会创建jar包。通过以下命令运行
java -jar xxx.jar
运行顺序为 apollo-configservice > apollo-adminservice > apollo-portal。
将三个jar包放到一个文件夹,使用一个脚本来统一启动
@echo off
start cmd /c "java -jar apollo-configservice-2.0.1-SNAPSHOT.jar"
start cmd /c "java -jar apollo-adminservice-2.0.1-SNAPSHOT.jar"
start cmd /c "java -jar apollo-portal-2.0.1-SNAPSHOT.jar"
pause // 防止运行完毕后直接关闭界面
http://localhost:8070/登录后台 apollo/admin
客户端使用
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-client</artifactId>
<version>2.0.1</version>
</dependency>
在后台页面应用中开启访问秘钥
app:
id: '001' # 注意,不加引号会被转换成数字类型1
apollo:
meta: http://localhost:8080
bootstrap:
enabled: true
namespaces: application.properties
access-key:
secret: 57d90e6bf80647788deaa0d993af536f
@Data
@Component
public class UserProperties {
@Value("${myuser.name:}")
private String name;
}
@RestController
@RequestMapping("/test")
@Api(tags = "测试接口")
@Slf4j
public class TestController {
@Autowired
private UserProperties userProperties;
@GetMapping("/testRefreshQuery")
@ApiOperation("测试刷新对象查询")
public String testRefreshQuery() {
return userProperties.getName();
}
}
页面修改发布之后会自动刷新最新值
原理
请求配置
- ApolloApplicationContextInitializer通过namespace来请求服务器
- ConfigService具体来发送请求,通过metaServer和appId及secret
http://localhost:8080/configs/{appId}/{cluster}/{namespace}
客户端使用到了Guice这个IOC框架。
自动刷新
- ConfigService通过RemoteConfigRepository来发送请求
- 它内部会创建一个RemoteConfigLongPollService对象
- 每隔2秒发送一个长轮训请求,默认60秒
- ApolloAutoConfiguration通过ConfigPropertySourcesProcessor自动配置了AutoUpdateConfigChangeListener,ApolloAnnotationProcessor和SpringValueProcessor,PropertySourcesProcessor等Bean。
- SpringValueProcessor会查找所有Bean中包含@Value注解的属性和方法,注册到SpringValueRegistry中,这是一个单例对象。
- ApolloAnnotationProcessor会查找@ApolloConfig注解和@ApolloConfigChangeListener注解
- AutoUpdateConfigChangeListener是一个ConfigChangeListener对象,也监听了Spring中的ApolloConfigChangeEvent事件
- PropertySourcesProcessor中向Config实现DefaultConfig中添加了ConfigChangeListener对象,逻辑为发送Spring的ApolloConfigChangeEvent事件,这样流程就连接起来了。
总结起来就是:RemoteConfigLongPollService发送长轮训请求,如果发现有变更,触发RepositoryChangeListener的onRepositoryChange()方法,每一个DefaultConfig都是一个RepositoryChangeListener监听器。DefaultConfig又会触发它内部的ConfigChangeListener监听器列表,上面第8步就是添加的这个,发送Spring的ApolloConfigChangeEvent事件,AutoUpdateConfigChangeListener就会将SpringValueRegistry(@Value注解)中的属性通过反射更新。
- 对于@Value的属性,Apollo可以直接支持
- 对于@ConfigurationProperties修饰的属性Bean,需要配合SpringCloud的属性自动刷新机制,发送EnvironmentChangeEvent事件或者使用@RefreshScope注解及RefreshScope的refresh()方法
@Data
@Component
@ConfigurationProperties(prefix = "myuser")
public class UserProperties {
private String name;
}
@Component
public class ApolloConfig implements ApplicationContextAware {
private ApplicationContext context;
@ApolloConfigChangeListener
public void configRefresh(ConfigChangeEvent event) {
this.context.publishEvent(new EnvironmentChangeEvent(this.context, event.changedKeys()));
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
}
}
http://localhost:8080/notifications/v2?
服务端NotificationControllerV2中使用了DeferredResult这种异步方式,一直hold住60秒,ReleaseMessageScanner每隔1秒回扫描有变化的配置,并通知NotificationControllerV2。