端午节前将Spring Boot的版本升级到2.3.1.RELEASE之后,假期回来的第一天就推送上线,最近线上系统开始爆一些奇奇怪怪的错误,比如:
paho3625270288893656: Timed out as no activity, keepAlive=60,000,000,000 lastOutboundActivity=4,391,824,700,168,296 lastInboundActivity=4,391,767,474,515,409 time=4,391,884,700,372,796 lastPing=4,391,824,700,242,264
或:
Lost connection: Timed out waiting for a response from the server; retrying...
怀疑是系统压力过大,处理不过来导致的,而系统在极低的负载时爆出过很多次。检查了一圈怀疑是Paho的版本有问题,Spring Boot 2.3.1.RELEASE指定的Paho是1.2.2,升级前是1.2.0,目前最新版本是1.2.4,扫了一眼Release Notes,感觉 1.2.1 有好多fix…和领导商量了一下,宁愿降级而不愿意升级,用1.2.0跑了好长时间一点问题都没有,那么就降吧。
项目由于使用了Gradle构建,所有的依赖都交给了 Spring Boot Gradle Plugin 进行管理,在引入依赖的时候做好对齐就好了, 即使手动引入一个较高或者较低的依赖版本,在打包的时候仍然会被替换为Plugin管理的版本,在IDEA中还会显示手动引入的依赖版本与Plugin的管理版本 。
Spring Boot Gradle Plugin Reference 提及了可以自定义版本 ,同时也提醒了: Each Spring Boot release is designed and tested against a specific set of third-party dependencies. Overriding versions may cause compatibility issues and should be done with care.
Reference的推荐做法是在 Spring Boot管理的依赖中 找到对应的version property,通过在build.gradle中指定版本达成目的,如:
ext['slf4j.version'] = '1.7.20'
在这个名单找不到Paho的版本,Paho被Spring Integration MQTT所引用,Spring Integration MQTT还引用了其他很多工具的依赖,我只需要修改Paho的版本就好,Reference提及的做法不能奏效。
参照 Gradle DependencyHandler 中的配置:
Examples of advanced dependency declaration including: - Forcing certain dependency version in case of the conflict. - Excluding certain dependencies by name, group or both. More details about per-dependency exclusions can be found in docs for ModuleDependency.exclude(java.util.Map). - Avoiding transitive dependencies for certain dependency.
在手动引用依赖的时候,声明依赖的版本为强制指定,如:
api('org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.0') { force = true }
repackaging之后Paho就被替换为指定的版本。