nginxに変更したらメモリ不足なったので、php-fpmを設定を見直し

2019-08-08

ApacheからNginxに変更したらサーバーが定期的に落ちる

VPSをサーバーをLightsailに変更した際に、Apacheを使っていたWEBサーバーをnginxに変更しました。始めは問題なく動作していたのですが、しばらくするとNetworkManagerが落ちるのでSSHでログインもできないなので、サーバーのインスタンスを停止・起動しないと復旧しない事が多くなってきました。

落ちる直前のCPUとかのメモリとリソース監視のグラフを見ると、物理メモリが使いつくされ、swap領域で限界まで使われている状況でした。メモリ不足でサーバーの定期的に落ちていたと推測されるので、多くのメモリを使っているサービスは、おそらくnginx + php-fpm が怪しいのそのあたりを調べると、php-fpm の設定を初期値のままだとメモリ不足になる症状のあったので、php-fpm の設定を見直しました。

php-fpmで使用しているメモリを調べて最適な設定に見直す

まずは現在のサーバーのメモリが物理メモリが「1G」でswapは「2G」です。php-fpmのメモリの使用状況は「ps」コマンドで調べます

$ ps aux | head -1 && ps aux | grep php-fpm | grep -v grep | grep -v master
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
nginx     6611  0.1  5.0 542156 50704 ?        S    Jul08   9:25 php-fpm: pool www
nginx     7068  0.1  3.6 523488 36680 ?        S    Jul10   5:02 php-fpm: pool www
nginx     7083  0.1  4.0 527800 41220 ?        S    Jul10   5:04 php-fpm: pool www
nginx     7084  0.1  4.0 527452 40956 ?        S    Jul10   5:01 php-fpm: pool www
nginx    12926  0.1  4.1 537476 41608 ?        S    Jul08  10:04 php-fpm: pool www
nginx    12927  0.1  4.2 539800 42964 ?        S    Jul08  10:04 php-fpm: pool www
nginx    12928  0.1  4.6 545856 47304 ?        S    Jul08  10:06 php-fpm: pool www
nginx    12929  0.1  4.2 543304 42840 ?        S    Jul08  10:06 php-fpm: pool www
nginx    12930  0.1  4.2 542940 42740 ?        S    Jul08  10:03 php-fpm: pool www
nginx    12933  0.1  3.7 535936 38164 ?        S    Jul08  10:04 php-fpm: pool www
nginx    12952  0.1  4.2 541248 43288 ?        S    Jul08  10:03 php-fpm: pool www
nginx    13836  0.1  4.0 534916 40888 ?        S    Jul09   7:33 php-fpm: pool www
nginx    13856  0.1  4.2 537216 42764 ?        S    Jul09   7:36 php-fpm: pool www
nginx    13857  0.1  3.5 533648 36200 ?        S    Jul09   7:35 php-fpm: pool www
nginx    13876  0.1  3.3 528844 33536 ?        S    Jul09   7:34 php-fpm: pool www
nginx    13877  0.1  3.8 534644 38856 ?        S    Jul09   7:45 php-fpm: pool www
nginx    13878  0.1  3.8 533604 39328 ?        S    Jul09   7:35 php-fpm: pool www
nginx    13879  0.1  3.2 527784 33160 ?        S    Jul09   7:41 php-fpm: pool

「RSS」の値が、プロセスが確保している物理メモリサイズとなるので、php-fpmで使用しているメモリは30MB~50MBとなります。

今の状態では、20個くらいphp-fpmが起動しているで、その平均を計算するのに「awk」コマンドで計算してみます

$ ps aux | grep php-fpm | grep -v grep | grep -v master | awk '{sum+=$6} END {p
rint sum/NR}'
38444

38MBですので、計算しやすいように40MBとします。今で20個くらい使っているので20×40MB=800MB。ほぼ物理メモリを使っている状態です。

初期値のphp-fpmで子プロセスとメモリ関連の設定は以下のようです

pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35

  • pm = dynamic dynamicの設定だと、動的に子プロセスが変わっていきます
  • pm.max_children = 50 子プロセスの最大数です
  • pm.start_servers = 5 起動時のプロセス数です
  • pm.min_spare_servers = 5 待機中(アイドル時)に起動しているプロセスの最小値です
  • pm.max_spare_servers = 35 待機中(アイドル時)に起動しているのプロセスの最大値です。余剰分のプロセスはアイドル時にkillされます

初期値だと最大が50個なので、メモリの使用量は40Mとすると2GMBのメモリ状況となります。swap領域と物理メモリでギリギリの設定です。

待機中の最大プロセスの値の「pm.max_spare_servers」を35から30に変更して以下の値にして様子をみることのしました

$ sudo vim /etc/php-fpm.d/www.conf
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 30

php-fpmがメモリ不足時のログ

php-fpmが子プロセスが最大値になった時のログですが、以下のエラーが出力されていました

$ less /var/log/php-fpm/error.log
[06-Jul-2019 12:23:53] WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 8 children, there are 2 idle, and 29 total children
[06-Jul-2019 12:23:57] WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 16 children, there are 2 idle, and 32 total children
[06-Jul-2019 12:23:58] WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 32 children, there are 2 idle, and 35 total children
[06-Jul-2019 12:23:59] WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 32 children, there are 2 idle, and 38 total children
[06-Jul-2019 12:24:00] WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 32 children, there are 1 idle, and 41 total children
[06-Jul-2019 12:24:01] WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 32 children, there are 1 idle, and 45 total children
[06-Jul-2019 12:24:02] WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 32 children, there are 1 idle, and 49 total children

[06-Jul-2019 12:24:03] WARNING: [pool www] server reached pm.max_children setting (50), consider raising it

待機中の子プロセスが最大値に超えて使い切ってますのようなメッセージです。php-fpmの子プロセスが使い切った時にメモリが不足してNetworkManagerが落ちた状況が考えられます

swap領域を監視して、空きが少なったらメール・nginx,php-fpmを再起動する

swap領域の空きが少なったら、メールしてかなりswapの空きがなくなったら、nginxとphp-fpmを再起動すれば、メモリ不足でサーバーが落ちる状況が解決できるかもと思って、以下のスクリプトを作ってcronで定期的に実行するようにしました。

#!/bin/bash

# swapの使用率を表示
USEDSWAP=`free |tail -1 | awk '{printf ("%2d",$3/$2*100)}'`

# メール関係の設定
#メールを送信するメールアドレスを指定する
MAILTO=info@example.com
#メールの件名を生成
MAIL_SUB="ALERT SWAP SPACE"
#メール本文に使用するファイルを指定する
MAILFILE=/var/tmp/swapcheck_mail.txt

# swapの使用率が50%超えるとメールする
if [ $USEDSWAP -gt 50 ]; then

#メールの本文を生成
  date "+%Y/%m/%d %H:%M:%S" > $MAILFILE
  echo "WARNNING USED SWAP" >> $MAILFILE
  free -m >> $MAILFILE

#メールを送信する
  cat $MAILFILE | /bin/mail -s "$MAIL_SUB" "$MAILTO"
fi

# swapの使用率が70%超えるとnginx, php-fpmを再起動する
if [ $USEDSWAP -gt 70 ]; then
  systemctl restart nginx.service
  systemctl restart php-fpm.service
fi

swapの使用率を監視して、50%を超えたらメモリ状況の内容を「freee」コマンドで取得してその内容をメールするようにします。また、70%超えたらnginxとphp-fpmを再起動するようにしています

スポンサーリンク