ZeroMQ
Push/Pull
(彼らはPipeline
と呼んでいます)ソケットタイプを試してみると、このパターンの有用性を理解するのに苦労しています。 「ロードバランサー」として請求されます。
単一のサーバーが多数のワーカーにタスクを送信すると、プッシュ/プルはすべてのクライアント間でタスクを均等に配布します。 3クライアントと30タスク、各クライアントは10タスクを取得します。client1はタスク1、4、7、... client2、2、5、...などを取得します。けっこうだ。文字通り。
ただし、実際には、タスクの複雑さやクライアントの計算リソース(または可用性)が不均一に混在していることが多く、このパターンはひどく壊れます。すべてのタスクは事前にスケジュールされているようで、サーバーはクライアントの進捗状況や、利用可能かどうかを把握していません。 client1がダウンした場合、残りのタスクは他のクライアントに送信されず、client1のキューに残ります。 client1がダウンしたままの場合、それらのタスクは処理されません。逆に、クライアントのタスク処理が速い場合、他のクライアントに対してスケジュールされたままであるため、それ以上のタスクを取得せず、アイドル状態のままになります。
REQ/REP
を使用することは、可能な解決策の1つです。タスクは利用可能なリソースにのみ与えられます。
だから私は何かが欠けていますか? Push/Pull
はどのように効果的に使用されますか?このソケットタイプでクライアント、タスクなどの非対称性を処理する方法はありますか?
ありがとう!
簡単なPythonの例:
# server
import zmq
import time
context = zmq.Context()
socket = context.socket(zmq.Push)
#socket = context.socket(zmq.REP) # uncomment for Req/Rep
socket.bind("tcp://127.0.0.1:5555")
i = 0
time.sleep(1) # naive wait for clients to arrive
while True:
#msg = socket.recv() # uncomment for Req/Rep
socket.send(chr(i))
i += 1
if i == 100:
break
time.sleep(10) # naive wait for tasks to drain
。
# client
import zmq
import time
import sys
context = zmq.Context()
socket = context.socket(zmq.PULL)
#socket = context.socket(zmq.REQ) # uncomment for Req/Rep
socket.connect("tcp://127.0.0.1:5555")
delay = float(sys.argv[1])
while True:
#socket.send('') # uncomment for Req/Rep
message = socket.recv()
print "recv:", ord(message)
time.sleep(delay)
コマンドラインで遅延パラメーター(1、1、0.1)を使用して3つのクライアントを起動し、次にサーバーを起動して、すべてのタスクが均等に分散される様子を確認します。次に、クライアントの1つを強制終了して、残りのタスクが処理されないことを確認します。
示されている行のコメントを外して、Req/Rep
タイプのソケットに切り替え、より効果的なロードバランサーを監視します。
これはロードバランサーではありません。これは誤った説明であり、しばらくの間0MQドキュメントにとどまりました。負荷分散を行うには、可用性についてワーカーからいくつかの情報を取得する必要があります。プッシュは、ディーラーと同様、ラウンドロビンディストリビューターです。素早い速度とシンプルさで役立ちます。チャタリングは必要ありません。パイプラインにタスクを送り込むだけで、ネットワークが処理できる限り迅速に、利用可能なすべてのワーカーにスプレーされます。
このパターンは、非常に多数の小さなタスクを実行している場合や、従業員が頻繁に出入りする場合に役立ちます。このパターンは、新しいタスクを使用可能なワーカーにのみ送信する単一のキューが必要なため、完了に時間がかかる大規模なタスクには適していません。また、クライアントが多くのタスクを送信してからワーカーが接続すると、最初のワーカーが1,000個程度のメッセージを取得し、他のワーカーはまだ接続に忙しいというアンチパターンの影響を受けます。
いくつかの方法で、独自の上位ルーティングを作成できます。ガイドのLRUパターンを見てください。この中で、ワーカーはブローカーに明示的に「準備完了」と伝えます。また、クレジットベースのフロー制御を行うこともできます。これは、実際の負荷分散状況で私がすることです。これは、LRUパターンの一般化です。 http://hintjens.com/blog:15 を参照してください