Celery使用中のメモリリークの問題と解決策

セロリ使用中のメモリリーク

問題の説明

セロリ非同期タスクは、時限ループで非同期タスクを実行します。約半月後、メモリ警告メッセージを受信した後、メモリは1週間ゆっくりと増加します。
次の図に示すように、メモリ使用量を照会するための一番上のコマンドは非常に高いです。

セロリメモリ使用量線形グラフ
セロリメモリーリークトップ

問題を特定する

デバッグにMemoryProfilerツールキットを使用すると
、非同期タスクでメモリが増加する場所のほとんどが、要求要求が送信される場所であることがわかります。たとえば、次の例

Line #    Mem usage    Increment  Occurences   Line Contents
============================================================
5  23.94531 MiB  23.94531 MiB           1   @profile(precision=5)
6                                         def my_func(url):
7                                         
8  25.59375 MiB   1.64844 MiB           1       resp = requests.get(url)
9  25.59375 MiB   0.00000 MiB           1       print(resp)
10  25.59375 MiB   0.00000 MiB           1       return resp

解決プロセス

また、同様のメモリリークの問題があり、関連セロリメモリリークがセロリプロジェクトにgithubので見つかるオンライン発行するには問題を
セロリを紹介RabbitMQの時間に再接続要求を開始し、また、メモリーリークが発生していました。しかし、この問題は解決されておらず、まだ開いています

また、リクエストのメモリリークの問題についても質問しました。リクエストを使用するとメモリリークが発生し、リクエスト後にメモリが解放されません。この問題を解決できる使用例として、requests.Session()を使用します。
ただし、requests.Session()にはスレッドの安全性の問題があります。1つのスレッドにSession()を使用することをお勧めしますが、requests.Session()はスレッドに従いません。終わりと終わり。この問題は完全には解決されていません

これは明らかに彼らが見た答えではありません。Celeryの公式文書であるChildTasks Setting Maxによる
と、Celeryジョブプログラムがある場合のメモリリークの問題が説明されていますが、制御プログラム内にはありません。このオプションを使用できます。代わりに新しいプロセスを開始し、最大数のタスクを実行した後に前のプロセスを閉じるようにワーカーを構成できます。

現在、プログラムでは多数のリクエストパッケージが使用されているため、メモリリークが発生しないようにすばやく交換して見つけることはできません(さらに、インターネット上の情報はおそらくすべてurllib3、urllibであり、リクエストにはメモリリークがあります)

したがって、緊急の必要性に対する現在の解決策は、ワーカーが30のタスクを実行した後、CELERYD_MAX_TASKS_PER_CHILDを使用して再構築することです。

CELERYD_CONCURRENCY = 1  # celery worker 的并发数
CELERYD_PREFETCH_MULTIPLIER = 1  # 一次预取多少消息乘以并发进程数。默认值为4 要禁用预取将其设置1 若为0 将允许工作程序继续使用所需数量的消息。
CELERYD_MAX_TASKS_PER_CHILD = 30  # 池工作进程可以被新任务替换之前执行的最大任务数。默认值是没有限制。

しかし、プロセスを再構築することは良い解決策ではありません。リクエストのメモリリークの問題を解決する方法を研究する必要があります。後で研究のためにそれを置いてください。


  • 差出人:xaohuihui
  • 手でこするのは簡単ではありません、スターを付けることを忘れないでください

おすすめ

転載: blog.51cto.com/14612701/2543766