nginx+WordPressで504 Gateway Time-outしていた原因はeAcceleratorだった。

500px-Nginx_logo.svg

nginx+WordPressでちょっとアクセスが増えたら504 Gateway Time-Outするようになった。そしてしばらく続くとサーバーにアクセスできなくなる。

安いVPSだったので、アクセスに耐え切れ無いのかもと思ったがロードアベレージは1未満。

nginx自体に慣れていないのもあるので何か設定をミスっているのかもと色々調べてみる。

nginxのエラーログを見てみる。

/var/log/nginx/error.log

2014/03/04 00:08:07 [error] 5645#0: *13526 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: unix:, server: exsample.com, request: "GET /2014/03/04/2695.html HTTP/1.0", upstream: "fastcgi://unix:/var/run/php-fpm/php-fpm.sock:", host: "exsample.com", referrer: http://example.example.com/test/test2.html

目についたログはこれ、

recv() failed (104: Connection reset by peer)

というエラーが出ている、これで検索してみると、nginxとphp-fpmのタイムアウト値を伸ばすことで対応できるという記事や、php-fpmのプロセス数などを調整することで直るという記事を見かけた。

なるほどと思って、やっていたが改善しなかった。

それについては下の記事などが参考になると思う。

504 Gateway Time-out using Nginx

で、他に気になった記事として、phpのバージョンで起こるという記事があり、仕方なくphpのバージョンを下げたという記事を見かけた。最新バージョンのphpを見てみたが、特にchangelogにbugfixした等の記述がなかった。

色々試してみたが直らなくて、もっといいサーバーを借りなくてはいけないかもと思いながら時間だけが過ぎて1日無駄にした頃、しかし、アクセスはそれなりにあってもロードアベレージが大したこと無いのがやっぱり気にかかり更に調査を続ける。

そして、辿り着いたのが下記の記事。

phpがエラーログを全然出してくれなくてハマった件 – 東京伊勢海老通信

php-fpmのエラーログを詳細に出力させることにしてみる。

/etc/php-fpm.d/www.conf

; Redirect worker stdout and stderr into main error log. If not set, stdout and
; stderr will be redirected to /dev/null according to FastCGI specs.
; Default Value: no
catch_workers_output = yes

catch_workers_output = yesのコメントを外して、php-fpmの再起動をする。

念の為にnginxを再起動したほうがいいかもしれない。

$ service nginx restart
$ service php-fpm restart

php-fpmのエラーログは[/var/log/php-fpm]にerror.logとして出力される。

ずっと、nginxのエラーログだけ見ていた。

/var/log/php-fpm/error.log

[04-Mar-2014 00:08:07] WARNING: [pool www] child 6468 said into stderr: "[Tue Mar  4 00:08:07 2014"
[04-Mar-2014 00:08:07] WARNING: [pool www] child 6468 said into stderr: "] [notice] EACCELERATOR(6468): PHP crashed on opline 51 of array_map() at /var/www/wordpress/wp-content/advanced-cache.php:276"
[04-Mar-2014 00:08:07] WARNING: [pool www] child 6468 said into stderr: ""
[04-Mar-2014 00:08:07] WARNING: [pool www] child 6468 exited on signal 11 (SIGSEGV) after 304.327824 seconds from start
[04-Mar-2014 00:08:07] NOTICE: [pool www] child 6624 started

/var/log/nginx/error.log

2014/03/04 00:08:07 [error] 5645#0: *13526 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: unix:, server: exsample.com, request: "GET /2014/03/04/2695.html HTTP/1.0", upstream: "fastcgi://unix:/var/run/php-fpm/php-fpm.sock:", host: "exsample.com", referrer: http://example.example.com/test/test2.html

nginxのエラーログとも時刻が一致している。

「recv() failed」が発生するときにEACCELERATORで[PHP crashed]が発生しているらしい。

実際にtail -f コマンドで/var/log/php-fpm/error.logと/var/log/nginx/error.logを監視しながら504エラーが再現するの確認した。

ああ、そういえばそんなの入れてたなーと思う。eAcceleratorと言うのはPHPを高速化してくれる素敵なプログラムです。

eAccelerator

便利なものにはリスクが伴うという教訓でしょうか?

で、最新バージョンは出ていないかと思ってサイトを見に行ってみたが、使っているものが最新バージョンだった。

さて、どう対処したものかと思い検索してみると下記の記事を発見。

WordPress › Support » EACCELERATOR: PHP crashed

下記の様に問題を引き起こしているプログラムをフィルタしろということらしい。

(eaccelerator.filter="!*kses.php" in your config)

なるほど、ということで早速やってみる。

php.iniのeacceleratorの設定にadvanced-cache.phpをフィルタする設定を追加した。

/etc/php.ini

[eaccelerator]
zend_extension="/usr/lib64/php/modules/eaccelerator.so"
eaccelerator.shm_size = "32"
eaccelerator.cache_dir = "/var/cache/eaccelerator"
eaccelerator.enable = "1"
eaccelerator.optimizer = "1"
eaccelerator.check_mtime = "1"
eaccelerator.debug = "0"
eaccelerator.filter="!*advanced-cache.php"
eaccelerator.shm_max = "0"
eaccelerator.shm_ttl = "0"
eaccelerator.shm_prune_period = "0"
eaccelerator.shm_only = "0"
eaccelerator.compress = "1"
eaccelerator.compress_level = "9"
eaccelerator.keys = "shm_and_disk"
eaccelerator.sessions = "shm_and_disk"
eaccelerator.content = "shm_and_disk"

そして、サーバを再起動。

$ service nginx restart
$ service php-fpm restart

サーバーは嘘のように安定しました。

タイムアウト値や子プロセス数の調整で改善しない人は他の要因をエラーログなどでしっかりチェックしましょう。

追記:
調べてみたところ、advanced-cache.phpってキャッシュ系のプラグインを導入すると作られるファイルみたいです。うちの場合はQuick Cacheを導入しているためでした。

タグ :