知识卡片

四种边界物理形式的通信成本呈阶梯递增

普通读书笔记卡

内容

架构边界从最轻量到最昂贵,依次分四个层级。单体结构:最简单常见的边界并没有固定物理形式,只是对同一进程同一地址空间内的函数和数据做了划分([[三种解耦粒度与为何默认微服务优先是代价高昂的选择]]中的源码层次解耦),最终部署成一个可执行文件(静态链接的C/C++项目、绑定一堆类的jar包、.NET的EXE文件),组件间交互就是普通函数调用,迅速廉价,因此这类跨边界通信可以非常频繁,组件通常以源码形式交付。部署层次组件:动态链接库(.Net的DLL、Java的jar、Ruby Gem、UNIX共享库),部署时不需要重新编译,以二进制或等价可部署形式交付,函数仍处于同一进程同一地址空间,除了动态加载有一次性调用成本外,跨边界通信同样廉价频繁,依赖管控策略和单体结构基本一致(线程只是管理调度程序执行的方式,既不算架构边界也不算部署单元,可以被包含在单个组件内,也可以横跨多个组件)。本地进程:由命令行或等价系统调用产生,运行于同一组处理器但各自拥有独立地址空间,内存保护机制通常让它们无法直接共享内存,最常见的通信方式是socket,也可以用共享内存或消息队列——通信需要系统调用、数据编解码、进程间上下文切换,成本明显更高,必须谨慎控制通信次数,且高层进程的源码里不该出现低层进程的名字、物理内存地址或注册表键名(低层进程该是高层进程的插件)。服务:最强的边界形式,本质是一个进程,但不假设具体运行位置,通信方式统一假设走网络,往返时间可以从几十毫秒到几秒不等,是四者中最慢的,因此在这个层次划分边界时必须严格控制通信次数、并设计成能容忍高延迟。现实系统除单体外通常会混用多种边界策略——服务往往不过是一系列互相作用的本地进程的外在形式,无论是服务还是本地进程,内部几乎都是由单体或动态链接组件构成的,最终一个系统常常同时包含高通信量低延迟的本地边界和低通信量高延迟的服务边界。

参考来源

- 位置:《架构整洁之道》第18章《边界剖析》"部署层次的组件""线程""本地进程""服务""本章小结"(源文件:_epub-src/text/part0014_split_003.html) - 结论依据:原文依次描述单体结构、部署层次组件、本地进程、服务四种边界形式各自的通信机制与成本(函数调用廉价频繁 vs socket/共享内存需谨慎控制 vs 网络通信几十毫秒到几秒必须严格控制),并说明现实系统常混合使用多种边界策略,直接支撑本卡片结论。 - 原始内容:这些进程无法共享其内存……最常见的情况是,这些本地进程会用socket来实现彼此的通信……服务之间的跨边界通信相对于函数调用来说,速度是非常缓慢的,其往返时间可以从几十毫秒到几秒不等……一个系统中通常会同时包含高通信量、低延迟的本地架构边界和低通信量、高延迟的服务边界。