20

私は今週ZeroMQを使い始めましたが、Request-Responseパターンを使用するときに、メッセージをドロップしたり、そのメッセージを送信した顧客にメッセージを送信させたりせずに、ワーカーが安全に「電話を切って」ソケットを閉じる方法がわかりません。応答。次のようなPythonで記述されたワーカーを想像してみてください。

import zmq
c = zmq.Context()
s = c.socket(zmq.REP)
s.connect('tcp://127.0.0.1:9999')
while i in range(8):
    s.recv()
    s.send('reply')
s.close()

私は実験を行ってきましたが、均等化キューイングのリクエストを行う127.0.0.1:9999ソケットタイプの顧客zmq.REQは、均等化キューイングアルゴリズムが最後の作業を行った直後で、send()実行される前に上記のワーカーを選択するという不幸を抱えている可能性があることがわかりました。次のclose()方法。その場合、要求はワーカープロセスのØMQスタックによって受信およびバッファリングされclose()、ソケットに関連付けられているすべてのものを破棄すると要求は失われるようです。

ワーカーが「安全に」切り離すにはどうすればよいですか。「メッセージはもう必要ありません」というシグナルを送信し、(a)シグナルの送信中に到着した最終メッセージをループし、(b)応答を生成する方法はありますか。次に(c)close()メッセージが破棄されないことを保証して実行しますか?

編集:私が入りたい生の状態は「ハーフクローズ」状態であり、それ以上のリクエストを受信することはできず、送信者はそれを知っていると思いますが、チェックできるようにリターンパスはまだ開いています最後に到着した1つのメッセージの着信バッファーで、バッファー内にメッセージが存在する場合はそれに応答します。

編集:良い質問に答えて、応答を待機している接続が多数ある可能性があるため、待機中のメッセージの数が複数になるように説明を修正しました。

4

6 に答える 6

11

次のような「単純な」競合状態を回避しようとしていると思われるようです。

... = zmq_recv(fd);
do_something();
zmq_send(fd, answer);
/* Let's hope a new request does not arrive just now, please close it quickly! */
zmq_close(fd);

しかし、問題は、均等化キューイング(ラウンドロビン)によって事態がさら​​に困難になることだと思います。ワーカーにすでにいくつかのキューイングされたリクエストがある場合もあります。送信者は、新しいリクエストを受信する番である場合、ワーカーが解放されるのを待たずに新しいリクエストを送信します。そのため、電話をかけた時点で、zmq_send他のリクエストがすでに待機している可能性があります。

実際、間違ったデータ方向を選択した可能性があります。リクエストプールでワーカーにリクエストを送信する代わりに(新しいリクエストを受信したくない場合でも)、ワーカーにリクエストキューから新しいリクエストをフェッチさせ、それを処理してから回答を送信することをお勧めします。

もちろんXREP/を使うという意味XREQですが、それだけの価値はあると思います。

編集:私は、私が何を意味するかを説明するために、他の方向を実装するいくつかのコードを書きました。

于 2010-12-07T20:36:35.190 に答える
3

問題は、メッセージングアーキテクチャが間違っていることだと思います。ワーカーはREQソケットを使用して作業要求を送信する必要があります。そうすれば、ワーカーでキューに入れられるジョブは1つだけになります。次に、作業の完了を確認するために、前のジョブのackを兼ねて新しいジョブを要求する別のREQ要求を使用するか、2番目の制御ソケットを使用することができます。

一部の人々は、コントロールにPUB / SUBを使用してこれを行い、各ワーカーがackをパブリッシュし、マスターがそれらをサブスクライブするようにします。

ZeroMQではメッセージキューが0であることを覚えておく必要があります。まったくありません!最高水準点やソケットのタイプなどの設定に応じて、送信者または受信者のいずれかにバッファリングされたメッセージのみ。メッセージキューが本当に必要な場合は、それを処理するブローカーアプリを作成するか、すべての通信がサードパーティのブローカーを介して行われるAMQPに切り替える必要があります。

于 2011-07-30T01:08:07.370 に答える
2

私もこれについて考えてきました。ワーカーが不在になることを顧客に通知するCLOSEメッセージを実装することをお勧めします。その後、シャットダウンする前に、ワーカーを一定期間ドレインさせることができます。もちろん、理想的ではありませんが、実行可能かもしれません。

于 2010-10-28T16:48:06.227 に答える
0

労働者に可能な限り迅速に要求を送信することと、作業者がクラッシュまたは死亡した場合の信頼性を取得することとの間には、利害の対立があります。ZeroMQガイドには、この信頼性の質問に対するさまざまな回答を説明するセクション全体があります。それを読んでください、それは大いに役立ちます。

tl; drワーカーはクラッシュする可能性があり、クラッシュする可能性があり、クライアントには再送機能が必要です。このガイドでは、そのための再利用可能なコードを多くの言語で提供しています。

于 2012-01-23T03:47:36.157 に答える
-1

最も簡単な解決策は、応答を待つときに顧客にタイムアウトを設定し、応答がない場合は再試行することではないでしょうか。

于 2010-11-22T02:26:38.220 に答える
-3

通話を終了する前に寝てみてください。これは2.1で修正されていますが、2.0ではまだ修正されていません。

于 2010-10-01T18:16:22.903 に答える