如果消息队列关闭,如何在事件驱动的微服务中处理?
How to handle in Event Driven Microservices if the messaging queue is down?
假设微服务环境中有两个服务A和B。
在 A 和 B 之间有一个消息队列 M,它是一个代理。
A<---->'M'<----->B
问题是如果代理 M 宕机了怎么办?
我能想到的可能的解决方案:
只要消息队列 M 处于关闭状态,就会定期从服务 A 执行 Ping 操作以检查消息队列 M。与此同时,服务 A
将数据存储在本地数据库中,并在代理 M 启动后将其转储到队列中。
考虑到上述问题,如果有人可以建议线程或反应式编程是否最适合这种情况以及如何通过代码处理它,我将不胜感激。
The problem is what if the broker M is down?
如果 broker 挂了,那么 A 和 B 就不能用它来通信了。
A 和 B 在这种情况下应该做什么将在很大程度上取决于您的特定 application/use-case 的细节。
在那种情况下,他们可以做哪些有用的工作?
如果没有,那么他们不妨暂时停止尝试处理任何 work/transactions,而是坐等 M 回来。让他们在这种状态下定期 pings/queries M(看看它是否回来了)是个好主意。
如果他们可以在这种情况下做一些有用的事情,那么您可以让他们继续以某种方式工作 "offline mode",将他们的结果缓存在本地,以期待 M 将来某个时候再次出现.当然,这可能会成为问题,特别是如果 M 很长时间没有恢复——例如
- 如果缓存的本地结果集变得异常大,以至于 A/B 用完 space 来存储它怎么办?
- 或者,如果 A 和 B 缓存本地结果,这些结果都将应用于 M 中的相同数据结构,这样当 M 重新联机时,A 的某些结果将覆盖 B 的结果(反之亦然,取决于他们重新连接的顺序)? (这类似于源代码控制服务器在几个开发人员离线工作后必须处理的事情,他们都对同一文件中的相同行进行了更改,然后他们都重新联机并希望将他们的更改提交到该文件。它可能会变得有点复杂,并且并不总是有明显的 "correct" 解决冲突的方法)
- 最后,如果首先导致 M 崩溃的是 A 或 B "said" 怎么办?在那种情况下,在 M 重新上线后将相同的请求重新上传到 M 可能只会导致它再次崩溃,如此无限循环,使服务永远无法使用。 (在这种情况下,当然,正确的解决方法是调试 M)
另一种方法可能是尝试通过拥有多个冗余代理(例如 M1、M2、M3 等)来避免此问题,这样只要其中至少一个仍然可用,就可以继续进行生产性工作.或者允许 A 和 B 直接相互通信,而不是通过中介。
至于这种事情最好由线程还是反应式编程来处理,那是个人喜好问题——我个人更喜欢反应式编程,因为多线程风格通常意味着阻塞-RPC-操作,并且在阻塞操作中被阻塞的线程是 frozen/helpless 线程,直到远程方响应(例如,如果 M 需要 2 分钟来响应 RPC 请求,那么 A 对 M 的 RPC 调用不能 return 2 分钟,这意味着调用线程在 2 分钟内无法做任何事情)。在反应性方法中,A 的线程也可以在此期间做其他事情(例如 ping M 以确保它没问题,或者联系备份代理,或者其他任何事情)在那 2 分钟的时间段内,如果它愿意的话。
假设微服务环境中有两个服务A和B。
在 A 和 B 之间有一个消息队列 M,它是一个代理。
A<---->'M'<----->B
问题是如果代理 M 宕机了怎么办?
我能想到的可能的解决方案: 只要消息队列 M 处于关闭状态,就会定期从服务 A 执行 Ping 操作以检查消息队列 M。与此同时,服务 A 将数据存储在本地数据库中,并在代理 M 启动后将其转储到队列中。
考虑到上述问题,如果有人可以建议线程或反应式编程是否最适合这种情况以及如何通过代码处理它,我将不胜感激。
The problem is what if the broker M is down?
如果 broker 挂了,那么 A 和 B 就不能用它来通信了。
A 和 B 在这种情况下应该做什么将在很大程度上取决于您的特定 application/use-case 的细节。
在那种情况下,他们可以做哪些有用的工作?
如果没有,那么他们不妨暂时停止尝试处理任何 work/transactions,而是坐等 M 回来。让他们在这种状态下定期 pings/queries M(看看它是否回来了)是个好主意。
如果他们可以在这种情况下做一些有用的事情,那么您可以让他们继续以某种方式工作 "offline mode",将他们的结果缓存在本地,以期待 M 将来某个时候再次出现.当然,这可能会成为问题,特别是如果 M 很长时间没有恢复——例如
- 如果缓存的本地结果集变得异常大,以至于 A/B 用完 space 来存储它怎么办?
- 或者,如果 A 和 B 缓存本地结果,这些结果都将应用于 M 中的相同数据结构,这样当 M 重新联机时,A 的某些结果将覆盖 B 的结果(反之亦然,取决于他们重新连接的顺序)? (这类似于源代码控制服务器在几个开发人员离线工作后必须处理的事情,他们都对同一文件中的相同行进行了更改,然后他们都重新联机并希望将他们的更改提交到该文件。它可能会变得有点复杂,并且并不总是有明显的 "correct" 解决冲突的方法)
- 最后,如果首先导致 M 崩溃的是 A 或 B "said" 怎么办?在那种情况下,在 M 重新上线后将相同的请求重新上传到 M 可能只会导致它再次崩溃,如此无限循环,使服务永远无法使用。 (在这种情况下,当然,正确的解决方法是调试 M)
另一种方法可能是尝试通过拥有多个冗余代理(例如 M1、M2、M3 等)来避免此问题,这样只要其中至少一个仍然可用,就可以继续进行生产性工作.或者允许 A 和 B 直接相互通信,而不是通过中介。
至于这种事情最好由线程还是反应式编程来处理,那是个人喜好问题——我个人更喜欢反应式编程,因为多线程风格通常意味着阻塞-RPC-操作,并且在阻塞操作中被阻塞的线程是 frozen/helpless 线程,直到远程方响应(例如,如果 M 需要 2 分钟来响应 RPC 请求,那么 A 对 M 的 RPC 调用不能 return 2 分钟,这意味着调用线程在 2 分钟内无法做任何事情)。在反应性方法中,A 的线程也可以在此期间做其他事情(例如 ping M 以确保它没问题,或者联系备份代理,或者其他任何事情)在那 2 分钟的时间段内,如果它愿意的话。