现象:
服务始终发不成功,即使是以前发布成功的commit, 这会也发不上去了。同时Sentry里有多次报错:
NoSuchMethodError
com.ctrip.framework.apollo.Config.addChangeListener(Lcom/ctrip/framework/apollo/ConfigChangeListener;Ljava/util/Set;)V
com.leyantech.utility.concurrent.DynamicThreadPools in setThreadPoolDynamicallyConfigurable at line 130
com.leyantech.utility.concurrent.DynamicThreadPools in create at line 89
com.leyantech.utility.concurrent.DynamicThreadPools in create at line 100
com.leyantech.gaia.server.Gaia in createDefaultExecutor at line 339
…
分析过程:
吉老师:看上去和 apollo 版本有关,以致于运行时的 apollo class 版本不对。pom.xml里apollo的版本很久没动过了。不过近期 gaia 的运行时新增了一些功能,可能刚好用到了项目P 以前没依赖到的 apollo 版本,所以先拉下 项目P 的代码分析。
进 项目P 的容器把 jar 包打开,反编译了一下相关 class,结果如下:
public interface com.ctrip.framework.apollo.Config {
public abstract java.lang.String getProperty(java.lang.String, java.lang.String);
public abstract java.lang.Integer getIntProperty(java.lang.String, java.lang.Integer);
public abstract java.lang.Long getLongProperty(java.lang.String, java.lang.Long);
public abstract java.lang.Short getShortProperty(java.lang.String, java.lang.Short);
public abstract java.lang.Float getFloatProperty(java.lang.String, java.lang.Float);
public abstract java.lang.Double getDoubleProperty(java.lang.String, java.lang.Double);
public abstract java.lang.Byte getByteProperty(java.lang.String, java.lang.Byte);
public abstract java.lang.Boolean getBooleanProperty(java.lang.String, java.lang.Boolean);
public abstract java.lang.String[] getArrayProperty(java.lang.String, java.lang.String, java.lang.String[]);
public abstract java.util.Date getDateProperty(java.lang.String, java.util.Date);
public abstract java.util.Date getDateProperty(java.lang.String, java.lang.String, java.util.Date);
public abstract java.util.Date getDateProperty(java.lang.String, java.lang.String, java.util.Locale, java.util.Date);
public abstract <T extends java.lang.Enum<T>> T getEnumProperty(java.lang.String, java.lang.Class<T>, T);
public abstract long getDurationProperty(java.lang.String, long);
public abstract void addChangeListener(com.ctrip.framework.apollo.ConfigChangeListener);
public abstract java.util.Set<java.lang.String> getPropertyNames();
}
从反编译结果来看,确实没有 com.ctrip.framework.apollo.Config.addChangeListener(Lcom/ctrip/framework/apollo/ConfigChangeListener;Ljava/util/Set;)
这个方法,只有 public abstract void addChangeListener(com.ctrip.framework.apollo.ConfigChangeListener)
而gaia 里依赖的 apollo client 版本是 1.7.1 ,确实是有相关方法的,如下图红框内所示:
解决办法:
把项目P依赖的apollo client 版本升级至1.7.1后,问题解决
建议:
基础组件的版本管理,例如apollo,es,redis等基础组件,最好在基础架构的包里去管理,类似于spring-boot(注:本项目没有用spring全家桶,而是用的ninja+juice),在基础包里做好依赖管理,避免依赖管理混乱,造成一些潜在问题。但这不是单一团队的事情,需要各个团队配合升级才好做。