背景
系统使用的是zuul作为网关,我们的zuul规则是/api/{service-id}但是其中有个规则/api/*转发到指定服务,
我们把转发规则配置到yml文件中,后面系统接入apollo版本是1.5.1,发现拉回来配置的是混乱的,但是我们的zuul路由规则是要求有序的。
1.解决问题
首先上apollo的github查找是否存在同样的问题,结果果然搜索到一个有相同问题的,附上github链接:
https://github.com/ctripcorp/apollo/issues/2451 查找到问题解决思路,再继续看后面发现已经提交
代码结局了这个问题,如下图进一步去查看源码这一问题是怎么解决的。我们在我们引入的1.5版本的apollo是没有这个的,所以我们需要引入1.6版本的apollo
2.源码
在github找到修改当前问题提交的代码链接: https://github.com/songdragon/apollo/pull/2/commits/6f4d3e56a2466c8ef23ba89b5facc4751dca1ce8
List< ConfigChange> calcPropertyChanges ( String namespace, Properties previous,
Properties current) {
if ( previous == null) {
previous = new Properties ( ) ;
previous = PropertiesFactory. getPropertiesObject ( ) ;
}
if ( current == null) {
current = new Properties ( ) ;
current = PropertiesFactory. getPropertiesObject ( ) ;
}
Set< String> previousKeys = previous. stringPropertyNames ( ) ;
从上面可以发现使用PropertiesFactory.getPropertiesObject()替代了Properties,
因为Properties是继承Hashtable是无序的这个就是问题所在。下面我们去查看下PropertiesFactory
public interface PropertiesFactory {
String APOLLO_PROPERTY_ORDER_ENABLE = "apollo.property.order.enable" ;
public Properties getPropertiesInstance ( ) ;
看到apollo.property.order.enable这个配置,从描述上看,是保证配置文件的顺序那就是这里了。进一步
看一下PropertiesFactory的实现
public class DefaultPropertiesFactory implements PropertiesFactory {
private ConfigUtil m_configUtil;
public DefaultPropertiesFactory ( ) {
m_configUtil = ApolloInjector. getInstance ( ConfigUtil. class ) ;
}
@Override
public Properties getPropertiesInstance ( ) {
if ( m_configUtil. isPropertiesOrderEnabled ( ) ) {
return new OrderedProperties ( ) ;
} else {
return new Properties ( ) ;
}
}
}
我们看到这里做了一个判断,是实例化OrderedProperties还是Properties,我们看到OrderedProperties是
继承Properties,其中就是对有序做了一些处理,可以去研究一下,我们现在看下
m_configUtil.isPropertiesOrderEnabled()是做了什么操作,只要这个为true,
那就实例化OrderedProperties那就能保证有序了。
继续看ConfigUtil可以看到isPropertiesOrderEnabled方法只是读取了ConfigUtil的一个属性
propertiesOrdered,那么这个是在哪里设值的呢?我们从ConfigUtil的构造函数中找到了答案
public ConfigUtil ( ) {
warnLogRateLimiter = RateLimiter. create ( 0.017 ) ;
initRefreshInterval ( ) ;
initConnectTimeout ( ) ;
initReadTimeout ( ) ;
initCluster ( ) ;
initQPS ( ) ;
initMaxConfigCacheSize ( ) ;
initLongPollingInitialDelayInMills ( ) ;
initAutoUpdateInjectedSpringProperties ( ) ;
initPropertiesOrdered ( ) ;
}
private void initPropertiesOrdered ( ) {
String enablePropertiesOrdered = System. getProperty ( APOLLO_PROPERTY_ORDER_ENABLE) ;
if ( Strings. isNullOrEmpty ( enablePropertiesOrdered) ) {
enablePropertiesOrdered = Foundation. app ( ) . getProperty ( APOLLO_PROPERTY_ORDER_ENABLE, "false" ) ;
}
if ( ! Strings. isNullOrEmpty ( enablePropertiesOrdered) ) {
try {
propertiesOrdered = Boolean. parseBoolean ( enablePropertiesOrdered) ;
} catch ( Throwable ex) {
logger. warn ( "Config for {} is invalid: {}, set default value: false" ,
APOLLO_PROPERTY_ORDER_ENABLE, enablePropertiesOrdered) ;
}
}
}
initPropertiesOrdered这个方法是读取了一个这个配置APOLLO_PROPERTY_ORDER_ENABLE,找到问题了,
我们只需要把这个设置为true就ok了,所以终极解决方案是在jvm启动参数中加上
apollo.property.order.enable=true。