边界:微服务的粒度

    子贡问:“师与商也孰贤?” 子曰:“师也过,商也不及。” 曰:“然则师愈与?” 子曰:“过犹不及。”

    子贡问:“颛孙师和卜商谁更贤德?” 孔子说:“颛孙师常常作得有些过头,卜商常常达不到要求。” 子贡说:“如此说来,是不是颛孙师要好一些呢?” 孔子说:“过头和达不到同样不好。”

    —— 论语·先进

    当今软件业界,对本节的话题“识别微服务的边界”其实已取得了较为一致的观点,也找到了指导具体实践的方法论,即领域驱动设计(Domain-Driven Design,DDD)。囿于主题,在这部文档中甚少涉及该如何抽象业务、分析流程、识别边界、建立模型、映射到服务和代码等偏重理论的务虚话题,即使在这一章中,笔者也尽量规避了 DDD 中需要专门学习才能理解的概念,如界限上下文(Bounded Context)、语境映射(Context Map)、通用语言(Ubiquitous Language)、领域和子域(Domain、Sub Domain)、聚合(Aggregate)、领域事件(Domain Event)等等。并非笔者认为业务流程与设计方法论不重要,而是如果要严谨、深刻地讨论这些话题,其篇幅足以独立地写出一本书。事实上,市场上已经有不少这样的书了,DDD 的发明人 Eric Evans 撰写的同名书籍《》便是其中翘楚。笔者个人是更推荐 Chris Richardson 撰写的颇具口碑的入门书《微服务架构设计模式》,其叙述的主线就是在 DDD 指导下,如何将一个单体服务逐步拆分为微服务结构,如果你对这方面感兴趣,不妨一读。这两节中,笔者会从业务之外的其他角度,从非功能性、研发效率等方面来探讨微服务的粒度与拆分。

    系统设计是一种创作,而不是应试,不可能每一位架构师设计的服务粒度全都相同,微服务的大小、边界不应该只有唯一正确的答案或绝对的标准,但是应该有个合理的范围,笔者称其为微服务粒度的上下界。我们可以分析如果微服务的粒度太小或者太大会出现哪些问题,从而得出服务上下界应该定在哪里。

    综合以上,我们可以得出第一个结论:微服务粒度的下界是它至少应满足独立——能够独立发布、独立部署、独立运行与独立测试,内聚——强相关的功能与数据在同一个服务中处理,完备——一个服务包含至少一项业务实体与对应的完整操作。

    我们再来想想,如果微服务的粒度太大,会出现什么问题?从技术角度讲,并不会有什么问题,每个能正常工作的单体系统都能满足独立、内聚、完备的要求,世界上又有那么多运行良好的单体系统。微服务的上界并非受限于技术,而是受限于人,更准确地说,受限于人与人之间的社交协作。《人月神话》中最反直觉的一个结论是:“为进度给项目增加人力,如同用水去为油锅灭火”(Adding Manpower to A Late Software Project Makes It Later)。为什么?Fred Brooks 给出了简洁而有力的答案:

    为了让你能更直观地理解这个答案,笔者已经算好了一组数字:15 人参与的项目,沟通成本大约是 5 个人时的十倍,150 人参与的项目,沟通成本大约是 5 个人时的一千倍。你不妨回想一下自己在公司的工作体验,不可能有 150 人的团队而不划分出独立小组来管理的,除非这些人都从事流水线式的工作,协作时完全不需要沟通。此外,你也不妨回想一下自己的生活体验,我敢断言你的社交上界是不超过 5 个知己好友,15 个可信任的伙伴,35 个普通朋友,150 个说得上话的人。这句话的信心底气源于此观点是人类学家在 1992 年给出的科学结论,今天已被普遍认可,被称为“邓巴数”(Dunbar’s Number),据说是人脑的新皮质大小限制了人能承受的社交数量,决定了邓巴数这个社交的上界。

    有了以上铺垫,你应该更能理解前面的许多文章中笔者为何采用“2 Pizza Team”作为微服务团队规模的“量词”了,并不是因为制造这个梗的人是,是亚马逊 CEO、世界首富。而是因为两个 Pizza 能喂饱的人数大概就是 6-12 人,符合软件开发中团队管理的理想规模。

    康威定律约束了软件的架构与组织的架构要保持一致,所以微服务的上界应该与 2 Pizza Team 能够开发的最大程序规模保持一致。2 Pizza Team 能开发多大规模的程序?人员数量固定的前提下,这个答案不仅与开发者的能力水平相关,更是与研发模式和周期相关。如果你的软件产品是瀑布开发,可能需要一个月、两个月迭代一次;如果采用 Scrum,可能会一周、两周完成一次冲刺;如果追求日构建、精益,甚至可能一天、两天就会集成构建出一个小版本,以上不同的研发方法,都会产生相应规模的上界。

    综合以上,我们得出了第二个结论:微服务粒度的上界是一个 2 Pizza Team 能够在一个研发周期内完成的全部需求范围。

    在上下界范围内,架构师会根据业务和团队的实际情况来灵活划定微服务的具体粒度。譬如下界的完备性要求微服务至少包含一项完整的服务,不超过上界的前提下,这个微服务包含了两项、三项业务操作是否合理,那需要根据这些操作本身是否有合理的逻辑关系来具体讨论。又譬如上界要求单个研发周期内能处理掉一个微服务的全部需求,不超过下界的前提下,一个周期就能完成分属于两个、三个微服务的全部需求时,是缩短研发周期更合理,还是允许这个周期内同时开发几个微服务,也可以根据实际情况具体讨论。