今天我还是想和大家继续聊一聊微服务中代码的组织形式。
昨天聊了微服务项目中要不要使用聚合工程的问题(微服务项目搭建,到底要不要聚合工程?),感觉小伙伴们对这个话题还挺感兴趣,因此今天我们就再来说说微服务中公共代码库的组织形式。
1.公共代码库
任何项目,我们都不可避免的会有一个公共代码库,这个公共代码库中可能存放了一些工具类或者实体类,供其他项目使用。
常规的做法就是把公共代码库上传到公司私服,然后每个人各自在项目中添加依赖即可,这种方式,相信很多小伙伴们都玩过。
但是不知道大家有没有想过,这种方式其实有一个弊端,就是它不适用于快速迭代的项目。
在一个快速迭代的项目中,common 的变化非常频繁,这就意味着开发者得不停的将 common 打包上传,其他人不停的修改所引用的 common 版本号。
在传统的单体应用中,团队人可能不会太多,common 变化也不怎么频繁,所以用 Maven 管理公共代码块的劣势并不明显。
而现在流行的微服务架构适合大军团作战,人多微服务数量也多,在微服务项目中,动辄几十个上百个微服务。为了解决微服务之间调用时的序列化问题,我们可能将实体类都抽到一个公共的 common 中,每个微服务都可以根据自己的需求修改 common,即使每个微服务每天修改一次 common,反映到 common 身上,也是日日夜夜不停的变化,而其他的微服务就得不停的修改版本号以便日日夜夜追随这种变化。
在这样的情况下,显然不适合使用 Maven 继续管理 common,因为这意味着你得不停的打包,所有的微服务得不停的修改引用的 common 版本号。
为了防止有人抬杠,松哥得补充一句,上面所说的这种情况在快速迭代的微服务项目中比较常见,特别是团队越大,微服务数量越多,Maven 管理公共代码块的劣势越明显。而传统的单体应用中,你可能并不容易感受到问题所在。
从松哥上面的描述中大家可以看出,Maven 实际上更侧重于包的依赖管理,虽然它能够做到在不同项目中同步公共代码,但没法双向同步(所谓双向同步,就是各个微服务中 common 的更新自动同步到 common 库,common 库的更新也能自动同步到各个微服务),Maven 更适用于公共代码库比较稳定的情形。
2.解决方案
如果公共代码库总是在不停的变化,而 Maven 又并不是特别方便,那么我们还有没有其他解决方案呢?
方案肯定是有的,不然松哥也不会撸这篇文章了。
这里给大家介绍一个我们团队目前在使用的方案---Git Subtree。
2.1 Git Subtree
Git Subtree 是 Git 官方给出的一个管理子项目的解决方案,在 Git Subtree 之前,官方给出的方案是 Git Submodule,但是从 Git1.5.2 开始,Git 新增并推荐使用这个功能来管理子项目,只要大家本地安装的 Git 版本大于等于 1.5.2,都可以直接使用 Git Subtree。
Git Subtree 虽然不具备依赖管理的功能,但是在处理快速代替的公共代码库时,却显得非常得心应手,而且它能够做到双向同步!
2.2 具体应用
说了这么多,这个 Git Subtree 到底要怎么用?这里松哥来给大家稍微介绍下。
首先,假设我现在有一个项目叫做 vmall,vmall 是一个微服务项目,里边包含了很多微服务,同时也包含了一个在快速迭代的公共代码块 vmall-common(注意,vmall 和 vmall-common 分属两个不同的仓库)。
vmall-common 我已经提交在 GitHub 上了,地址是 https://github.com/lenve/vmall-common。
现在我想在 vmall 项目中引用 vmall-common,怎么做呢?在 vmall 仓库中执行如下代码即可:
git subtree add --prefix=vmall-common https://github.com/lenve/vmall-common.git master --squash
最后的 --squash
参数表示不拉取历史信息,而只生成一条 commit 信息,这是一个可选参数,可以不加。这行命令执行完成后,在 vmall 项目中,就可以看到 vmall-common 了,而且 vmall-common 将作为一个普通的文件夹存在,该怎么样还是怎么样。
这个时候我们就可以正常开发了。
假如说,我们在开发的过程中,修改了 vmall-common,这个时候,在 vmall 仓库中,我们可以通过如下命令将 vmall-common 提交到它自己的仓库中去(先将 vmall 中的变化提交到远程仓库,再执行如下代码):
git subtree push --prefix=vmall-common https://github.com/lenve/vmall-common.git master
如果是在 vmall-common 自己的仓库中提交这种变化,那就是普通的 Git 提交命令,这个就不需要我多说了。
当 vmall-common 中的代码发生变化了,其他微服务通过如下指令可以更新代码:
git subtree pull --prefix=vmall-common https://github.com/lenve/vmall-common.git master --squash
这三个指令基本上就能应付日常的大部分操作了,不过每次都要输入一个长长的地址很不方便,我们可以给地址取一个别名:
git remote add -f vmall-common https://github.com/lenve/vmall-common.git
这样,最上面介绍的三个命令就可以简化了:
git subtree add --prefix=vmall-common vmall-common master --squash
git subtree pull --prefix=vmall-common vmall-common master --squash
git subtree push --prefix=vmall-common vmall-common master
3.总结
今天还是和小伙伴们聊了下代码微服务中代码的组织问题。
一言以蔽之,Maven 适合管理比较稳定的公共代码库,Git Subtree 适合处理快速变化的公共代码库,并且支持双向同步!关于 Git Subtree 的一些使用细节问题,比如 --squash
参数要不要加,什么时候加,松哥以后抽时间再来和大家细说。
好啦,感兴趣的小伙伴可以下来试试~如果大家觉得有收获,记得点个在看鼓励下松哥哦~