php-fpm の pm.max_children の適正値

WordPressの記事にブログカードを入れようとして、URLだけの行を追加したら、サーバ負荷が増加してレスポンスが悪化するようになりました。

topコマンドで確認すると、php-fpmがCPUを使っていることがわかったので、nginx のアクセスログを確認すると、以下のようなアクセスが延々と繰り返しリクエストされていました。

[27/Jul/2021:17:29:54 +0900] "GET / HTTP/1.1" 499 0 "https://taiyodo.ga/" "WordPress/5.8; https://taiyodo.ga/"

直前にやったブログカードの追加を削除したら、php-fpm のCPU使用率が下がったので、原因は特定できました。接続元は同じサーバで、UAが「WordPress/5.8」なので wp-cron で起動されているものと推測しました。

エラーコード499についてはこちらのページに記載がありました。

引用すると、こういうことらしいです。

/*
 * HTTP does not define the code for the case when a client closed
 * the connection while we are processing its request so we introduce
 * own code to log such situation when a client has closed the connection
 * before we even try to send the HTTP header to it
 */
#define NGX_HTTP_CLIENT_CLOSED_REQUEST     499

これらより、nginx から php-fpm のソケットに接続して通信しようとしたけど、突然切断されてしまったんだろうな、というところまでわかりました。

で、なんで切断されたのかは php-fpm のログ(/var/log/php7.4-fpm.log)に書いてありました。

[27-Jul-2021 17:27:39] WARNING: [pool www] server reached pm.max_children setting (5), consider raising it

Nginx から接続要求がたくさん来るけど、5個の php-fpm ではさばききれないから pm.max_children を増やせ、ということらしいです。

ということで本題ですが、じゃ、pm.max_children はいくつにすればいいの?ってのを考えてみました。まぁ、話は単純で、

nginx からの最大接続数 = pm.max_children

になればいいはずなので、nginx がいくつ立ち上がるかを調べました。nginx の設定(nginx.conf)で関係ありそうなのは以下。

worker_processes auto;
worker_connections 768;

worker_process はワーカープロセス数で auto の場合はCPUのコア数に設定してくれるそうです。念のため確認すると、/proc/cpuinfo の「cpu cores」は4で、ps aux |grep nginx の「nginx: worker process」も4でした。

worker_connections は1つのワーカーで接続できるコネクション数なんですが、クライアントからのリクエストだけでなく、php-fpm のコネクションも含まれるとのことです。つまり、php-fpm への接続数が最大になるのは、すべてのリクエストが php-fpm へ向けられるときで、そのリクエストでは常に2コネクション消費することになるので、

1ワーカーからの最大接続数 = worker_connections ÷ 2 = 768 ÷ 2 = 384

になります。

ワーカープロセスは4つあるので、

  nginx からの最大接続数 = 1ワーカーからの最大接続数 × ワーカー数 = 384 × 4 = 1536

でした。

htopでphp-fpmをフィルタして観察すると、php-fpm 1プロセスあたり約20~30MB程度のメモリ(RES-SHR)を消費していましたので、30MB×1536個で46GB程度です。そんなリッチなサーバではないので、どうしよー。

そもそも5つでもレスポンスが劣化しているのだから、ほかの対策をしないとだめな気が。。。

と思っていたのですが、Wi-Fiの電波が弱く、ネットワークが遅すぎたために発生していたようで、ネットワーク環境を改善したら全然発生しなくなりました。

ということで、pm.max_children は変更なしでしたとさ。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です