微服务客户端确认和事件溯源

Imr*_*had 5 architecture design-patterns asynchronous event-handling microservices

设想

我正在使用微服务构建快递服务系统。我不确定一些事情,这是我的场景

  1. 预订 API - 这是客户下订单的地方
  2. 付款 API - 这是我们处理预订付款的地方
  3. 通知 API - 该服务负责在一切完成后发送通知。

该系统采用事件驱动架构。当客户下预订订单时,我在预订 API 中提交本地事务并发布事件。支付 API 和通知 API 订阅各自的事件。完成付款和通知 API 后,需要向 Booking API 确认。

我的问题是

发布活动后,我的预订服务无法阻止呼叫并返回到客户端(前端)。我的客户端应用程序必须如何检查交易状态或者知道交易已完成?它每隔几秒轮询一次吗?由于这是分布式事务,任何服务都可能出现故障并且无法回复。在这种情况下,我的客户端(前端)怎么知道,因为它会继续等待。我正在考虑分布式事务的传奇。

实现这一切的最佳方法是什么?

事件溯源

我想实施事件溯源来跟踪预订订单的完整轨迹。我是否必须在我的预订 API 中使用事件存储来实现此功能?或者事件存储在服务之间共享,因为我应该捕获来自不同服务的所有事件。实现这一点的最佳方法是什么?

非常感谢,

Sap*_*asu 3

我对此进行可视化的方式如下(受 Martin Kleppmann 的演讲影响

  1. 最终用户下订单。该订单写入 Kafka 主题。由于Kafka具有日志结构化存储,因此订单详细信息将在尽可能短的时间内保存。这是一个原子操作(“ACID”中的“A”)——全有或全无
  2. 现在,一旦用户下了订单,用户就会想读回它(读你所写的)。为了实现这一点,我们也可以将订单数据写入分布式缓存中。虽然双重写入通常不是一个好主意,因为它可能会导致部分失败(例如写入 Kafka 成功,但写入缓存失败),但我们可以通过确保其中一个 Kafka 使用者将数据写入数据库来减轻这种风险。因此,即使在罕见的缓存失败情况下,用户最终也可以从数据库读回数据。
  3. 订单创建时写入缓存中的订单状态为“进行中”
  4. 然后使用一个或多个kafka消费者组来处理事件,如下所示:正确处理付款和通知,并将最终状态写回缓存和数据库
  5. 然后,单独的 Kafka 消费者将接收来自支付和通知 API 的响应,并将更新写入缓存、数据库和 Web 套接字

  6. 然后,websocket 将更新 UI 模型,并且更改将通过事件源反映在 UI 中。

根据评论进一步澄清

  1. 这里的基本思想是,我们使用流式传输为每个服务及其所需的数据构建一个缓存。例如,帐户服务需要来自支付和通知服务的反馈。因此,我们让这些服务将响应写入某个 Kafka 主题,该主题有一些消费者将响应写回订单服务的缓存

  2. 基于 Kafka(或任何类似技术)的 ACID 属性,消息永远不会丢失。最终我们要么得到全部,要么一无所有。这就是原子性。如果订单服务无法写入订单,则会以同步方式向客户端发送错误响应,用户可能会在一段时间后重试。如果订单服务成功,对其他服务的响应最终必须流回其缓存。如果其中一项服务宕机一段时间,响应将会延迟,但最终会在服务恢复时发送

  3. 客户端不需要轮询。结果将通过使用 websocket 的流式传输传播给它。UI页面将监听websocket,当消费者将反馈写入缓存时,它也可以写入websocket。这将通知 UI。然后,如果您使用 Angular 或 ReactJS 之类的东西,则可以使用 websocket 接收到的值刷新 UI 的相应部分。在此之前,用户会一直看到订单创建时写入缓存的“进行中”状态,即使用户刷新页面,也会从缓存中检索到相同的状态。如果缓存值过期并遵循 LRU 机制,将从数据库中获取相同的值并将其写回缓存以服务将来的请求。一旦其他服务的反馈可用,新结果将使用 websocket 进行流式传输。页面刷新时,可以从缓存或数据库获取新状态