Apollo还是存在一些坑的,要自己一一踩过之后才能知道怎么处理。最近在配置文件中想把Apollo关闭,试了很多情况,都没成功。官网上只说明了如何集成Apollo的方式,并没有介绍关闭Apollo的配置方式。现在把这些情况和解决方案记录下来,免得以后继续犯错。
测试环境
-
bootstrap.properties/yml
apollo.bootstrap.enabled=true/false
-
application.properties/yml
apollo: bootstrap: enabled: true/false
-
启动类
@EnableTransactionManagement @SpringBootApplication @EnableEurekaClient @EnableApolloConfig//是否注释 @Slf4j public class AppApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(FormEngineApplication.class, args); ConfigurableEnvironment environment = context.getEnvironment(); String apolloEnable = environment.getProperty("apollo.bootstrap.enabled"); System.out.println(apolloEnable); } @Value("${testname:}") private String testName; @Bean public TestBean testBean() { if (!StringUtils.isEmpty(testName)) { System.out.println("应用启动前能读取到Apollo配置"); } return new TestBean(); } }
@RestController @RequestMapping("test") public class TestController { @Value("${testname:}") private String testName; @GetMapping("testApollo") public String testApollo() { return "hello: " + testName; } }
测试开始
SpringBoot通过注解或者配置的方式来集成Apollo的方式主要有一下三种,下面针对这三种情况做下测试
bootstrap.properties/yml配置
apollo.bootstrap.enabled=true
bootstrap.properties/yml配置
apollo.bootstrap.enabled=true
启动类配置
@EnableApolloConfig
注解
bootstrap | application | 是否配置注解 | 打印结果 | 启动前能否读取 | 启动后能否读取 | 能否实时读取 | 结论 |
---|---|---|---|---|---|---|---|
true | true | 配置 | true | 能 | 能 | 能 | Apollo配置起效且能实时更新 |
true | true | 不配置 | true | 能 | 能 | 能 | Apollo配置起效且能实时更新 |
true | false | 配置 | false | 能 | 能 | 能 | Apollo配置起效且能实时更新 |
true | false | 不配置 | false | 能 | 能 | 不能 | 应用启动时读取Apollo配置起效,但不能实时更新 |
true | 不配置 | 配置 | true | 能 | 能 | 能 | Apollo配置起效且能实时更新 |
true | 不配置 | 不配置 | true | 能 | 能 | 能 | Apollo配置起效且能实时更新 |
false | true | 配置 | true | 能 | 能 | 能 | Apollo配置起效且能实时更新 |
false | true | 不配置 | true | 能 | 能 | 能 | Apollo配置起效且能实时更新 |
false | false | 配置 | false | 能 | 能 | 能 | Apollo配置起效且能实时更新(有注解时不能禁用) |
false | false | 不配置 | false | 不能 | 不能 | 不能 | Apollo配置不起效 |
false | 不配置 | 配置 | false | 能 | 能 | 能 | Apollo配置起效且能实时更新 |
false | 不配置 | 不配置 | false | 不能 | 不能 | 不能 | Apollo配置不起效 |
不配置 | true | 配置 | true | 能 | 能 | 能 | Apollo配置起效且能实时更新 |
不配置 | true | 不配置 | true | 能 | 能 | 能 | Apollo配置起效且能实时更新 |
不配置 | false | 配置 | false | 能 | 能 | 能 | Apollo配置起效且能实时更新 |
不配置 | false | 不配置 | false | 不能 | 不能 | 不能 | Apollo配置不起效 |
不配置 | 不配置 | 配置 | null | 能 | 能 | 能 | Apollo配置起效且能实时更新 |
不配置 | 不配置 | 不配置 | null | 不能 | 不能 | 不能 | Apollo配置不起效 |
打印结果解析:
如果通过bootstrap.yml来配置Bootstrap上下文,且在设定好父级上下文的情况下,bootstrap.yml中的属性会添加到子级的上下文。它们的优先级低于application.yml和其他添加到子级中作为创建Spring Boot应用的属性源。
所以打印结果会与application配置相同,当application配置不存在时,才会与bootstrap的一样。
结论
对比这几种情况,可以得出:
只要注解配置了,Apollo都能起效且能实时读取最新配置。
当注解不配置的时候,以application的配置为主。(虽说只配application或者bootstrap都能单独进行控制)
所以,当需要配置控制Apollo是否起效时,尽量不好混合用这几种集成方式。最好的方式是:不配置bootstrap,不配置注解,只配置application,由application来控制Apollo的开关。
针对namespace的测试
测试目的:
测试
apollo.bootstrap.namespaces
配置在哪个配置文件的时候起效。
测试条件1:
我先在Apollo配置了两个namespace,两个namespace的同一个配置的配置值不一样。
application.properties:testname=test1
application.yml:testname:test2
然后在项目启动前及启动后观察加载的是哪个配置。
测试条件2:
测试只在SpringBoot的bootstrap.properties和application.yml中进行,且开关由application.yml配置控制
ps:使用注解的话,是在注解处配置namespace的
bootstrap.properties/yml
apollo.bootstrap.namespaces=application/application.yml/不配置
application.properties/yml
apollo:
bootstrap:
enabled: true
namespaces: application/application.yml/不配置
启动类:
@EnableTransactionManagement
@SpringBootApplication
@EnableEurekaClient
//@EnableApolloConfig
@Slf4j
public class AppApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(FormEngineApplication.class, args);
ConfigurableEnvironment environment = context.getEnvironment();
String apolloEnable = environment.getProperty("apollo.bootstrap.enabled");
System.out.println(apolloEnable);
}
@Value("${testname:}")
private String testName;
@Bean
public TestBean testBean() {
if (!StringUtils.isEmpty(testName)) {
System.out.println("应用启动前能读取到Apollo配置");
}
return new TestBean();
}
}
测试接口:用于测试项目启动后的testName的值
@RestController
@RequestMapping("test")
public class TestController {
@Value("${testname:}")
private String testName;
@GetMapping("testApollo")
public String testApollo() {
return "hello: " + testName;
}
}
测试:
bootstrap | application | 启动前的testName | 启动后的testName | 结论 |
---|---|---|---|---|
不配置 | 不配置 | test1 | test1 | 默认读取application.properties的namespace配置 |
不配置 | application | test1 | test1 | 看不出哪个起效 |
不配置 | application.yml | test2 | test2 | application.yml配置文件中配置namespace起效 |
application | 不配置 | test1 | test1 | 看不出哪个起效 |
application | application | test1 | test1 | 看不出哪个起效 |
application | application.yml | test2 | test2 | application.yml配置文件中配置namespace起效 |
application.yml | 不配置 | test1 | test1 | application.yml配置文件中配置namespace起效 |
application.yml | application | test1 | test1 | application.yml配置文件中配置namespace起效 |
application.yml | application.yml | test2 | test2 | 看不出哪个起效 |
结论
Apollo开关在application.properties配置文件中配置时,以application.properties配置文件中配置的namespace为主。
总结
以哪种方式集成Apollo,就以那种方式配置对应的namespace,才会起作用。
ps:经过测试(这里省略)
当Apollo开关在bootstrap.properties配置文件中配置时,namespace的配置会以bootstrap.properties配置文件中的为主。
当使用注解集成Apollo时,需在注解处配置namespace。