微服务架构 - 在订单无关紧要时通过服务传递消息

时间:2017-12-21 05:21:21

标签: design-patterns architecture rabbitmq message-queue microservices

Tl; dr :“我如何通过一堆异步,无序的微服务推送消息,并知道该消息何时通过它们?”

我正在努力为特定的微服务架构找到合适的消息传递系统/协议。这不是一个“哪个是最好的”问题,而是一个关于我对设计模式/协议的选择的问题。

Diagram

  • 我在开始队列中有消息。假设带有序列化JSON的RabbitMQ消息
  • 我需要该消息通过任意数量的微服务
  • 每个微服务都是长期运行的,必须是独立的,并且可以用各种语言实现
  • 消息通过的服务顺序无关紧要。实际上,它不应该是同步的。
  • 每个服务都可以数据追加到原始邮件中,但其他服务会忽略该数据。应该有 no 合并冲突(每个服务写一个唯一的密钥)。任何服务都不会改变或破坏数据。
  • 一旦所有服务轮到,就应该将消息发布到包含原始数据和新数据的第二个RabbitMQ队列。
  • 微服务没有其他副作用。如果这些都在一个单一的应用程序中(并且使用相同的语言),那么函数式编程将是完美的。

所以,问题是,通过各种服务管理该消息的适当方式是什么?我想要一次做一个,订单并不重要。但是,如果是这种情况,那么系统如何知道所有服务何时发生了重击并且最终消息可以写入结束队列(以便让下一批服务完成)。

我能想到的唯一,半优雅的解决方案是

  1. 让第一个遇到消息的服务将该消息写入公共存储(比如mongodb)
  2. 让每个服务做它的事情,标记它已完成该消息,然后检查所有服务是否已经轮到
  3. 如果是,那最后一项服务将发布消息
  4. 但是仍然需要每个服务都知道所有其他服务要求每个服务留下它的标记。这些都不是必需的。

    我愿意接受某种“牧羊人”服务。

    我很感激我错过的任何选择,并且愿意承认他们可能是一个更好的,基本的设计。

    谢谢。

2 个答案:

答案 0 :(得分:11)

管理长时间运行的流程(或涉及多个微服务的处理)有两种方法:编排和编排。有很多文章描述它们。

长话短说:在业务流程中,您有一个跟踪流程状态的微服务,在编排中,所有微服务都知道在哪里发送下一条消息和/或完成该过程。

article解释了这两种风格的好处和交易。

<强>编排 Orchestration

协调优势

  • 提供了一种在进行同步处理时控制应用程序流的好方法。例如,如果服务A需要在调用服务B之前成功完成。

业务流程权衡

  • 将服务结合在一起创建依赖关系。如果服务A关闭,将永远不会调用服务B和C.

  • 如果所有请求都有orchestrator的中央共享实例,则协调器是单点故障。如果它发生故障,所有处理都会停止。

  • 利用阻止请求的同步处理。在此示例中,总端到端处理时间是服务A +服务B +服务C被调用所花费的时间总和。

<强>编排 Choreography

编排优势

  • 实现更快的端到端处理,因为服务可以并行/异步执行。

  • 更容易添加/更新服务,因为它们可以轻松插入/退出事件流。

  • 与敏捷交付模式很好地协调,因为团队可以专注于特定服务而不是整个应用程序。

  • 控制是分布式的,因此不再有单个协调器作为中心故障点。

  • 多种模式可与反应式架构一起使用,以提供额外的好处。例如,Event Sourcing是事件流存储所有事件并启用事件重放的时间。这样,如果服务在事件仍然产生时停止,当它重新联机时,它可以重播这些事件以便恢复。此外,可以应用命令查询责任隔离(CQRS)来分离读取和写入活动。这使得每个都可以独立缩放。如果您的应用程序读取繁重且写入较轻,反之亦然,这会派上用场。

编排权衡

  • 异步编程通常是开发人员的重要思想转移。我倾向于认为它类似于递归,在那里你无法通过查看它来弄清楚代码将如何执行,你必须考虑在特定时间点可能存在的所有可能性。

  • 复杂性发生了变化。流控制现在被分解并分布在各个服务中,而不是将流控制集中在协调器中。每个服务都有自己的流逻辑,这个逻辑将根据事件流中的特定数据确定何时以及如何做出反应。

答案 1 :(得分:1)

我会考虑常见的存储理念。

让每个微服务注册自己的公共存储。让每个微服务注册它已经处理了消息标识符。

您可以确定哪些服务应该处理它以及有多少n服务已经处理过它。

没有服务需要彼此了解。