微服务客户确认和活动来源



场景

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

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

系统使用事件驱动的体系结构。当客户下订单时,我在预订API中提交本地交易并发布事件。支付API和通知API订阅各自的事件。一旦完成付款和通知API需要确认返回预订API。

我的问题是

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

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

活动来源

我想实现事件来源来跟踪预订订单的完整跟踪。我是否必须在我的活动商店预订API中实现这一点?或者事件存储在服务之间共享,因为我应该捕获来自不同服务的所有事件。实现这一点的最佳方式是什么?

非常感谢,

我将其可视化的方式如下(受Martin Kleppmann在这里和这里的演讲影响)。

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

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

基于评论的进一步澄清

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

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

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

预订完成后,您可以将标识符传递回客户端,如果您可以在后端连接后续操作,则客户端可以使用此标识符查询后续操作的状态。当其他事件完成时,您也可以向客户端发回通知。您可以进行长时间轮询,也可以进行通知。

感谢skjagini。我的部分问题是处理一个其他微服务无法及时恢复或永远无法恢复。假设支付api是完成工作并向客户收费,但没有通知我的订单服务及时或经过很长时间。我的客户如何等待?如果我们超时客户端后端可能在超时后处理了它

在CQRS中,您可以将命令和查询分开。即,考虑到您的场景,您可以使用Queues实现所有交互。(有多种具有事件源的CQRS实现,但形式最简单):

客户端发送请求-->支付API接收请求-->验证请求(如果验证失败,则向用户返回错误)-->验证成功时-->生成GUID并将消息请求写入队列-->将GUID传递给用户

支付API订阅支付队列-->处理请求后-->写入订单队列或任何其他队列

订单APi订阅订单队列并处理请求。

用户有一个GUID,可以为他获取所有交互的数据。

如果在Kafka中使用pub/sub而不是Kafka(所有其他后续系统都可以从同一主题中读取,您不需要为每个队列编写)

如果任何服务无法处理,一旦服务被重新启动,他们应该能够选择他们停止的地方,如果服务在事务处理过程中停止,只要他们回滚他们的resp更改,你的系统应该是稳定的条件

我不能100%确定你在问什么。但听起来你应该使用消息服务。正如@Saptarshi Basu提到的那样,卡夫卡很好。我真的很推荐NATS——尽管我有偏见,因为这是我与合作的一个

使用NATS,您可以创建请求回复消息,以便在客户和预订服务之间建立接口。这是1-1通信

如果每个服务都有多个实例在运行,则可以使用队列服务自动实现负载平衡。NATS只会为您随机选择一个服务器

然后,您可以使用酒吧订阅源在所有服务之间进行通信。

这将为您提供一个非常有弹性和可扩展的体系结构,NATS使变得非常容易

相关内容

  • 没有找到相关文章

最新更新