如果消息队列已关闭,如何在事件驱动的微服务中处理?

时间:2018-05-27 18:40:54

标签: multithreading reactive-programming message-queue microservices event-driven-design

假设在微服务环境中有两个服务 A B

在A和B之间有一个消息队列 M ,它是一个代理。

A< ----> 'M' < ----->乙

问题是,如果经纪人M关闭了吗?

我可以想到的可能的解决方案: 定期从服务A Ping,以检查消息队列 M ,只要它已关闭。与此同时,服务 A 将数据存储在本地数据库中,并在代理M启动后将其转储到队列中。

考虑到上述问题,如果有人可以建议线程或反应式编程是否最适合这种情况以及可以通过代码处理的方式,我将不胜感激。

1 个答案:

答案 0 :(得分:2)

  

问题是,如果经纪人M关闭了吗?

如果经纪人关闭,则A和B不能用它进行通信。

在这种情况下A和B应该做的事情很大程度上取决于您的特定应用/用例的细节。

他们在这种情况下可以做有用的工作吗?

如果没有,那么他们可能暂时停止尝试处理任何工作/交易,而只是等待M回来。让他们在这种状态下定期查看/查询M(查看它是否已经回来)是一个好主意。

如果他们可以在这种情况下做一些有用的事情,那么你可以让他们继续以某种“离线模式”工作,在本地缓存他们的结果,以期在未来的某个时刻M重新出现。当然,这可能会成为问题,特别是如果M长时间不回来 - 例如

  • 如果缓存的本地结果集合变得过大,那么A / B会用尽空间来存储它?
  • 或者如果A和B缓存本地结果将同时应用于M中的相同数据结构,那么当M重新联机时,A的一些结果将覆盖B(反之亦然,取决于他们重新连接的顺序)? (这类似于源代码控制服务器在几个开发人员脱机工作后必须处理的事情,都在同一个文件中对相同的行进行更改,然后他们都重新联机并希望将更改提交到该文件。它可能会变得有点复杂,而且并不总是有一种明显的“正确”方法来解决冲突。
  • 最后如果A或B“说”导致M首先崩溃了怎么办?在这种情况下,在重新联机后将相同的请求重新上传到M可能只会导致它再次崩溃,等等在无限循环中,使服务永远无法使用。 (在这种情况下,当然,正确的修复方法是调试M)

另一种方法可能是尝试通过使多个冗余代理(例如M1,M2,M3 ......)来避免问题,只要其中至少有一个仍然可用,就可以继续进行生产性工作。或者也许允许A和B直接相互沟通,而不是通过中间人。

至于这类事情是否最好由线程或反应式编程处理,这是个人偏好的问题 - 我个人更喜欢反应式编程,因为多线程风格通常意味着阻塞RPC操作,以及在阻塞操作中被阻塞的线程是一个冻结/无助的线程,直到远程方响应(例如,如果M需要2分钟来响应RPC请求,那么A对RPC的RPC调用不能返回2分钟,这意味着调用线程无法做任何事情2分钟)。在一个被动的方法中,A的线程也可以在此期间做其他事情(例如ping M以确保它没问题,或联系备份经纪人,或其他任何事情),如果它想要的话,在2分钟内。