三方软件版本管理策略
系统升级、改造过程中,三方软件冲突是最常见的问题。随着软件迭代速度越来越快,传统的软件兼容性管理策略已经不适应软件的发展。
本章节分享三方软件管理的最佳实践,帮助您打造一个持续演进的应用系统。
开源软件选型
主要的开源社区,例如Spring Boot、Spring Cloud等都会维护多个版本分支。以Spring Cloud为例,存在Hoxton、Greenwich、2020.0.x等分支,其中大部分分支都已经停止维护。开源软件多数维护的分支存在两个:一个为最新版本的开发分支;一个为最近的稳定维护分支。
在开源软件选型上,应该紧跟社区的版本节奏,使用继续提供维护的分支的最新版本。在选择开发分支和维护分支上,没有严格的定论,需要视具体的产品功能确定。例如产品竞争力严重依赖某个三方软件的特性,那么更倾向于选择开发分支的最新版本;一个产品依赖某个三方软件的特性稳定,不使用新功能,那么更倾向于选择维护分支。
不建议选择社区已经停止维护的分支、以及虽然还在维护但发布时间超过半年以上的分支版本。虽然使用这些版本暂时没有发现功能问题,但是会给产品的持续演进带来严重影响:
- 软件的安全漏洞得不到及时处理。安全漏洞的发现和利用都有一定的时间周期,长期使用老版本,安全漏洞被利用的可能性变大,使得系统更加容易被攻击。
- 系统出现故障,更难寻求社区支持。停止维护的版本,或者已经发布超过半年以上的版本,很难得到社区的支持。
- 系统演进变得更加困难。当系统需要增加新特性,引入新开发工具时,老版本更难与新开发工具兼容。
- 还有很多的故障,可能在新版本已经修复,新版本在代码可维护性、性能等方面也都优于老版本。
因此,在开源软件选型问题上 ,最佳方案就是选择社区提供维护升级的开发分支或者维护分支,根据问题驱动升级到分支的最新版本,每季度周期性升级到分支的最新版本。
三方软件版本管理
首先通过一个简单的例子,介绍三方件冲突的原理。假设开发一个X项目,该项目需要同时引用项目A提供的组件,也需要引用项目B的组件,并且项目A和项目B同时依赖了项目C,但是版本号不同。
- 项目X的pom:
<dependency> <groupId>groupA</groupId> <artifactId>artifactA</artifactId> <version>0.1.0</version> </dependency> <dependency> <groupId>groupB</groupId> <artifactId>artifactB</artifactId> <version>0.1.0</version> </dependency>
- 项目A的pom
<dependency> <groupId>groupC</groupId> <artifactId>artifactC</artifactId> <version>0.1.0</version> </dependency>
- 项目B的pom:
<dependency> <groupId>groupC</groupId> <artifactId>artifactC</artifactId> <version>0.2.0</version> </dependency>
项目X在最终发布的时候,会出现如下几种情况:
- 使用项目C的0.2.0版本。由于项目A是使用0.1.0版本编译和测试的,那么组件A可能无法正常工作。例如0.2.0版本和0.1.0不兼容,并且项目A恰好使用了这些不兼容的接口。
- 使用项目C的0.1.0版本。由于项目B是使用0.2.0版本编译和测试的,那么组件B可能无法正常工作。例如项目B使用了0.2.0提供的新接口。
可以看出,如果项目A和项目B使用的C组件存在接口不兼容的情况,无论怎么调整,项目X都无法正常工作。必须修改项目A的代码,使用和B同样的或者兼容的版本进行测试,发布新的版本给X项目使用。
因此,进行依赖管理的最佳策略是保证公共组件的依赖,都使用较高的版本。尽管如此,通常还是会碰到一系列问题,特别是项目依赖关系非常复杂的情况。
目前主流的复杂项目,都采用dependency management机制管理依赖。使用dependency management已经被验证是比较有效的管理依赖的手段,因此被开源社区广泛使用。例如,Spring Boot、Spring Cloud和Spring Cloud Huawei,开发者可以通过查看Spring Cloud Huawei的源代码目录结构了解dependency management的具体使用。
对于复杂项目,以Spring Cloud Huawei项目为例,和依赖关系管理有关的pom文件包含:
/pom.xml # 项目的根目录 /spring-cloud-huawei-dependencies/pom.xml # 项目的主要依赖管理。和项目dependency management有关的声明都在这个文件。 /spring-cloud-huawei-parents/pom.xml # parents既给本项目的子module使用,也给项目开发者使用,类似Spring Boot提供的parent /spring-cloud-huawei-bom/pom.xml # bom主要用于项目开发者期望将Spring Cloud Huawei自己提供的组件引入项目的依赖管理,而不期望引入Spring Cloud Huawei依赖的第三方软件的版本。
Spring Cloud Huawei的这几个pom是相对完整的pom结构,从不同的使用视角给开发者提供了可以引入的pom,比较适用于公共开发组件。
一般的微服务开发项目可能只包含“/pom.xml”,项目的parent和dependency management都在“/pom.xml”声明。引入dependency management以后,项目中的所有dependency声明,都不指定版本号。这样的好处是当需要升级三方软件版本的时候,只需要修改“/pom.xml”里面的dependency management,其他地方都不需要排查修改。
您可以通过Spring Cloud Huawei的示例项目,直观体会dependency management的原理和作用:
- 执行命令mvn dependency:tree查看项目的依赖关系。
- 修改“/pom.xml”中“spring-boot.version”,再执行命令mvn dependency:tree查看项目的依赖关系的变化。
- 调整“/pom.xml”中“spring-boot-dependencies”和“spring-cloud-dependencies”的位置,再执行命令mvn dependency:tree查看项目的依赖关系的变化。
当项目依赖的三方软件增多的时候,识别软件之间的配套关系是非常困难的。一个比较好的策略是跟随Spring Boot、Spring Cloud的版本配套关系。将spring-boot-dependencies和spring-cloud-dependencies作为依赖关系管理的基础是非常好的选择。因为Spring Boot、Spring Cloud使用比较广泛,社区能够及时修复兼容性问题,开发者只需要升级Spring Boot、Spring Cloud版本即可,而无需关注被其依赖的其他三方软件的版本号。
升级三方软件,能够推动软件的持续改善,但是也需要进行一些工程能力的提升,例如自动化测试能力的建设。
关于三方软件管理的更多内容,请参考Java Chassis兼容问题和兼容性策略。