49

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、より効果的なロードバランサーを監視します。

4

1 に答える 1

67

これはロードバランサーではありません。これは、0MQドキュメントにしばらく残っていた誤った説明でした。負荷分散を行うには、ワーカーから可用性に関する情報を取得する必要があります。PUSHは、DEALERと同様に、ラウンドロビンディストリビューターです。それはその生の速度と単純さのために便利です。どんな種類のおしゃべりも必要ありません。パイプラインにタスクを送り込むだけで、ネットワークが処理できる限り迅速に、利用可能なすべてのワーカーにタスクがスプレーされます。

このパターンは、非常に多くの小さなタスクを実行している場合や、作業者が頻繁に出入りする場合に役立ちます。このパターンは、完了に時間がかかる大規模なタスクには適していません。これは、新しいタスクを使用可能なワーカーにのみ送信する単一のキューが必要になるためです。また、クライアントが多くのタスクを送信してからワーカーが接続すると、最初のワーカーが1,000程度のメッセージを取得し、他のワーカーはまだ接続に忙しいというアンチパターンに悩まされています。

いくつかの方法で、独自の上位レベルのルーティングを作成できます。ガイドのLRUパターンを見てください。この中で、ワーカーはブローカーに「準備完了」と明示的に伝えます。クレジットベースのフロー制御を行うこともできます。これは、実際の負荷分散の状況で私が行うことです。これは、LRUパターンの一般化です。http://hintjens.com/blog:15を参照してください

于 2012-09-21T09:44:55.227 に答える