Spring Cloud Application集成ConfigServer和Bus后,如果希望配置可以灰度发布, 通常我们会通过指定destination来实现:
curl -X POST "http://localhost:8888/bus/refresh?destination=${application context id}"
一般容易把这个context id误解为spring.application.name
而实际上, 默认的context id是spring.application.name + server.port, 比如:
curl -X POST "http://localhost:8888/bus/refresh?destination=demo-service:8080"
curl -X POST "http://localhost:8888/bus/refresh?destination=demo-service:8090"
将分别刷新端口为8080和8090的demo-service, 其他端口的demo-service并不会刷新
然而通常我们部署一个服务集群的时候, 是在多个host上部署端口相同的实例, 因此上面的方法就不能完成配置的灰度发布. 因此我们需要搞清楚context id到底是个什么东西
分析Spring源码找到如下类:
ContextIdApplicationContextInitializer.java
private String getApplicationId(ConfigurableEnvironment environment) {
String name = environment.resolvePlaceholders(this.name);
String index = environment.resolvePlaceholders(INDEX_PATTERN);
String profiles = StringUtils
.arrayToCommaDelimitedString(environment.getActiveProfiles());
if (StringUtils.hasText(profiles)) {
name = name + ":" + profiles;
}
if (!"null".equals(index)) {
name = name + ":" + index;
}
return name;
}
从以上代码可以看出, context id实际上是application name : active profile : application index
其中,name的表达式如下:
${spring.application.name:${vcap.application.name:${spring.config.name:application}}}
一般对应配置项spring.application.name
而index的表达式是:
${vcap.application.instance_index:${spring.application.index:${server.port:${PORT:null}}}}
对应配置项:spring.application.index
如果什么都不配置,就取server.port。
综上,如果什么都不配置,那么getApplicationId返回的是${spring.application.name}:${server.port}
为了能单机变更配置, 只需要配置application index就可以了, 我们选择配置为hostname:
spring.application.index=${spring.cloud.client.hostname}
之后通过
curl -X POST "http://localhost:8888/bus/refresh?destination=demo-service:dev:localhost"
就可以完成单机配置发布