web-dev-qa-db-ja.com

Bull Queueの同時実行に関する質問

Bull Queue(bull.js)がどのように並行ジョブを処理するかを理解する手助けが必要です。

同じRedisインスタンスに接続されたBullキューをそれぞれインスタンス化するNode.jsインスタンスが10個あるとします。

const bullQueue = require('bull');
const queue = new bullQueue('taskqueue', {...})
const concurrency = 5;
queue.process('jobTypeA', concurrency, job => {...do something...});

これは、10個すべてのノードインスタンス全体で、タイプjobTypeAのジョブが同時に最大5つ(同時実行)実行されることを意味しますか?それとも誤解していて、同時実行の設定はノードインスタンスごとですか?

Nodeインスタンスが別の同時実行値を指定するとどうなりますか?

ジョブが複数のNodeインスタンスで処理されないことを確認できますか?

7
Brian

TL; DRは次のとおりです。通常の状態では、ジョブは1回だけ処理されます。問題が発生した場合(たとえば、Node.jsプロセスがクラッシュした場合)、ジョブが二重に処理される可能性があります

Bullの公式からの引用 README.md

重要な注意事項

キューは「少なくとも1回」の作業戦略を目的としています。これは、状況によっては、ジョブが複数回処理される可能性があることを意味します。これは主に、処理の合計期間中にワーカーが特定のジョブのロックを維持できなかった場合に発生します。

ワーカーがジョブを処理している間、他のワーカーが処理できないように、ジョブは「ロック」されたままになります。

ジョブがロックを失うことを防ぐためにロックがどのように機能するかを理解することは重要です-ストールになり、結果として再起動されます。ロックは、間隔lockDuration(通常はlockRenewTimeの半分)でlockDurationのロックを作成することにより、内部的に実装されます。ロックが更新される前にlockDurationが経過すると、ジョブは停止していると見なされ、自動的に再起動されます。 二重処理になります。これは次の場合に起こります。

  1. Nodeジョブプロセッサを実行しているプロセスが予期せず終了します。
  2. ジョブプロセッサはCPUに負荷がかかりすぎて、Nodeイベントループが発生したため、Bullはジョブロックを更新できませんでした(これをより適切に検出する方法については#488を参照してください)。これを修正するには、ジョブプロセッサを小さなパーツに分割して、Nodeイベントループをブロックできないようにします。または、lockDuration設定に大きな値を渡すことができます(トレードオフは本当の停滞した仕事を認識するのにより長くかかること)。

そのため、常にstalledイベントをリッスンし、これをエラー監視システムに記録する必要があります。これは、ジョブが二重処理される可能性が高いことを意味します。

安全策として、問題のあるジョブが無期限に再起動されないようにします(たとえば、ジョブプロセッサがそのNodeプロセス)をクラッシュさせた場合)、ジョブはストール状態から最大maxStalledCount回(デフォルト: _1_)。

0
Stas Korzovsky

プロセッサスレッドが多すぎる問題 に直面した結果として、かなりの時間をかけて掘り下げました。

要するに、ブルの並行性はキューobjectレベルであり、キューレベルではないということです。

コードを詳しく調べると、キューオブジェクトで.processを呼び出した時点で同時実行設定が呼び出されます。これは、同じNodeアプリケーション内であっても、複数のキューを作成して.processを複数回呼び出すと、処理可能な同時ジョブの数が増えることを意味します。

ある投稿者は以下を投稿しました:

はい、ブルを初めて使用したときも私にとっては少し意外でした。キューオプションはRedisでは永続化されません。アプリケーションごとにキューインスタンスをいくつでも持つことができ、それぞれに異なる設定をすることができます。同時実行性の設定は、プロセッサを登録するときに設定されます。これは、実際には、Queueではなく、各process()関数呼び出しに固有です。名前付きプロセッサを使用する場合は、process()を複数回呼び出すことができます。各呼び出しは、同時実行の量(デフォルトは1)でN個のイベントループハンドラー(Nodeのprocess.nextTick()を使用)を登録します。

したがって、あなたの質問に対する答えは次のとおりです。はい、プロセスハンドラーを複数のノードインスタンスに登録すると、プロセスは複数のノードインスタンスによって処理されます。

0
slifty