Book Building Microservices详细描述了@RogerAlsing 在他的回答中提到的样式。
在第 43 页的编排与编排下,这本书说:
随着我们开始对越来越复杂的逻辑进行建模,我们必须处理管理跨越单个服务边界的业务流程的问题。使用微服务,我们将比平时更快地达到这个限制。[...] 在实际实现此流程时,我们可以遵循两种架构风格。通过编排,我们依靠中央大脑来指导和推动这个过程,就像管弦乐队中的指挥一样。通过编排,我们告知系统的每个部分它的工作,并让它处理细节,就像舞者在芭蕾舞中都找到自己的方式并对周围的其他人做出反应。
然后本书继续解释这两种风格。编排风格更对应于 SOA 的编排/任务服务理念,而编排风格对应于 Martin Fowler 文章中提到的哑管道和智能端点。
编排风格
在这种风格下,上面的书提到:
让我们考虑一下这个流程的编排解决方案是什么样的。在这里,可能最简单的做法就是让我们的客户服务充当中央大脑。在创建时,它通过一系列请求/响应电话与忠诚度积分银行、电子邮件服务和邮政服务 [...] 进行对话。然后,客户服务本身可以跟踪客户在此过程中的位置。它可以检查客户的帐户是否已设置,是否已发送电子邮件或已发送邮件。我们可以使用流程图 [...] 并将其直接建模为代码。我们甚至可以使用为我们实现这一点的工具,也许使用适当的规则引擎。为此目的,商业工具以业务流程建模软件的形式存在。假设我们使用同步请求/响应,我们甚至可以知道每个阶段是否有效 [...] 这种编排方法的缺点是客户服务可能成为过多的中央管理机构。它可以成为网络中间的枢纽和逻辑开始存在的中心点。我已经看到这种方法导致少数智能“上帝”服务告诉基于 CRUD 的服务该做什么。
注意:我想当作者提到工具时,他指的是BPM之类的东西(例如Activity、Apache ODE、Camunda)。事实上,Workflow Patterns 网站有一组很棒的模式来进行这种编排,它还提供了不同供应商工具的评估细节,以帮助以这种方式实现它。我不认为作者暗示需要使用其中一种工具来实现这种集成风格,但可以使用其他轻量级编排框架,例如Spring Integration、Apache Camel或Mule ESB
但是,我读过的其他有关微服务主题的书籍以及我在网络上找到的大多数文章似乎都不赞成这种编排方法,而是建议使用下一种。
编舞风格
在编舞风格下,作者说:
使用精心设计的方法,我们可以改为让客户服务以异步方式发出事件,如客户创建。电子邮件服务、邮政服务和忠诚度积分银行只需订阅这些事件并做出相应的反应 [...] 这种方法明显更加分离。如果需要其他一些服务来创建客户,它只需要订阅事件并在需要时完成它的工作。缺点是我们在 [工作流] 中看到的业务流程的显式视图现在仅隐式反映在我们的系统中 [...] 这意味着需要额外的工作来确保您可以监控和跟踪正确的事情发生了。例如,您是否知道忠诚度积分银行是否存在错误并且由于某种原因没有设置正确的帐户?我喜欢处理这个问题的一种方法是构建一个监控系统,该系统明确匹配 [工作流] 中的业务流程视图,然后跟踪每个服务作为独立实体所做的事情,让您看到奇怪的异常映射到更明确的流程。[流程图] [...] 不是驱动力,而只是一个镜头,通过它我们可以看到系统的行为方式。总的来说,我发现更倾向于编排方法的系统更松散耦合,并且更灵活且易于更改。但是,您确实需要做额外的工作来监控和跟踪跨系统边界的进程。我发现大多数精心编排的实现都非常脆弱,更改成本更高。考虑到这一点,我更喜欢以精心设计的系统为目标,其中每个服务都足够聪明,可以理解它在整个舞蹈中的作用。
注意:直到今天,我仍然不确定编排是否只是事件驱动架构(EDA) 的另一个名称,但如果 EDA 只是实现它的一种方式,那么其他方式是什么?(另请参阅“事件驱动”是什么意思?和事件驱动架构的含义)。此外,CQRS 和 EventSourcing 之类的东西似乎与这种架构风格产生了很大的共鸣,对吧?
现在,在这之后是乐趣。《微服务》一书并未假设微服务将使用 REST 实现。事实上,在本书的下一节中,他们继续考虑基于 RPC 和 SOA 的解决方案,最后是 REST。这里重要的一点是,微服务并不意味着 REST。
那么,HATEOAS 呢? (超媒体作为应用程序状态的引擎)
现在,如果我们想遵循 RESTful 方法,我们不能忽略 HATEOAS,否则 Roy Fielding 会非常高兴地在他的博客中说我们的解决方案并不是真正的 REST。请参阅他关于REST API 必须是超文本驱动的博客文章:
我对将任何基于 HTTP 的接口称为 REST API 的人数感到沮丧。需要做些什么来使 REST 架构风格清楚地认识到超文本是一种约束?换句话说,如果应用程序状态引擎(以及 API)不是由超文本驱动的,那么它就不能是 RESTful 并且不能是 REST API。时期。是否有一些损坏的手册需要修复?
因此,正如您所见,Fielding 认为没有 HATEOAS,您并没有真正构建 RESTful 应用程序。对于 Fielding,HATEOAS 是编排服务的最佳选择。我只是在学习这一切,但对我来说,HATEOAS 并没有明确定义谁或什么是实际遵循这些链接的驱动力。在可能是用户的 UI 中,但在计算机到计算机的交互中,我认为这需要由更高级别的服务来完成。
根据 HATEOAS 的说法,API 消费者真正需要知道的唯一链接是启动与服务器通信的链接(例如 POST /order)。从这一点开始,REST 将执行该流程,因为在此端点的响应中,返回的资源将包含指向下一个可能状态的链接。然后,API 使用者决定遵循哪个链接并将应用程序移动到下一个状态。
尽管这听起来很酷,但客户端仍然需要知道链接是否必须被 POST、PUT、GET、PATCHed 等。客户端仍然需要决定传递什么有效负载。客户端仍然需要知道如果失败该怎么办(重试、补偿、取消等)。
我对这一切都很陌生,但对我来说,从 HATEOA 的角度来看,这个客户端或 API 使用者是一个高阶服务。如果我们从人类的角度来思考,您可以想象网页上的最终用户,决定要遵循哪些链接,但是网页的程序员仍然必须决定使用什么方法来调用链接,以及要传递的有效载荷。因此,就我而言,在计算机对计算机的交互中,计算机扮演了最终用户的角色。这就是我们所说的编排服务。
我想我们可以将 HATEOAS 与编排或编排一起使用。
API 网关模式
另一个有趣的模式是 Chris Richardson 提出的,他还提出了他所谓的API 网关模式。
在单体架构中,应用程序的客户端(例如 Web 浏览器和本机应用程序)通过负载均衡器向应用程序的 N 个相同实例之一发出 HTTP 请求。但在微服务架构中,单体应用已被服务集合所取代。因此,我们需要回答的一个关键问题是客户与什么互动?
应用程序客户端,例如本地移动应用程序,可以向各个服务发出 RESTful HTTP 请求 [...] 从表面上看,这似乎很有吸引力。但是,单个服务的 API 与客户端所需的数据之间的粒度可能存在严重的不匹配。例如,显示一个网页可能需要调用大量服务。例如,Amazon.com
描述了某些页面如何需要调用 100 多项服务。发出如此多的请求,即使是通过高速互联网连接,更不用说低带宽、高延迟的移动网络,也会非常低效并导致糟糕的用户体验。
更好的方法是让客户端通过 Internet 向称为 API 网关的前端服务器每页发出少量请求,可能只有一个。
API 网关位于应用程序的客户端和微服务之间。它提供了为客户端量身定制的 API。API 网关为移动客户端提供粗粒度 API,为使用高性能网络的桌面客户端提供更细粒度的 API。在此示例中,桌面客户端发出多个请求以检索有关产品的信息,而移动客户端发出单个请求。
API 网关通过在高性能 LAN 上向一些微服务发出请求来处理传入请求。例如,Netflix
描述
了每个请求如何平均分配到六个后端服务。在这个例子中,来自桌面客户端的细粒度请求被简单地代理到相应的服务,而来自移动客户端的每个粗粒度请求都是通过聚合调用多个服务的结果来处理的。
API 网关不仅优化了客户端和应用程序之间的通信,而且还封装了微服务的细节。这使微服务能够在不影响客户端的情况下发展。例如,可能会合并两个微服务。另一个微服务可能被划分为两个或多个服务。只有 API 网关需要更新以反映这些更改。客户不受影响。
既然我们已经了解了 API 网关如何在应用程序及其客户端之间进行中介,那么现在让我们看看如何实现微服务之间的通信。
这听起来与上面提到的编排风格非常相似,只是意图略有不同,在这种情况下,它似乎都是关于性能和交互的简化。