最適化—Pythonドキュメント

提供:Dev Guides
Celery/docs/latest/userguide/optimizing
移動先:案内検索

最適化

序章

デフォルトの構成では、多くの妥協が必要です。 単一のケースには最適ではありませんが、ほとんどの状況で十分に機能します。

特定のユースケースに基づいて適用できる最適化があります。

最適化は、タスクの実行にかかる時間、使用されるメモリの量、高負荷時の応答性など、実行環境のさまざまなプロパティに適用できます。


運用の確保

著書 Programming Pearls で、Jon Bentleyは、質問をすることによって、封筒裏の計算の概念を示しています。

❝ミシシッピ川から1日にどのくらいの水が流れ出しますか。 ❞


この演習 * のポイントは、システムがタイムリーに処理できるデータの量に制限があることを示すことです。 封筒裏の計算は、これを事前に計画する手段として使用できます。

セロリで; タスクの完了に10分かかり、毎分10個の新しいタスクが来る場合、キューが空になることはありません。 これが、キューの長さを監視することが非常に重要である理由です。

これを行う方法は、 Munin を使用することです。 アラートを設定する必要があります。アラートは、キューが許容できないサイズに達するとすぐに通知されます。 このようにして、新しいワーカーノードを追加したり、不要なタスクを取り消したりするなどの適切なアクションを実行できます。


一般設定

ブローカー接続プール

バージョン2.5以降、ブローカー接続プールはデフォルトで有効になっています。

:setting: `broker_pool_limit` 設定を微調整して競合を最小限に抑えることができます。値は、ブローカー接続を使用するアクティブなスレッド/グリーンスレッドの数に基づく必要があります。


一時キューの使用

Celeryによって作成されたキューは、デフォルトで永続的です。 これは、ブローカーが再起動された場合でもタスクが確実に実行されるように、ブローカーがディスクにメッセージを書き込むことを意味します。

ただし、メッセージが失われても問題ない場合もあるため、すべてのタスクに耐久性が必要なわけではありません。 これらのタスク用に transient キューを作成して、パフォーマンスを向上させることができます。

from kombu import Exchange, Queue

task_queues = (
    Queue('celery', routing_key='celery'),
    Queue('transient', Exchange('transient', delivery_mode=1),
          routing_key='transient', durable=False),
)

または:setting: `task_routes` を使用して:

task_routes = {
    'proj.tasks.add': {'queue': 'celery', 'delivery_mode': 'transient'}
}

delivery_modeは、このキューへのメッセージの配信方法を変更します。 値1は、メッセージがディスクに書き込まれないことを意味し、値2(デフォルト)は、メッセージをディスクに書き込むことができることを意味します。

タスクを新しい一時キューに転送するには、キュー引数を指定できます(または、:setting: `task_routes` 設定を使用します)。

task.apply_async(args, queue='transient')

詳細については、ルーティングガイドを参照してください。


ワーカー設定

プリフェッチ制限

Prefetch は、AMQPから継承された用語であり、ユーザーが誤解することがよくあります。

プリフェッチ制限は、ワーカーが自分で予約できるタスク(メッセージ)の数の制限です。 ゼロの場合、ワーカーはメッセージを消費し続けます。メッセージをより早く処理できる可能性のある他の使用可能なワーカーノードがある可能性があること、またはメッセージがメモリに収まらない可能性があることを考慮しません。

ワーカーのデフォルトのプリフェッチカウントは、:setting: `worker_prefetch_multiplier` 設定に同時実行スロットの数(プロセス/スレッド/グリーンスレッド)を掛けたものです。

期間の長いタスクが多数ある場合は、乗数の値を one にします。つまり、ワーカープロセスごとに一度に1つのタスクのみを予約します。

ただし、短期間のタスクが多数あり、スループット/往復の待ち時間が重要な場合は、この数値を大きくする必要があります。 メッセージがすでにプリフェッチされており、メモリで使用可能な場合、ワーカーは1秒あたりにより多くのタスクを処理できます。 あなたはあなたのために働く最高の価値を見つけるために実験しなければならないかもしれません。 このような状況では、50や150などの値が意味をなす場合があります。 64、または128と言います。

長時間実行タスクと短期実行タスクの組み合わせがある場合、最良のオプションは、別々に構成された2つのワーカーノードを使用し、実行時にタスクをルーティングすることです(ルーティングタスクを参照)。


一度に1つのタスクを予約する

タスクメッセージは、タスクが確認済みになった後でのみキューから削除されるため、タスクを確認する前にワーカーがクラッシュした場合は、別のワーカーに再配信できます(またはリカバリ後に同じメッセージを配信できます)。

one のプリフェッチ乗数設定を持つデフォルトの早期確認を使用する場合、ワーカーはすべてのワーカープロセスに対して最大で1つの追加タスクを予約することを意味します。つまり、ワーカーが[X230X ] 、ワーカーはいつでも最大20個のタスク(実行中の10個の確認済みタスクと10個の未確認の予約済みタスク)を予約できます。

多くの場合、ユーザーは「タスクのプリフェッチ」を無効にすることが可能かどうかを尋ねますが、実際には、ワーカープロセスと同じ数のタスクのみを予約することを意味します(-c 10の未確認タスク10個)

それは可能ですが、遅延確認応答も有効にする必要があります。 デフォルトの動作に対してこのオプションを使用すると、電源障害またはワーカーインスタンスが突然強制終了された場合に、すでに実行が開始されているタスクが再試行されるため、タスクはべき等である必要があります。

次の構成オプションを使用して、この動作を有効にできます。

task_acks_late = True
worker_prefetch_multiplier = 1

脚注

*
この章はここから無料で読むことができます:封筒の裏側。 この本は古典的なテキストです。 強くお勧めします。
RabbitMQおよびその他のブローカーはラウンドロビンでメッセージを配信するため、これはアクティブなシステムには適用されません。 プリフェッチの制限がなく、クラスターを再起動すると、ノードの開始間にタイミング遅延が発生します。 3つのオフラインノードと1つのアクティブノードがある場合、すべてのメッセージがアクティブノードに配信されます。
これは並行性の設定です。 :setting: `worker_concurrency` またはcelery worker -cオプション。