web-dev-qa-db-ja.com

セロリでAPIを呼び出す

要件が次のようなクライアント向けのシステムを設計しています。

  • jSONファイルをアップロードします(1つのオブジェクト/行)
  • jSONオブジェクトをペイロードとしてAPIを呼び出す
  • 各API呼び出しの状態(成功/失敗)をデータベースに記録する
  • 失敗した場合は、1回再試行します。

セロリとsqliteデータベースをバックエンドとして使用して構築することにしました。 JSON行の数は多くなく、おそらくメモリ内に収まる数百万です。個々のコンポーネントはすべて正常に動作していますが(ファイルのアップロード、ファイルの読み取り、APIの呼び出し、dbへの書き込みなど)、セロリを使用したタスクのディスパッチの全体的なアーキテクチャについてはわかりません。

ファイルにN行あるとすると、次のようになります。

オプションA:

  1. result列(最初はnull)を使用して、データベースにN個のオブジェクトを作成します。
  2. セロリタスクをN個作成し、オブジェクトIDをパラメーターとペイロードとして渡します
  3. サブタスクにAPIを呼び出しさせ、オブジェクトの結果フィールドを成功/失敗に更新します。
  4. 失敗した場合にセロリの再試行機能がAPIを再度呼び出そうとするようにします。

オプションB:

  1. result列(最初はnull)を使用して、データベースにN個のオブジェクトを作成します。
  2. 1つのセロリタスクを作成し、N個のオブジェクトIDとN個のペイロードのリスト全体を渡します
  3. N個のオブジェクトすべてをループし、各ステップの結果でデータベースを更新します。
  4. 前のタスクが完了すると、別の1回限りのセロリタスクが起動され、失敗した結果を持つすべてのオブジェクトのデータベースが読み取られて再試行されます。

オプションAは、その単純さのために優先していますが、スケジュールできるセロリタスクの数の制限と、ブローカー(RabbitMQ)がそれを処理するかどうかはわかりません。オプションBの場合、大きなリスクは、セロリタスクが何らかの理由で何らかの行Mで終了した場合、後続のすべてのオブジェクトが試行されることはないということです。

これらの2つについての考え、または3番目に優れた代替案があるかどうか。

8
user154706

オプションAは、1人のワーカーのみが管理できる巨大なタスクではなく、APIを個別にワーカーに設定できるので便利です。

KombuとCeleryを使用した非常に類似したシナリオがあります。

  • RMQキューへの何らかの統合によってRMQにメッセージが投稿されます
  • 昆布消費者流出イベントがあります
  • イベントを受信したら、コールバックを実行します(ローカルへの投稿pythonキュー)
  • セロリは、pythonキュー経由で送信されたメッセージを取得して処理します
  • 完了すると結果が返され、メッセージが昆布プロデューサーにリレーされます
  • プロデューサーはRMQにポストバックします

ご覧のとおり、基本的には同じアプローチを使用しています。本番環境では、問題なく1時間あたり約2000件のメッセージを処理しています。

1
ZeroSoul13