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

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

贺靖
2023-03-14

脚本

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

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

系统采用事件驱动架构。当客户下预订订单时,我在预订应用编程接口中提交本地交易并发布事件。支付应用编程接口和通知应用编程接口订阅了各自的事件。一旦完成,支付和通知应用编程接口需要向预订应用编程接口确认。

我的问题是

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

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

活动采购

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

非常感谢,

共有3个答案

东郭俊楠
2023-03-14

我不是百分之百确定你在问什么。但听起来你应该使用信息服务。正如@Saptarshi Basu提到的,Kafka很好。我真的会推荐NAT——尽管我有偏见,因为这是我的工作对象

使用NAT,您可以创建请求-回复消息,以在客户端和预订服务之间建立接口。这是一种1-1的交流

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

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

这将为您提供一个非常有弹性和可扩展的架构,而NATS使这一切变得非常简单

拓拔嘉颖
2023-03-14

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

感谢skjagini。我的部分问题是处理其他微服务没有及时返回或永远不会返回的情况。假设支付api已完成工作并向客户端收费,但没有及时或在很长时间后通知我的订单服务。我的客户端如何等待?如果我们超时客户端,后端可能会在超时后处理它

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

客户端发送请求--

支付API订阅支付队列--

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

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

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

如果任何服务无法处理,一旦服务重新启动,它们应该能够选择停止的位置,如果服务在事务处理过程中停止,只要它们回滚其resp更改,系统就应该处于稳定状态

史烨
2023-03-14

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

>

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

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

    >

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

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

    客户无需投票。结果将通过使用websocket的流媒体传播到它。当消费者在缓存中写入反馈时,UI页面将监听websocket,它也可以写入websocket。这将通知用户界面。然后,如果使用Angular或ReactJS之类的工具,可以使用在websocket上接收到的值刷新UI的相应部分。在此之前,用户会一直看到订单创建时写入缓存的状态“进行中”,即使用户刷新页面,也会从缓存中检索到相同的状态。如果缓存值过期并遵循LRU机制,则将从数据库中提取相同的值,并重新写入缓存以服务于未来的请求。一旦其他服务的反馈可用,新结果将使用websocket流式传输。在页面刷新时,缓存或数据库将提供新状态

  •  类似资料:
    • 我到处都读到微服务中的服务对服务调用应该是异步的。当请求必须通过2个或多个异步服务时,我们如何进行客户端确认? 这是我的实时场景。我们正在我们的组织中开发电子邮件发送功能。我们计划按以下顺序为此提供4个API服务。 公共API-将电子邮件功能公开给公共 验证API-验证电子邮件和其他字段的真实性 模板获取API-从数据库/CMS中获取电子邮件模板并准备要发送的最终内容 电子邮件发送API-将接收收

    • Lazy 微服务客户端 Sometimes you have to load initial data before you can create your @Client(). In this case, you can use ClientProxyFactory, which provides create() method. 有时候在创建@Client()之前你需要加载原始数据。这时,你可

    • 我有一个包含10个微服务的微服务架构,每个微服务提供一个客户端。在由微服务团队管理/控制的客户机内部,我们只接收参数并将它们传递给一个通用http调用程序,该调用程序接收endpoint和N个params,然后进行调用。所有微服务都使用http和web api(我猜技术并不重要)。 对于我来说,作为微服务团队提供一个客户是没有意义的,应该是消费者的责任,如果他们想创建一些抽象或者直接调用它是他们的

    • 我有两个用Jhipster创建的微服务。(ms1和ms2) ms1有一些DTO类,用作REST API的输入和输出类。 从ms2我需要调用ms1的一些API,因此我需要那些DTO类来输入和输出数据。 MS2中显然没有这些DTO类。 所以我现在有两个选择: 1)将DTO类从ms1复制到ms2 2)将ms1导入为ms2中的maven依赖项 方法2-ms1和ms2都被打包为war文件,而不是jar文件。

    • 客户端事件通过 SetEvent 方法进行设置。 客户端事件有两个,它们分别定义为: type onErrorEvent interface { OnError(name string, err error) }   type onFailswitchEvent interface { OnFailswitch(Client) } 因为 go 语言不需要显式实现接口的特点,所以这两

    • 我想在一些计算机之间建立点对点连接,这样用户就可以在没有外部服务器的情况下聊天和交换文件。我最初的想法如下: 我在服务器上制作了一个中央服务器插座,所有应用程序都可以连接到该插座。此ServerSocket跟踪已连接的套接字(客户端),并将新连接的客户端的IP和端口提供给所有其他客户端。每个客户端都会创建一个新的ServerSocket,所有客户端都可以连接到它。 换句话说:每个客户端都有一个Se