📝

PHP-FPMのリロードをGracefulにした件

に公開

起きたこと

本番リリースでデプロイする瞬間に502エラーになるという事象が発生しました。
nginxのエラーログには以下のエラーメッセージが出力されていました。

recv() failed (104: Connection reset by peer) while reading response header from ...

どうやらデプロイ時にnginxがPHP-FPMに接続できず、502エラーになっていたようでした。

解決方法

結論

PHP-FPMのprocess_control_timeoutという設定に値を設定したところ、解消しました!
詳細は以下に記載します。

やったこと

原因の詳細

デプロイ時に以下のコマンドが実行されています。

# nginxのリロード
sudo systemctl reload nginx
# php-fpmのリロード
sudo systemctl reload php-fpm

どうやら、PHP-FPMのリロードがGracefulになっていなかったようです。
Gracefulなリロードとは、処理中のリクエストをすべて完了した後に安全にリロードすることです。
デプロイ時、処理中のリクエストがある中PHP-FPMのリロードが走り、エラーが発生していたと思われます。(前提として、該当システムはBlue/Greenデプロイを採用しておりません><)

いろんな記事を参考にしたところprocess_control_timeoutを設定するとGracefulにできるみたいだったため、試してみることにしました。

process_control_timeoutを設定

/etc/php-fpm.confに以下を設定

process_control_timeout = 30

PHPのmax_execution_timeを30に設定しているため、それに合わせて30で設定しました。
ここで設定を反映するためにPHP-FPMを再起動。

動作確認

リクエスト処理中にPHP-FPMをリロードして、エラーが発生しないかどうかを確認します。
ブラウザからリクエストを送っても良いのですが、今回はabコマンドを使用しました。
ローカルで以下を実行します。

ab -n 100 -c 100 https://example.com

上記実行中に、サーバーでPHP-FPMをリロードします。

sudo systemctl reload php-fpm

その後nginxのエラーログを確認し、エラーが出ていないことが確認できました!

学び

この問題に遭遇するまで、Graceful restartGraceful reloadといったものを知りませんでした。
そのため上記を知れたこと自体大きな学びだったのですが、それだけではありませんでした。

事象の再現方法や、設定値変更後の確認方法が知れたのも大きな学びでした(abコマンドなど)。
何か問題が起きた時、原因の推測はできるけど断定することは難しいです。
頭の中だけであれこれ考えるだけでなく、下記をサクッとできることが大事だと思いました。

  • dev環境やローカル環境で再現確認をすること。
  • 改善案を試してみること。

もちろん、いろいろ試してみる前にログなどを見て状況を正しく理解することも大事です。

当時、「いろいろ解決案は出てるけど実際どうやって確認すればいいんだろう😣」、「インフラ周りだから触るの怖いな😣」...といった感情になっていて全然動けていなかったのですが、dev環境なら何か起きても問題ないので今後は試してガッテンしていきます💪

参考

Discussion