俺のブログサーバーがこんなに遅いわけがない2。apc→opcacheへ。

Linux

ブログサーバー性能改善を継続しています。今回は、opcacheの導入と、最近食らったトラブルについて。

まずはトラブル。しばらく前からこんなメッセージが表示されていました。

WP HTTP Error: Couldn't resolve host 'ja.wordpress.org'

どうやら外部サイトに接続できないらしいのですが、原因が分からず。最初はダッシュボードの表示だけかと思っていたのですが、newrelicやakismet、cloudfrareまで、ありとあらゆるwordpressプラグインからの接続がNGになっていることが判明。最終的に気付いたきっかけは、大量のスパムコメント(akismetがフィルタしてくれなかった)でした。

で、結局、原因は何だったかというと、「/etc/resolv.confのパーミッションが600になってたため、rootユーザー以外のプロセスから名前検索ができなくなっていた」。なんでこんな状態になったのか。もしかハッキングにあったか?とも思ったのですが、思い当たる節は2つ。

まず、最近、yum updateを行った。これによって、かなりファイルが置き換わっていた。もしやこれが原因かもしれない・・・と。ただ、これは可能性が低い。

で、本命。おそらくdocker。このWebサイトは、VPS上でdockerを動かし、その中で一式のプロセスを稼働しています。そのままだとファイルシステムの差分がどんどん大きくなってしまうため、3ヶ月に1回ほど、commitして立ち上げ直すということをしています。今回、この事象が出たのは、docker commitした後なので、このタイミングで、resolv.confが書き換わってしまったか、あるいは何かの間違いで(?)書き換えてしまったっぽいです。

教訓。名前解決できない、って言われたときは、resolv.confのパーミッションも注意しましょう。特にdockerコンテナ等では、作業をrootアカウントで行っていて、apache等のプロセスアカウントからのアクセスができないことに気付かないケースがあります(今回、気づくのに遅れたのはこのため)。意外に盲点なので、気をつけよう、と。

さて、トラブルが片付いたところで、Webサーバーの高速化です。CentOSの標準はphp5.3なので、アクセラレータとしてはAPCが標準的に利用されます。ウチでもAPC使っていました。ただ、APC自体、結構古いのと、最近はZend OPcacheの評判が良いので、これを導入してみることにしました。

php5.3でOPcacheを導入するのも比較的カンタンです。php-develパッケージが要るのが注意点。

wget http://pecl.php.net/get/ZendOpcache
tar zxvf ZendOpcache
cd zendopcache-7.0.5
phpize
./configure --with-php-config=`which php-config`
make
make install

これでライブラリファイルが/usr/lib64/php/modules/opcache.soとかに入ります。インストール先は環境によって異なると思いますので、要確認です。あとは、CentOSなら、phpのコンフィグレーションは/etc/php.d以下に並べておけるので、以下のように作ってあげます。

cat > /etc/php.d/opcache.ini <<EOF
zend_extension=/usr/lib64/php/modules/opcache.so
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.revalidate_freq=60
opcache.fast_shutdown=1
EOF

パラメータは適当。まずは動かすことを優先し、パラメータ調整はあとで。ここまでやると、phpがOPcacheを認識しているか確認できます。

# php -v
PHP 5.3.3 (cli) (built: Oct 30 2014 20:12:53)
Copyright (c) 1997-2010 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies
    with Zend OPcache v7.0.5, Copyright (c) 1999-2015, by Zend Technologies

はい、入りましたね。これでOK。楽ちんです。あとはapacheやphp-fpmを再起動すれば、OPcacheが有効な状態で稼働します。

稼働状況を見るには、APCの場合ならapc.phpというツールがありましたが、OPcacheについても同じようなものがあります。ズバリ、ocp.phpです。

# wget 'https://gist.githubusercontent.com/ck-on/4959032/raw/be19d1bc30f1548be226ad312ddb5a5911452588/ocp.php'

これを適当なディレクトリにおいて、ブラウザから見ると、OPcacheの動作状況が分かります。

スクリーンショット 2015-06-22 2.51.47

なかなか綺麗です。見れる情報はapc.phpと同じように、ヒット率やキャッシュの中身が見れます。

さて、OPcacheとAPCを同時に有効にした場合、どちらが使われるか、ですが、実際の動作をapc.php、ocp.phpで見くらべてみると、OPcacheが使われているようです。OPcacheのほうが性能は良いとされているので、このほうが嬉しいですね。感覚的には、APC外したほうが速いような気がします。

続いて。Google PageSpeed Insightsでずーっと言われている、「お前のサイトの応答速度は380msで遅いんじゃー」という言いがかりに対する対応。apacheのプロセスの見直しです。

Apache httpdのMPMには4つモデルがあります。prefork、worker、perchild、winntです。preforkが所謂1プロセス1処理、それ以外はマルチスレッド動作をします。ただ、mod_phpを使う場合、mod_phpがスレッドセーフになっている必要があり、一般にworkerモデルは非奨励になっています(スレッドセーフでコンパイルすれば大丈夫という情報もありますが)。

そのため、wordpressサイトでは、preforkモデルを使うことになるわけですが、VPS等でメモリが少ない場合、httpdのプロセス数増加によるメモリ増大が馬鹿になりません。また、Apache httpdのworkerについても、昔は不安定と言われて、大規模サイトでは「preforkでプロセス数を増やしてKeepAlive offだ」と都市伝説のように言われていましたが、流石にイマドキはマルチスレッドでKeepAlive onにして処理効率を向上させるのが通常の設定になっています。

そこで、マルチスレッド化を行いました。と言っても、mod_phpをスレッドセーフにしたわけではありません。ウチのサイトは元々、mod_fastcgiとphp-fpmで高速化しているため、mod_phpは使ってないのです。今のままでもworkerにできるじゃん!と気付いたのが実は発端。

CentOSでパッケージで入れたhttpdをマルチスレッドにするには、バイナリを変更することで対応ができます。実は既に、prefork版のhttpdとは別にworker版のhttpd.workerというバイナリがインストールされてるんですね。知らなかった。変更箇所は/etc/sysconfig/httpdです。

#
# The default processing model (MPM) is the process-based
# 'prefork' model.  A thread-based model, 'worker', is also
# available, but does not work with some modules (such as PHP).
# The service must be stopped before changing this variable.
#
HTTPD=/usr/sbin/httpd.worker

はい、ここを書き換えましょう。変わったかどうかは、apachectlコマンド等で分かります。

# apachectl -V | grep MPM
Server MPM:     Worker

あとはこの状態で、httpdを起動すればworkerなhttpdが動き出します。注意点は、この変更は、httpdを落とした状態で修正しないといけないこと。killすれば大丈夫かな、と思いますが、おそらくhttpd -kでstopかけたりするのは通らなくなるので、止めた状態で書き換えて、再度起動するのが安全だと思います。

これでhttpdプロセスの数も減り、処理も速くなる・・・かなぁ、と期待。パラメータとか全然チューニングしていないので、ちょっと様子見るかな、という感じですが、まずはhttpdのプロセスが減りましたので、良かった、と。ちなみに、server-statusでの見え方には変わりがないので、どんな動きをしているかは今までと同じようにモニタリングできそうです。

そんな感じで、改善してみた訳ですが・・・相変わらず「お前のサイトの応答速度は380msで遅いんじゃー」と言われています。ははははは・・・

コメント

タイトルとURLをコピーしました