翻译 | 微服务架构中的 API 交互类型:查询、命令和事件

2019-06-091945

原文自国外技术社区dzone,作者为 Matt McLarty,传送门

自微服务被推行起来后,有一个一直在持续发酵的争议点,微服务间应该进行相互通信。

在 James Lewis 和 Martin Fowler 发布的 bliki 文章中谈论到,他们对通信协议中发表了以下的看法:

最常用的两种协议是带有资源 API 的 HTTP 请求响应以及轻量级信息。

从那篇文章发布后开始,似乎促进了两批代表不同立场的人的思想分裂,一批是希望使用 HTTP API 的微服务从业者,另一批是推动被作为"响应式微服务"的事件驱动架构思想的人。第一批人将引用 RESTFUL API 生态系统的稳健性作为优点,并且超过对其延迟和阻塞的担忧。另一批人围绕分布式架构中的事件溯源能力提出了有力的论据,并且指出 Apache Kafka 在投票中的受欢迎程度的上升。

与大多数像这样的技术争论一样,我相信正确的做法是接受在服务交互中你需要同时应用上同步和异步模式这个现实,并且正确的关注点应该是认识到何时使用它们。根据我的经验,当对微服务系统建模,有助于摆脱 protocol weeds。事实上,就像通过消息总线来实现同步交互一样,你也可以通过 HTTP 来实现异步交互。并不是要求读者这样做,只是强调当实现细节被抽象出来的时候,才能最好地完成系统工程。

这种类型的系统架构有一些令人兴奋的论点。领域驱动设计(DDD) — 最初是构思在面向对象编程中 — 在微服务推行过程中人气大增。它为复杂的软件系统建模提供了一个实现无关的方法,并且它的"上下文映射"在当中非常有用。Alberto Brandolini 的"事件风暴"源自于 DDD 社区,作为服务识别边界和交互的协作方法,并且,顾名思义,对事件特别地关注。我主张这些 DDD 实践论,但我不认为它们在服务和领域间如何交互的实际方面有足够多的关注。

软件传奇 Alan Kay 曾提出过面向对象编程的相关概念,他说道:

我很久之前创造了"对象"这个词,导致许多人将注意力放到这个小点上,我感到非常抱歉。而最重要的想法应该是"消息传递",产生出色的并且可拓展的系统的关键在于设计其模式的通信方式,而不是其内部属性和行为应该是什么。

鉴于服务间通信的重要性,我认为更需要关注的是指向而非行为(the arrows in whiteboard diagrams than on the boxes)。为了帮助理解,这里有一个简单的方法对服务之间的交互进行分类。依我的经验,这里仅有三种交互的类型:

  • 查询("你能否告诉我…?"):这个交互是用于当服务需要从另一个服务获得一些按需信息时
  • 命令("请你去做…?"):这个交互出现在当一个服务需要另一个服务代表它去完成一个任务(或者执行一个事件)
  • 事件("…将发生"):这个交互发生于当服务清楚一个事件已经发生,并且希望将其通知给其他对其感兴趣的服务

这里通过买咖啡来简单类比...

查询:"请问一杯带莱姆汁的拿铁咖啡要多少钱?"

命令:"请给我一杯带莱姆汁的拿铁咖啡。"[付款]

事件:"Matt,你的带莱姆汁的拿铁咖啡已经好了!"

协议在这个例子中也抽象出来了。查询或者命令会出现在人或者 app 中。事件通知通常是咖啡馆中叫喊或者电话的蜂鸣声。不管步骤是怎么执行,它们都代表你在得到一杯咖啡的任务中将要遵循的一系列一致的交互流程。

我在两年前创建的微服务设计中加入了这种交互类型,并且它帮助了微服务开发者,清晰定义其微服务接口。交互设计优先,接口定义随后。至于协议,一旦定义了交互和接口,就顺理成章了!我相信随着 HTTP 的持续优化,参见 HTTP2,以及异步协议稳健性的不断增强,参见 AsyncAPI 规范,所有方面的差距都会缩小。很明显,正确的做法并不是选择,而是找到最适合特定交互的方法。

如果想要学习更多关于微服务架构的设计原则,查阅我们的白皮书,microservices best practices

分享
点赞1
打赏
上一篇:Docker常用命令笔记(一)
下一篇:翻译 | 注意 ForkJoinPool#commonPool()