知识卡片

三种解耦粒度,与为何"默认微服务优先"是代价高昂的选择

普通读书笔记卡

内容

水平分层和垂直用例切分可以落到三种不同的解耦粒度上。源码层次:控制源代码模块间的依赖关系,让一个模块的变更不会牵连其他模块重新编译(如Ruby Gem),所有组件在同一地址空间内运行、靠函数调用交互,这种模式通常被称为单体结构。部署层次:控制部署单元(jar/DLL/共享库)间的依赖关系,让一个模块变更不会牵连其他模块被迫重新构建部署,大部分组件仍可能共享地址空间,但也可能有些组件运行在同处理器的其他进程里,靠跨进程通信或socket/共享内存交互,解耦成果是若干可独立部署的单元。服务层次:把组件间依赖降到数据结构级别,仅通过网络数据包通信,每个执行单元在源码层和二进制层都彻底独立,服务和微服务就是这个粒度的典型代表。哪种粒度最好在项目早期很难判断,而且最佳粒度会随项目成熟度变化——单机运行良好的程序发展到一定规模可能需要把部分组件迁到其他服务器,那时源码层解耦就不够用了,得升级到部署层甚至服务层。作者明确反对当下流行的”默认就上服务层次解耦”:这个做法成本高昂,还在鼓励一种粗粒度的解耦——无论微服务号称多”微”,解耦的精细度往往仍然不够;服务边界的处理不仅耗费内存和处理器资源,更耗费研发人力,而人力成本远比硬件贵得多。更务实的做法是把解耦推进到”一旦有需要就能随时转成服务”的程度即可,让系统尽量长时间保持单体结构,为未来留出可选项——最初在源码层次做隔离可能就足够撑完整个项目周期,需求升高时再挑一部分组件升到部署层次乃至服务层次,需求降低时甚至可以退回到部署层或源码层解耦。一个设计良好的架构应该能让系统从单体起步、逐步成长为独立可部署单元乃至独立服务,也能在情况变化时逆向退回单体——解耦模式本身,就应该是架构师保留给系统的又一个可选项。

参考来源

- 位置:《架构整洁之道》第16章《独立性》"再谈解耦模式""本章小结"(源文件:_epub-src/text/part0014_split_001.html) - 结论依据:原文定义源码层次/部署层次/服务层次三种解耦粒度及各自的组件运行与通信方式,批评默认服务层次解耦成本高昂且鼓励粗粒度解耦,主张让系统尽量长时间保持单体、按需逐步升级解耦粒度并可逆地退回,直接支撑本卡片结论。 - 原始内容:源码层次……部署层次……服务层次……我通常会倾向于将系统的解耦推行到某种一旦有需要就可以随时转变为服务的程度即可,让整个程序尽量长时间地保持单体结构……一个设计良好的架构应该能允许一个系统从单体结构开始……最后还能随着情况的变化,允许系统逐渐回退到单体结构。