知识卡片
本地接口细粒度、远程接口粗粒度的根本原因
内容
按类模型进行跨进程分布之所以行不通,根子在计算机的基本物理特性:进程内的过程调用非常快,两个独立进程间的调用要慢一个数量级,不同机器间的调用又要再慢一两个数量级(具体取决于网络拓扑)。这个数量级差异决定了远程使用的对象接口必须和本地使用的接口长得不一样。本地接口最好是细粒度的——比如地址类给”取城市”“取州”“设城市”“设州”各配一个独立方法,这完全符合面向对象把对象拆细以便灵活组合、覆盖、扩展的一般原则。但同样的细粒度接口搬到远程调用场景就成了灾难:既然每次方法调用都慢,就应该在一次调用里把城市、州、邮编一次性取回或更新完,而不是分三次调用——这催生出一种专门为”减少调用次数”而不是为”灵活可扩展”设计的粗粒度接口,编程上麻烦一些,但为了性能这个代价是值得付的。中间件厂商常说”本地调用照常速度执行、远程调用略慢、只在真正跨进程时才付费”,这个说法本身没错,但掩盖了一个更本质的问题:只要一个对象可能被远程访问,就必须用粗粒度接口,而本地访问的对象适合用细粒度接口——这不是可选项,而是两种物理约束下的必然设计取向,任何两个对象互操作时都该先想清楚它们之间到底是本地关系还是远程关系。
结构图:
flowchart LR
A["调用延迟数量级"] --> B["进程内调用:最快"]
A --> C["跨进程调用:慢一个数量级"]
A --> D["跨机器调用:再慢一两个数量级"]
B --> E["细粒度接口<br/>可拆分/可扩展"]
C --> F["粗粒度接口<br/>一次调用取够数据"]
D --> F
参考来源
- 位置:《企业应用架构模式》第一部分"表述"之"第7章 分布策略"之"7.2 远程接口和本地接口"(源文件:_epub-src/OEBPS/Text/000046.html)
- 结论依据:原文说明"进程内的过程调用非常快。两个独立进程间的过程调用就慢了一个数量级。在不同机器间运行过程又要慢一两个数量级……本地接口最好是细粒度接口……但是,细粒度接口不能很好地用在远程调用中……可能被远程访问的对象需要使用粗粒度接口、而本地访问的对象需要使用细粒度接口",直接支撑本卡结构图。
- 原始内容:一旦某个对象会被远程访问到,就应该使用粗粒度接口,虽然要付出更大的编程代价。显然,只有在必要时才应该这么做,应该最小化跨进程的对象协作的数量。