最近有位朋友给我吐槽,接手了一个新的项目需要开通 80 多个代码仓库,几乎每个代码仓库对应一个微服务,但是团队却没有多少人。

一个人要维护好几个服务的事情最近几年越来越常见,我接手不少,虽然好几个项目的服务都被我合并了(不合并项目多半会死)。

非常有意思的是 7-8 年前还是好几十个人工作在一个代码库中,这不到几年就是一个人工作在 7-8 个代码库中。

这真是:兴,程序员苦,亡,程序员苦。

我用上高配置笔记本还是这几年的事情,在 Thoughtworks 之前一直使用的一台 ATOM 芯片的上网本,保持健康使用的情况下开发效率没有特别大的影响。

但是后来不行了。很多的项目需要同时打开多个代码仓库才能在本地开发。不仅对笔记本的性能提出要求,对我这个二流程序员来说认知上也提出了挑战。

老生常谈,微服务其实是分布式应用系统,当系统非常复杂、团队规模巨大的时候,拆分成微服务是非常合理的。

麻烦在于很多项目的微服务没有明确的边界和职责划分,于是在本地开发不得不启动多个服务,且修改一些逻辑的时候需要跨服务修改。

像我这种认知能力不高的人来说就很痛苦了,我自认为开发效率还挺高,但是是建立在我 ”一次只做一件事“的前提上。

一次只开一个编辑器或 IDE,一次只打开一个数据库,一次只打开一个浏览器。

如果一个架构设计需要认知不高的程序员同时打开多个 IDE 和数据库管理工具,那么这个架构是不合理的。

在接到一些客户的求助时,也遇到过类似的问题,100 人的开发团队,有 200 个微服务,微服务还在变多,最终成为压死骆驼身上最后一根稻草。

其实按照经验,大概 4-5 个人维护一个服务是比较舒服的,既不会有多大冲突,也不会有过多的负担。

工作在一个服务上的人数过多或者过少都会增加认知负担,为了衡量这个值,我使用有限的数学知识,整理了一个公式。

$$ log2(N/P/S) = 认知商 $$

其中:

  • N 为团队人数。
  • P 多少个人照顾一个服务的参数,根据项目类型进行设定。
  • S 为微服务数量。

人数除以微服务数量可以得到每个微服务有多少个人维护,引入 P 并取 2 为底的对数是为了获得一个有趣的值。当每个微服务维护的人数接近 P 的时候,认知商为 0,表示没有认知负担。

当人数过多、过少,认知商的绝对值就会增大,认知商符号为正数说明太多的人工作在一个服务上面,符号为负数说明服务太多。

举个例子,设定 P = 5, N = 100, S = 20。也就是 100 名开发者工作在 20 个服务上,100/5/20 = 1,取 2为底的对数就是 0。

如果这个公司裁人了,人数只有 20 人,然是依然维护这么多的服务,计算出新的结果就是 2.321928094887362 符号为负数,意味着服务太多。

通过这个公式可以在一定程度上衡量团队的认知负担。取 2 为底的原因让步长刚刚合适:

例如,上面的例子中 100 人的团队认知商为 0,如果 50 人的团队继续维护 20 个服务认知商就是 -1。我们可以选择合适的数值作为风险预警线,在公式中以 2 为底则刚刚合适。

如果认知商的绝对值在 0-1 之间,可以认为安全访问,如果大于 1,说明微服务太多或者太少。

一般来说将微服务过多的划分原因之一是将微服务当做目的而非手段了。

项目中出现耦合,加一个服务。

性能有问题,加一个服务。

很多团队服务只见增加不见减少,慢慢很多团队手上就是一大堆服务。

到底多少个服务合适,我总结了 6 个一原则:

  1. 一个服务指定一个小型团队维护。
  2. 一个服务对应一个明确的能力和职责。
  3. 一个服务对应一个代码仓库。
  4. 一个服务配置一个对应的部署单元和配置。
  5. 一个服务对应一个数据库(有的可能没有)。
  6. 一个服务对应一条流水线。

一个服务对应一个小型团队是为了明确权限和责任的主体;一个服务对应一个明确的能力和职责是为了明确这个服务被划分出来的意义。;一个服务对应一个代码仓库是要求架构师清晰地划分代码的边界;一个服务配置一个对应的部署单元和配置是为了明确服务的 API、运维职责;一个服务对应一个数据库(有的可能没有)是为了明确数据边界;一个服务对应一条流水线是为了满足相关开发、部署的支持能力。

在划分微服务时候,如果做不到上述 6 点,说明这个微服务在划分上还需要斟酌,明确这个服务到底被谁维护、它的作用是什么、可以给它赋予什么权限等问题。

Last Updated:
Contributors: lin