说说依赖包的管理和维护

来源:互联网 发布:国际象棋和围棋 知乎 编辑:程序博客网 时间:2024/05/17 02:21

相信在Java阵营中,现在还在用Ant来做构建的团队已经越来越少了,大家都在使用Maven,甚至有一些Android/后端团队都转向Gradle。 同时,大家都绕不过一个共同的话题:依赖包的管理和维护。那我就针对这个话题谈谈我的一些实践经历。


版本的分类


在maven中,依赖包可以分为SNAPSHOT和RELEASE两类版本。


简单来说,SNAPSHOT依赖泛指以-SNAPSHOT为结尾的版本号,例如1.0-SNAPSHOT。除此之外,所有非-SNAPSHOT结尾的版本号则都被认定为release版本,即正式版,无论我们是不是在version中加上beta、rc之类的后缀,但是这些只是以软件工程角度的测试版,对于maven而言,这些都是RELEASE版本。既然Maven提供了这两类版本号,那么他们之前的优劣势是什么?分别在什么场景下使用?


SNAPSHOT的应用场景


目前,一个互联网应用的后端服务中通常包含多个模块,并且通常的场景是多个团队开发后端的不同模块。举个栗子,后端部门中有两个团队,其中一个团队开发应用的接口网关apigw,项目为apigw(apigw.jar:1.0),而另一个团队开发一个具体的用户服务,使用的项目名是user-service(user-service.jar:1.0)。


现在可能出现的情况是开发user-service的团队,正在进行快节奏的bug修复或者项目改进,他们几乎每隔一天就要发布新版本到远程仓库。

现在如果user-service团队每隔一天上传一个新版本,那么将会出现下面的问题:

user-service团队每次发布更新的代码时都要告知apigw网关开发团队更新版本。同时apigw团队需要经常地更新他们的pom.xml文件,以更新apigw到最新版本。为了解决这种情况,快照(SNAPSHOT)的概念派上了用场。


为什么SNAPHOT能解决这个问题


Maven会根据模块的版本号(pom.xml文件中的version)中是否带有-SNAPSHOT来判断是快照版本还是正式版本, 如果是使用snapshot版本的模块,在不更改版本号的情况下,直接编译打包时,Maven会自动从镜像服务器上下载最新的snapshot版本。如果是使用release版本的模块,在不更改版本号的情况下,编译打包时如果本地已经存在该版本的模块则不会主动去镜像服务器上下载。

注意一点,很多人误以为SNAPSHOT是一个特定的版本,其实不然,SNAPSHOT是一系列的版本的集合,只是其中的HEAD总是指向最新的快照,对外界可见的就是最新版,而不是新生成的snapshot覆盖了老的版本。



问题解决了?


从上面的描述,会让我们觉得,版本的规则可以设定为:在开发测试期间,被依赖的模块的版本号使用SNAPSHOT,在生产环境,生成Release版本的被依赖版本模块,一种很完美的感觉。


但是现实情况真是如此简单吗?


我想说的是这只是理想状态,即所有的模块的版本都在自己的掌控或者开发同学们不会滥用snapshot的情况下,只有这样你才能影响对应模块的版本号。


理想很丰满,现实很骨感。


往往是你依赖的SNAPSHOT版本就这样上到生产环境中去了,由于该模块很活跃,该模块的维护人都"懒"得上线前通过release版本来发布了,久而久之,你会发现pom.xml文件中有大量snapshot依赖。

进而导致环境的越来越不稳定,有问题或者不稳定的snapshot被带上生产环境,并直接影响到产品的正常使用。



进一步解决:流程和工具化建设


版本控制和维护,仅仅靠版本的约定最终往往是走不通的。

所以需要更进一步:流程和工具化建设


1. 私服按环境隔离


将Prod环境/Test环境/Dev环境的nexus私服彻底隔离开。


应该说,这不是一个实惠的办法,不过往往简单粗暴的做法,能减少有问题的包被传染到更多的环境,特别是生产环境上。当然我们可以保持一套私服,通过例如加test-snapshot和dev-snapshot的方式,来区分开发和测试的Snapshot包,同时需要一套脚本来维护pom文件,但在实际用下来,开发同学也时常会忘记或者犯错。同时,进行一些依赖改动的时候,也需要有一定的维护成本。

一般而言,让开发同学对环境透明,“忘记”考虑环境或者配置的因素,就能达到最佳的效果。



2. 引入版本控制插件


对于遇到三方包或者不受我控制的jar包怎么办? 找到有一款maven插件——versions,这是一个非常强大的版本管理插件,其中有个对依赖版本加锁的特性——lock-snapshots,并且提供了参数可以控制锁定的依赖,就可以实现对特定的SNAPSHOT模块锁定版本,执行的命令如下:


mvn versions:lock-snapshots -DincludesList="groupId:artifactId:type:classifier:version"


执行这个命令之后,对应的版本号会变化,例如 1.0.0-SNAPSHOT会变成1.0.0.20171120.235232-3,即完成了锁定,此时这个SNAPSHOT就变成了固定小版本的稳定版本,不会在变化了,也相当于正式版的功能了。


3. 权限控制和版本扫描


除了以上2点,在执行过程中,我们对依赖包的deploy的控制,进行了权限控制(特定人员执行,特定分支才能打包。。),所以保证包的质量能得到有效的监控和控制。进一步的,在生产环境打包的过程中,我们会去监控依赖二方包的版本是否正常,如果发现有依赖snapshot的二方包,就会主动报错,判定打包失败。



相关阅读


高效研发体系的基本特征

提升技术团队战斗力的几件事


扫描二维码或手动搜索微信公众号【架构栈】: ForestNotes

欢迎转载,带上以下二维码即可


点击阅读原文”,所有【架构栈】近期的架构文章汇总

↓↓↓

原创粉丝点击