如何保护ZeroMQ的请求回复模式,防止潜在的消息丢失?

7
我正在尝试在基于TCP层的C#应用程序和分布式python服务器之间实现ZeroMQ模式。我已经使用请求-响应REQ/REP模式制作了一个版本,在本地主机上测试时似乎相对稳定。然而,在测试中,我调试了一些情况,在接收到回复之前意外发送了多个请求,这显然是不可接受的。
实际上,网络可能会有很多丢包情况,我怀疑我将丢失很多回复并且/或无法发送请求。
1) 是否有一种方式可以重置REQ/REP请求-响应套接字之间的连接?换成REOUTER/DEALER模式是否更合理?由于这是我的第一个ZeroMQ应用程序,我希望保持简单。
2) 是否有一个很好的ZeroMQ机制来处理连接事件?我一直在阅读“指南”,里面提到了几个监控连接的例子,但没有代码示例。我发现了ZMonitor,但无法在C#中触发事件。

为什么不在REQ端使用轮询器并等待有限时间的响应。如果没有响应,应关闭/销毁套接字,创建一个新的并重试。 - jschiavon
指南中提到多次创建和销毁套接字是不良实践。显然,在上下文终止之前,底层套接字没有关闭的保证...这应该在我处置所有者时才会发生。 - UndeadBob
这取决于套接字关闭和重新打开的频率。该指南建议在“客户端可靠性(懒惰海盗模式)”部分(http://zguide.zeromq.org/page:all#Client-Side-Reliability-Lazy-Pirate-Pattern)中关闭和重新打开套接字。 - jschiavon
1个回答

8

广告1) 不行,
在ZeroMQ框架中没有向用户公开任何套接字链接管理接口,以测试/重置FSA到FSA链接状态。

是的,XREQ/XREP可以帮助您克服可能会发生的REQ/REP可扩展正式通信模式中的死锁:

参考:REQ/REP死锁 >>> https://dev59.com/Ppjga4cB1Zd3GeqPL4sW#38163015

图1: 为什么在所有情况下使用天真的REQ/REP是错误的
[1]in_WaitToRecvSTATE_W2R + [2]in_WaitToRecvSTATE_W2R时,REQ-FSA/REP-FSA有严重的相互死锁问题,永远无法达到“下一个”in_WaitToSendSTATE_W2S内部状态。
               XTRN_RISK_OF_FSA_DEADLOCKED ~ {  NETWORK_LoS
                                         :   || NETWORK_LoM
                                         :   || SIG_KILL( App2 )
                                         :   || ...
                                         :      }
                                         :
[App1]      ![ZeroMQ]                    :    [ZeroMQ]              ![App2] 
code-control! code-control               :    [code-control         ! code-control
+===========!=======================+    :    +=====================!===========+
|           ! ZMQ                   |    :    |              ZMQ    !           |
|           ! REQ-FSA               |    :    |              REP-FSA!           |
|           !+------+BUF> .connect()|    v    |.bind()  +BUF>------+!           |
|           !|W2S   |___|>tcp:>---------[*]-----(tcp:)--|___|W2R   |!           |
|     .send()>-o--->|___|           |         |         |___|-o---->.recv()     |
| ___/      !| ^  | |___|           |         |         |___| ^  | |!      \___ |
| REQ       !| |  v |___|           |         |         |___| |  v |!       REP |
| \___.recv()<----o-|___|           |         |         |___|<---o-<.send()___/ |
|           !|   W2R|___|           |         |         |___|   W2S|!           |
|           !+------<BUF+           |         |         <BUF+------+!           |
|           !                       |         |                     !           |
|           ! ZMQ                   |         |   ZMQ               !           |
|           ! REQ-FSA               |         |   REP-FSA           !           |
~~~~~~~~~~~~~ DEADLOCKED in W2R ~~~~~~~~ * ~~~~~~ DEADLOCKED in W2R ~~~~~~~~~~~~~
|           ! /\/\/\/\/\/\/\/\/\/\/\|         |/\/\/\/\/\/\/\/\/\/\/!           |
|           ! \/\/\/\/\/\/\/\/\/\/\/|         |\/\/\/\/\/\/\/\/\/\/\!           |
+===========!=======================+         +=====================!===========+

图2: 可以使用几个纯 ZeroMQ 内置工具来实现自由步进传输层,并添加一些 SIG 层工具以获取对所有可能的分布式系统状态的完全控制。 App1.PULL.recv(ZMQ.NOBLOCK)App1.PULL.poll(0) 是显而易见的。
[App1]      ![ZeroMQ]
code-control! code-control           
+===========!=======================+
|           !                       |
|           !+----------+           |         
|     .poll()|   W2R ___|.bind()    |         
| ____.recv()<----o-|___|-(tcp:)--------O     
| PULL      !|      |___|           |   :   
|           !|      |___|           |   :   
|           !|      |___|           |   :   
|           !+------<BUF+           |   :     
|           !                       |   :                           ![App2]
|           !                       |   :     [ZeroMQ]              ! code-control
|           !                       |   :     [code-control         ! once gets started ...
|           !                       |   :     +=====================!===========+
|           !                       |   :     |                     !           |
|           !                       |   :     |         +----------+!           |
|           !                       |   :     |         |___       |!           |
|           !                       |   :     |         |___| <--o-<.send()____ |
|           !                       |   :<<-------<tcp:<|___|   W2S|!      PUSH |
|           !                       |   :    .connect() <BUF+------+!           |
|           !                       |   :     |                     !           |
|           !                       |   :     |                     !           |
+===========!=======================+   :     +=====================!===========+

Ad 2) 不可以,但是可以创建自己的“ZeroMQ可消费品”,以测试分布式系统设置新传输/信令套接字的能力,如果RTO测试未能证明(多个)双方准备好在ZeroMQ基础设施上进行设置和通信,则准备处理它并丢弃它(请注意,问题不仅在于ZeroMQ层,而且应用程序端可能没有准备好/处于这种状态来处理预期的通信交互(并可能导致软锁定/死锁)。

最好的下一步是什么?

我现在可以为您进一步的问题提供帮助,引导您查看有关该主题的更大画面 >>>,其中包含更多论点,一个简单的信令平面/消息平面说明和来自Pieter HINTJENS的必读书籍的直接链接


2
哦,我的天。我不知道死锁的事情。我还需要多读一些相关的内容。感谢你的推动。 - UndeadBob
1
他们为什么又封禁你了?我查看了聊天记录,没有发现任何问题,只是好奇 :) - mlvljr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接