本文会尝试回答下面几个问题:
mono-repo
)?Google
/Facebook
/Bilibili
采用单体仓库?mono-repo
) 和多仓库 (multi-repo
) 分别解决了哪些问题?mono-repo
) 和多仓库 (multi-repo
) 在解决问题的同时又引入了哪些问题?在介绍单体仓库和多仓库前,我们先了解一下应用的类型,了解一下为什么要区分单体仓库和多仓库。
monolith
)在早期,实际上是不用区分单体仓库和多仓库的,因为在早期的时候一个应用就把所有功能打包了。哪怕使用多个仓库也是根据公共模块方式来区分,仓库数量也是比较少的。这时候的应用我们一般叫他单体应用。主要的特点就是一个程序就打包所有功能,全家桶。
这样的开发模式有很多优点,如:
IDE
当中,进行 code review
,方便开发人员把握整体的技术架构和业务目标。IDE
的支持)容易对现有代码进行重构,可以抽取出一些公共的功能进一步提升代码的质量和复用度。code review
,规范化代码的风格。但是随着单一应用功能的拓展,应用仓库无限制变大也带来了很多缺点,如:
micro-service
)既然单一应用的问题是由于后期功能过多,应用复杂度上升产生的。那是否可以通过将单体应用拆解成无数的小应用来避免这些问题呢?
实际上后面出现的微服务这个概念就类似于上面的思路,通过将一个大型应用拆分成无数个服务。每个服务有自己的代码文件,单独部署,然后共同组成一个应用程序。
需要注意的是这里的 "微"
不是指的代码行数,而是说服务的功能限定到单个功能。
微服务相比单体应用最大的好处是可以独立的开发测试部署和扩展。
既然单体应用一般采用单体仓库,那么微服务的代码仓库又是如何组织的呢?实际上关于这点网络上讨论的不是很多,基本上就是一个服务一个仓库。
我也一直以为这样是微服务的最佳实践。但是 bilibili
的源代码告诉了我们另一个选择,单体仓库(mono-repo
)。
实际上,针对微服务代码的仓库组织,业界一直有两种主要的实践:
multi-repo
),在微服务中就是每个服务一个源码仓库。mono-repo
),虽然应用采用的微服务架构,但将所有源码放在同一个仓库。从左到右依次为:单体应用单体仓库(monolith
),微服务多仓库(mono-repo
),微服务单体仓库(mono-repo
)。
首先需要肯定的是,单体仓库和多仓库两种方案能同时存在,一定是各有利弊的,希望大家不要将自己锁定到一种方案上。软件开发中没有银弹,没有绝对的好与不好之分,选择适合自身团队的管理方案就好。
multi-repo
)多仓库为我们带来了如下好处:
但同时,多仓库也存在着以下的问题:
code review
无法集中开展,代码风格各不相同。mono-repo
)单体仓库的优点:
code review
,规范化代码的风格。IDE
当中,进行 code review
,也可以直接在本地部署调试,方便开发人员把握整体的技术架构和业务目标。单体仓库的缺点:
OWNERS
,CODEOWNERS
等,但相比多仓库还是差了一些。Google
自研的面向单体仓库的构建工具 Bazel
:https://bazel.build/ 和 Facebook
的 Buck
:https://buck.build/ 。但还是需要团队进行整合。世界上采用单体仓库管理源码的公司实际并不少,比如: Google
,Facebook
,Twitter
这些互联网巨头。可以看到,虽然这些公司系统庞大、服务众多,内部研发团队人数众多,但是采用单体仓库也很好的解决了业务需求。
微服务架构并不是主张所有的东西都要独立自治,至少代码仓库就可以集中管理,不要让先入为主的观念影响你的判断,根据实际需要选择最合适的方案。初创公司的话,在公司早期并且服务不是特别多的情况下,采用单体仓库比较合适。这样也容易养成团队统一的代码风格,过早的分而治之容易导致团队各自为战,代码风格散乱等问题。
kubernetes
采用的大仓管理 https://github.com/kubernetes/kubernetes/tree/master/cmd