gunicornがCPU使用率100%になっていてサイトが激オモになった件

起きた現象
サイトにアクセスした際に、5000ms以上の読み込みが発生していた。(詳しい値を保存していなかったため感覚値になります。)
top
topコマンドでCPU使用率を見てみるとgunicorn
が100%となっていた。
Conoha VPSのリソースを見てみると以下のように急激に上がっていた。
時間的に、昨日のアップデートをした際に起きたものと考えられる。
解決策
結果的にはgunicornの再起動で直りました。
以下でプロセスを停止しました。
pkill gunicorn
この機会に、エラーログやアクセスログを出力するように変えました。
そして、ワーカーやスレッドを設定しました。
再起動時は以下のコマンドです。
gunicorn --bind 127.0.0.1:ポート番号 project_namme.wsgi -D --workers 3 --threads 2 --timeout 60 --access-logfile ./gunicorn-access.log --error-logfile ./gunicorn-error.log
ログをカレントディレクトリにしている理由はsudo権限がなくても書き込めるようにです。
原因としては、古いプロセスが残っていたのが良くない感じっぽかったです。
エラーログを見るとポートをバインドしようとした際に、すでに他のプロセスがそのポートを占有していたため、接続に失敗しており再接続を繰り返していたってことがわかりました。
ワーカーやスレッドを設定
以下、ワーカーやスレッドを設定するにあたって数を決める方法のメモです。
今回、サイトをデプロイしているVPSのスペックは、メモリ 2GB/CPU 3Coreとなっています。
これを元に、GPTくんに相談しながらワーカーやスレッドを設定します。
ワーカー数の算出方法
Gunicornの公式ドキュメントでは、ワーカー数の計算に以下の式が推奨されています:
ワーカー数 = CPUコア数 × 2 + 1
CPUは3コアなので、以下のようにワーカー数は7となります。
ワーカー数 = 3 × 2 + 1 = 7
ただし、VPSのメモリは 2GBと限られているため、ワーカー数を7にするとメモリ不足のリスクがあります。
- メモリの制約:
- 1ワーカーあたり100〜200MB程度のメモリを使用すると仮定。
- VPS全体の2GBのうち、500MBをシステムやその他のプロセスに確保。
- 残りの1.5GBを3ワーカーで分配すると、1ワーカーあたり約500MB使用可能。
上記を考慮し、ワーカー数を3に設定しました。
スレッド数の算出方法
Gunicornでは、各ワーカーが複数のスレッドを持つことができます。スレッドは軽量であり、I/O待ちなどの状況で有効に機能します。
- Gunicornのスレッド数のデフォルト値は1となっています。
スレッド数を --threads 2 に設定しました。
よって、6つの並列処理となります。
ワーカー数 × スレッド数 = 3 × 2 = 6 並列処理
スレッド数を2にした理由は、以下の点を考慮しました:
- I/O待ちに対応:
- データベースクエリやファイルI/Oの待ち時間が発生した場合、スレッドを使って他のリクエストを処理できる。
- メモリ負荷を抑える:
- スレッドはプロセスよりも軽量であり、スレッド数を増やすことでメモリ消費を抑えつつ並列性を向上させることができます。
- 過剰なスレッドは不要:
- スレッド数を増やしすぎるとコンテキストスイッチが増え、逆にパフォーマンスが低下する可能性があるため、少なめの設定にしています。
一旦は様子見します。
今回の高負荷がプログラムの無限ループなどの原因じゃなさそうということ、再起動で古いプロセスが残っていたためかもしれないという理由から様子見をしたいと思います。
ただし、SQLクエリなどの最適化によるパフォーマンスチューニングはこれからも行っていきたと思います。
また同じようなことが起きた際はここに追記していきます。