微服务与分布式对象第一定律

2014年8月13日

在我撰写《企业应用架构模式》时,我提出了我称之为“分布式对象设计第一定律”的原则:**“不要分布你的对象”。** 近几个月来,人们对微服务的兴趣日益浓厚,这也让一些人质疑微服务是否违反了这条定律,如果违反了,为什么我还支持微服务?

需要注意的是,在第一定律的表述中,我使用了“分布式对象”一词。这反映了90年代末和00年代初相当流行的一种想法,但后来(正确地)失宠了。分布式对象的想法是,你可以设计对象,并选择在进程内或远程使用这些相同的对象,远程可能意味着同一台机器上的另一个进程,或者在不同的机器上。聪明的中间件,如DCOM或CORBA实现,将处理进程内/远程的区别,因此你的系统可以被编写,并且你可以将其分解成进程,而与应用程序的设计方式无关。

我反对分布式对象的概念,是因为虽然你可以在对象边界后面封装很多东西,但你不能封装远程/进程内的区别。进程内函数调用速度快,而且总是会成功(因为任何异常都是由于应用程序造成的,而不是由于进行调用的事实造成的)。然而,远程调用要慢几个数量级,而且由于远程进程或连接失败,调用总是存在失败的可能性。

这种差异的结果是,你的API指南是不同的。在进程内调用可以是细粒度的,如果你想要100个产品的价格和可用性,你可以轻松地对你的产品价格函数进行100次调用,对可用性再进行100次调用。但是,如果该函数是远程调用,你通常最好将所有这些调用批处理成一个调用,一次性请求所有100个价格和可用性。结果是你的产品对象有了一个非常不同的接口。因此,你不能使用相同的类(主要是关于接口),并以透明的方式在进程内或远程使用它。

我交流过的微服务倡导者都非常清楚这种区别,我从未听过他们中的任何一个人谈论进程内/远程的透明性。所以他们并没有试图做分布式对象试图做的事情,因此也没有违反第一定律。相反,他们主张通过HTTP或轻量级消息传递与文档进行粗粒度的交互。

所以,从本质上讲,我对分布式对象的看法与微服务的倡导者之间并没有矛盾。尽管存在这种本质上的不冲突,但现在还有一个问题亟待提出。微服务意味着小的分布式单元,它们通过远程连接进行通信的次数远远超过单体应用。这难道不违背了第一定律的精神,即使它满足了第一定律的字面意思?

虽然我确实承认,对于许多系统来说,进行分布式设计是有正当理由的,但我确实认为分布式会增加复杂性。粗粒度的API比细粒度的API更难用。你需要决定如何处理远程调用失败,以及对一致性和可用性的影响。即使你通过协议设计将远程调用减到最少,你仍然需要更多地考虑围绕它们的性能问题。在设计单体应用时,你需要担心模块之间的职责分配,而在分布式系统中,你需要担心模块之间的职责分配和分布因素。

虽然小型微服务当然更容易理解,但我担心这会将复杂性推到服务之间的互连中,在那里它不那么明显,因此更难在出错时找出问题所在。当你必须跨越远程边界进行重构时,重构就会变得更加困难。微服务倡导者吹捧异步通信带来的耦合减少,但异步是另一个复杂性助推器。Cookie-cutter 缩放允许你在不增加分布式复杂性的情况下处理大量的流量。

因此,我对分布式持谨慎态度,我默认的倾向是更喜欢单体设计。鉴于此,为什么我花了这么多精力来描述微服务,并支持我的同事们倡导它?答案是因为我知道我的直觉并不总是正确的。我不能否认,许多团队已经采用了微服务方法,并取得了成功,无论是像Netflix和(可能)亚马逊这样广为人知的公开案例,还是我在Thoughtworks内外交流过的各种团队。我天生就是一个经验主义者,相信经验证据胜过理论,即使这个理论比我的直觉要完善得多。

并不是说我认为这件事已经尘埃落定了。在软件交付中,成功是一件非常难以界定的事情。尽管像Netflix和Spotify这样的组织已经吹嘘了他们早期在微服务方面的成功,但也有一些例子,比如Etsy或Facebook,他们使用更加单体的架构也取得了成功。无论一个团队认为自己在微服务方面有多么成功,唯一真正的比较是反事实的——如果他们使用单体应用,他们会做得更好吗?微服务方法出现的时间还比较短,所以我们没有太多来自十年历史的遗留微服务架构的证据,可以将其与我们非常不喜欢的那些老旧的单体应用进行比较。而且,可能还有一些我们尚未发现的因素,这意味着在某些情况下,单体应用更好,而在其他情况下,微服务更有利。鉴于在软件开发中收集证据的难度,即使在许多年后,也不太可能有一个令人信服的决定来支持其中一方。

鉴于这种不确定性,像我这样的作者能做的最重要的事情就是尽可能清楚地传达我们认为我们已经学到的东西,即使它们是矛盾的。读者会做出自己的决定,而我们作为作者的工作就是确保这些决定是明智的,无论他们站在架构的哪一边。


延伸阅读

我和我的同事James Lewis合著的文章是我们试图对微服务架构风格进行定义的尝试。我在我的著作《企业应用架构模式》中提出了分布式对象的第一定律,它出现在第7章:“分布式策略”。本章还由Dr Dobb's以错误的架构为题免费在线发表。

分布式计算的谬误是对为什么人们应该警惕任何认为分布式可以透明地(或容易地)完成的观点的经典阐述。Waldo等人的关于分布式计算的说明是对分布式对象的基本问题的极好阐述。