当前位置: 首页 > 知识库问答 >
问题:

是否可以将 REST 和消息传递结合起来用于微服务?

长孙昀
2023-03-14

我们有基于微服务架构的应用程序的第一个版本。我们使用REST进行外部和内部通信。

现在我们想从 CP(CAP 定理)* 切换到 AP,并使用消息总线在微服务之间进行通信。有很多关于如何基于 Kafka、RabbitMQ 等创建事件总线的信息。但是我找不到任何结合 REST 和消息传递的最佳实践。例如,您创建一个汽车服务,您需要添加不同的汽车组件。为此,将 REST 与 POST 请求一起使用会更有意义。另一方面,对于基于事件的方法来说,预订汽车的服务将是一个很好的任务。

当您具有不同的字典和业务逻辑功能时,您是否具有类似的方法?你如何组合它们?只是分别支持这两种方法?还是将它们统一在一种方法中?

*对于第一个版本,我们同意选择一致性和分区容差。但现在可用性对我们来说变得更加重要。

共有1个答案

鲜于煜祺
2023-03-14

最重要的一点是:您正在寻找命令查询职责分离;它定义了一种架构模式,用于将职责从查询数据分解为请求运行流程。简单的答案是,您不希望在查询或流程中以阻塞方式混合这两者。这个答案的其余部分将详细说明为什么,以及你能做你想做的事情的三种不同方式。

这个答案是我对微服务经验的简短形式。我的真诚:我从头开始创建了微服务拓扑(并且知识几乎为零),正如他们所说,在下降的过程中击中了每个分支。

从零知识开始的好处之一是,我创建的第一个拓扑使用了服务内同步和阻塞(HTTP)通信(从持有该通信的服务中检索操作所需的数据)和消息队列异步事件(用于命令)的混合。

我将定义这两个术语:

命令:告诉服务做某事。例如,“运行ETL批处理作业”。你期望有一个输出。但这必然是一个你无法可靠等待的过程。命令有副作用。有些事情会因为这个动作而改变(如果什么都没发生,什么都没改变,那你什么都没做)。

查询:向服务请求它拥有的数据。这些数据可能是因为某个命令而存在的,但是请求数据应该不会有副作用。不需要因为收到查询而运行任何命令操作。

无论如何,回到拓扑。

对于第一个拓扑,我们将同步查询与发出的异步事件混合在一起。这是...问题。

消息总线本质上是可观察的。RabbitMQ或事件源中的一个设置,您可以观察系统中的所有事件。这有一些好的副作用,因为当过程中发生一些事情时,您通常可以弄清楚是什么事件导致了这种状态(如果您遵循事件驱动的范式状态机)。

如果不检查网络流量或记录这些请求,就无法观察到HTTP调用(这本身就有问题,因此我们将从正常操作中的“不可行”开始)。因此,如果你混合使用基于消息的进程和HTTP调用,你将有洞,你无法分辨发生了什么。由于网络错误,您的 HTTP 调用没有返回数据,并且您的服务因此没有继续该过程。您还需要为 HTTP 调用挂接重试/断路器模式,以确保它们至少尝试几次,但随后您必须区分“不启动,因为它已关闭”和“不启动,因为它暂时繁忙”。

简言之,将这两种方法混合用于命令驱动流程并不是很有弹性。

在这个成熟度模型的第二步中,您将命令和查询分离出来。命令应该使用事件驱动系统,查询应该通过HTTP进行。如果您需要一个命令的查询结果,那么您可以通过消息总线发出一条消息并使用请求/响应模式。

这也有好处和问题。

从好处来看,您的整个命令现在是可观察的,即使它在多个服务之间跳跃。您还可以通过重新运行事件来重播系统中的进程,这对于跟踪问题非常有用。

问题方面,现在您的一些事件看起来很像查询;您现在正在为消息重新创建 HTTP 中可用的漂亮 HTTP 和 REST 语义;这不是非常有趣或有用。例如,404 告诉您 REST 中没有数据。对于基于消息的事件,您必须重新创建这些语义(关于我找不到的主题的很好的 Youtube 会议演讲,但一个团队试图非常痛苦地做到这一点)。

但是,您的事件现在是异步和非阻塞的,并且每个服务都可以重构为将响应给定事件的状态机。一些警告是,这些事件应包含操作所需的所有数据(这会导致消息在流程过程中增长)。

您的查询仍然可以使用HTTP进行外部通信;但是对于内部命令/进程,您应该使用消息总线。

我也不推荐这种方法(尽管它比第一种方法进步了一步)。我不建议这样做,因为您的事件开始呈现出杂质,而且在微服务系统中,整个系统中的合同都是相同的非常重要。

成熟度模型的第三步(当我离开这个项目时,我们正在走向这个范式)是让产生数据的服务在产生数据时发出事件。然后,这些数据由侦听这些事件的服务记下,这些服务将使用这些(可能是?)陈旧数据来进行操作。外部客户仍然使用HTTP;但在内部,当产生新数据时,您会发出事件,每个关心这些数据的服务都会存储它,以便在需要时使用。这就是Michael Bryzek演讲“设计微服务架构的正确方式”的症结。Michael Bryzek是白标电子商务公司Flow.io的首席技术官。

如果你想得到更深入的答案,以及其他正在讨论的问题,我会告诉你我关于这个问题的博客文章。

 类似资料:
  • 我听说亚马逊使用HTTP作为其基于微服务的架构。另一种方法是使用RabbitMQ或Solace Systems这样的消息传递系统。我个人对基于Solace的微服务架构有经验,但从未使用过REST。 知道像Amazon、Netflix、UK Gov等各种大联盟实现使用什么吗? 其他方面是,在微服务中,还需要以下东西(除了其他东西): *模式匹配 *异步消息传递。接收系统可能已关闭 *发布订阅 *缓存

  • 我已经检查的内容: 我曾考虑用QueryDSL生成SQL查询字符串,并在MyBatis中使用它的'@SelectProvider'注释,但这似乎是一个死胡同:MyBatis在它的SQL字符串中需要“${xxx}”的东西,但QueryDSL只生成基于实际Java类型的查询,所以它甚至对ID也不起作用。 作为querydsl/jooq的替代方案的mybatis生成器:相当糟糕的替代方案,因为它实际上生

  • 我正在计划开发一个基于微服务的架构应用程序,当我阅读Ronnie Mitra的书《微服务架构》时,我决定使用Kafka进行内部通信;马特·麦克拉蒂;迈克·阿蒙森;伊拉克利·纳达雷什维利说: 让微服务直接与消息代理(如RabbitMQ等)交互很少是个好主意。如果两个微服务通过消息队列通道直接通信,那么它们共享一个数据空间(通道),我们已经详细讨论了两个微服务共享一个数据空间的弊病。相反,我们可以做的

  • 新服务器密钥是否仅限于消息传递? 说明:在firebase项目设置中,我可以获得“旧”和新服务器密钥(云消息选项卡)。旧版本无法通过发送推送通知https://fcm.googleapis.com/fcm/send 因为响应说它是一个遗留服务器密钥。但在这里,它可以被限制在某些谷歌API中https://console.developers.google.com/apis. 谷歌API控制台中没有

  • 我对尝试将微服务/SOA作为一种体系结构非常感兴趣,并且很难对服务之间的集成进行概念化。 我喜欢使用消息传递将客户端与服务分离的想法,但不理解系统如何独占地使用它。典型的异步操作和发布/订阅显然是有意义的——比如创建新订单、广播数据以进行报告等。我不明白的是,人们是否通常尝试在常见的请求/回复场景中使用消息传递——例如,用户点击他们的“个人资料”页面,而需要在页面上呈现的部分数据来自用户服务。 我

  • 我们正在设计我们的新系统,它很可能是从头开始编写的,因为旧系统非常非常旧。对我们的系统来说,保留系统中发生的所有事情的审计跟踪日志非常重要。 由于审计跟踪的重要性,我们决定遵循事件源架构以获得它的所有好处。另一个关键因素是我们有多个团队在不同的“域”上工作。也就是说,我们想将每个域拆分为自己的服务(微服务架构),这样每个团队都可以独立工作。 我们面临的最大问题是谁将负责微服务之间的事件共享。例如,