web-dev-qa-db-ja.com

セロリタスクのプリフェッチについて

構成オプションCELERYD_PREFETCH_MULTIPLIERドキュメント )。デフォルトは4ですが、(私は信じています)プリフェッチをオフにするか、可能な限り低くしたいです。今は1に設定しています。これは探しているものに十分近いですが、まだ理解できないことがいくつかあります。

  1. なぜこれを先読みするのが良い考えですか?メッセージキューとワーカーの間に大きな遅延がない限り、その理由は実際にはわかりません(私の場合、現在同じホストで実行されており、最悪の場合、同じデータの異なるホストで実行される可能性があります)センター)。ドキュメントには欠点のみが記載されていますが、その利点については説明されていません。

  2. 多くの人々はこれを0に設定しているようで、そのようにプリフェッチをオフにできると期待しています(私の意見では合理的な仮定)。ただし、0は無制限のプリフェッチを意味します。なぜ誰もが無制限のプリフェッチを望んでいるのに、そもそもタスクキューを導入した並行性/非同期性を完全に排除しないのでしょうか?

  3. プリフェッチをオフにできないのはなぜですか?ほとんどの場合、パフォーマンスをオフにするのは得策ではないかもしれませんが、これが不可能になる技術的な理由はありますか?それとも実装されていないだけですか?

  4. 時々、このオプションはCELERY_ACKS_LATE。例えば。 Roger Huが書いています "[…]しばしば[ユーザー]が本当に望んでいるのは、ワーカーに子プロセスと同数のタスクのみを予約させることです。しかし、これは遅延確認を有効にしないと不可能です[…]"これら2つのオプションがどのように接続されているのか、なぜ一方が他方なしでは不可能なのか理解できません。接続についての別の言及は here にあります。誰かが2つのオプションが接続されている理由を説明できますか?

65
  1. プリフェッチはパフォーマンスを改善できます。ワーカーは、ブローカーからの次のメッセージが処理されるのを待つ必要はありません。ブローカーと一度通信して大量のメッセージを処理すると、パフォーマンスが向上します。ブローカからメッセージを取得することは、ローカルメモリアクセスであっても、ローカルメモリアクセスに比べて高価です。ワーカーはバッチでメッセージを確認することもできます

  2. ゼロに設定されたプリフェッチは、無制限ではなく「特定の制限なし」を意味します

  3. プリフェッチを1に設定することは、それをオフにすることと同等であると文書化されていますが、常にそうであるとは限りません( https://stackoverflow.com/a/33357180/71522 を参照)

  4. プリフェッチにより、メッセージをバッチで確認することができます。 CELERY_ACKS_LATE = Trueは、メッセージがワーカーに届くときにメッセージを確認できないようにします

23
mher

古い質問ですが、誰かを助けるために私の答えを追加します。いくつかの初期テストからの私の理解は、David Woleverの答えと同じでした。セロリ3.1.19でこれをさらにテストしたところ、-Ofairは機能します。ワーカーノードレベルでプリフェッチを無効にすることを意図したものではありません。それは起こり続けます。 -Ofairを使用すると、プールワーカーレベルで異なる効果があります。要約すると、プリフェッチを完全に無効にするには、次を実行します。

  1. CELERYD_PREFETCH_MULTIPLIER = 1を設定
  2. グローバルレベルまたはタスクレベルでCELERY_ACKS_LATE = Trueを設定します
  3. ワーカーの起動中に-Ofairを使用します
  4. 並行性を1に設定すると、ステップ3は不要です。より高い同時実行性が必要な場合、ステップ3は、長時間実行されるタスクを実行できるノードでタスクがバックアップされるのを防ぐために不可欠です。

さらに詳細を追加します。

ワーカーノードはデフォルトで常にプリフェッチされることがわかりました。 CELERYD_PREFETCH_MULTIPLIERを使用して、プリフェッチするタスクの数のみを制御できます。 1に設定されている場合、ノード内のプールワーカーの数(同時実行)と同数のタスクのみをプリフェッチします。したがって、並行性= nの場合、ノードによってプリフェッチされる最大タスクはnになります。

-Ofairオプションがないと、プールワーカープロセスの1つが長時間実行されるタスクを実行している場合、ノード内の他のワーカーも、ノードによって既にプリフェッチされたタスクの処理を停止します。 -Ofairを使用することにより、変更されました。ノードのワーカーの1つが長時間実行タスクを実行していても、他のワーカーは処理を停止せず、ノードによってプリフェッチされたタスクの処理を続行します。したがって、プリフェッチには2つのレベルがあります。ワーカーノードレベルで1つ。もう1つは、個々のワーカーレベルです。 -Ofairを使用すると、ワーカーレベルで無効になったようです。

ACKS_LATEはどのように関連していますか? ACKS_LATE = Trueは、タスクが成功した場合にのみタスクが承認されることを意味します。そうでない場合、それは労働者によって受け取られたときに起こると思います。プリフェッチの場合、タスクは最初にワーカーによって受信されます(ログから確認されます)が、後で実行されます。先読みされたメッセージは、rabbitmqの「認識されていないメッセージ」の下に表示されることに気付きました。したがって、Trueに設定することが絶対に必要かどうかはわかりません。とにかく、他の理由でタスクをそのように設定しました(遅刻)。

21
ksrini

警告:redisブローカー+ Celery 3.1.15でのテストの時点で、プリフェッチを無効にする_CELERYD_PREFETCH_MULTIPLIER = 1_に関して読んだアドバイスはすべて間違いなく間違っています。

これを実証するには:

  1. _CELERYD_PREFETCH_MULTIPLIER = 1_を設定
  2. それぞれ数秒かかる5つのタスクをキューに入れます(例、time.sleep(5)
  3. Redisでタスクキューの長さの監視を開始します:_watch redis-cli -c llen default_

  4. _celery worker -c 1_を開始

  5. Redisのキューの長さは_5_から_3_にすぐに下がることに注意してください。

_CELERYD_PREFETCH_MULTIPLIER = 1_はプリフェッチを防止しません。プリフェッチをキューごとに1タスクに制限します。

_-Ofair_、 ドキュメントの記載にもかかわらず 、またはプリフェッチを防止しません

ソースコードを変更する以外に、プリフェッチを完全に無効にする方法は見つかりませんでした。

14
David Wolever

私のstackcredは十分に高くないので、David Woleverの答えにコメントすることはできません。だから、私は自分の経験をCelery 3.1.18とMongodbブローカーと共有したいので、答えを答えとして組み立てました。次の方法でプリフェッチを停止できました。

  1. 追加 CELERYD_PREFETCH_MULTIPLIER = 1セロリの設定へ
  2. 追加 CELERY_ACKS_LATE = Trueセロリの設定へ
  3. オプションでセロリワーカーを開始します:--concurrency=1 -Ofair

CELERY_ACKS_LATEをデフォルトのままにしておくと、ワーカーは引き続きプリフェッチします。 OPのように、プリフェッチとレイトACKの間のリンクを完全には把握していません。 Davidが「CELERY_ACKS_LATE = Trueはメッセージがワーカーに届いたときにメッセージの確認を防ぐ」と言っていることは理解していますが、レイトACKがプリフェッチと互換性がない理由を理解できません。理論的には、プリフェッチは、セロリでそのようにコーディングされていない場合でも、まだ遅刻を許可しますか?