現在のシステムにredis キューを実装しようとしています。はjob
別のモジュールに送信され、ジョブが完了して結果が返されるまで待機しjob.result
、次に進みます。
with Connection(redis_connection):
job = job_queue.enqueue(worker_func, func_input1, func_input2)
print("waiting for result")
print(datetime.datetime.now())
while job.result is None:
pass
print(datetime.datetime.now())
print("got result")
# next step
next_step_func(job.result)
...
ここで2つの問題に直面しています:
- ビジー状態で
while job.result is None
、非常に長い時間がかかっています。での私の処理worker_func
は約 2 ~ 3 秒で、別のサーバーで API を呼び出す必要がありますが、ビジー状態の待機while job.result is None
自体にさらに 3 秒以上かかり、合計で 5 秒以上かかります。とwhile job.result is None
の両方のログを追加したため、 の実行後に待機が行われることは確かです。worker_func
while job.result is None
2021-07-12T18:57:59.09+0800 [APP/PROC/WEB/0] OUT start work
2021-07-12T18:57:59.09+0800 [APP/PROC/WEB/0] OUT 2021-07-12 10:57:57.601189
2021-07-12T18:57:59.09+0800 [APP/PROC/WEB/0] OUT 2021-07-12 10:57:59.075137
2021-07-12T18:57:59.09+0800 [APP/PROC/WEB/0] OUT end work
...
2021-07-12T18:57:59.09+0800 [APP/PROC/WEB/0] OUT waiting for result
2021-07-12T18:57:59.09+0800 [APP/PROC/WEB/0] OUT 2021-07-12 10:57:53.704891
2021-07-12T18:57:59.09+0800 [APP/PROC/WEB/0] OUT 2021-07-12 10:57:59.096009
上記でわかるように、ビジー状態の待機中のループは、処理worker_func
が完了した後に発生します。
2、ビジーループの代わりに、この同期待機を実装する他のエレガントな方法はありますか? ここでのビジー ループは、多くの CPU リソースを消費するため、最適な実装ではないと思います。
ありがとう!
-- 上記のコードを編集して、より明確なコンテキストを提供します
が呼び出された場所から値をnext_step_func(job.result)
返す必要があります。job_queue.enqueue
したがって、より明確な構造は次のようになります。
def endpoint():
with Connection(redis_connection):
job = job_queue.enqueue(worker_func, func_input1, func_input2)
print("waiting for result")
print(datetime.datetime.now())
while job.result is None:
pass
print(datetime.datetime.now())
print("got result")
# next step
return next_step_func(job.result)
...
job.result
そのため、問題は、で返されることができる必要があることですがendpoint()
、ジョブ コールバックによって、ジョブが の別のコンテキストに移されon_success
ます。