*ふとしたキッカケ [#we75a40b] Apache httpサーバが2.2系から2.4系にアップデートされた事がキッカケでした。せっかくなので、USEフラグを攻めてみようと。そしたらば…MPMという指定がOFFになっていたのです。ヽ(~~~ )ノ ハテ?MPMってなんだろう? Multi Processing Moduleという名称からも分かるように、mpmとはapacheの並列処理を行うmoduleです。 ほほう、なるほど…並列処理用のモジュールの指定、ということだったのね。せっかくアップデートするのであれば、ピカピカの状態で使用したい、と言うことで、Apache+PHPの実行環境を攻めて行くこととします。 *設計指針 [#i522c57d] -入力が捌けなくて落ちない様に、奥(PHPやMySQL)は広く、入り口(Apache)を狭く設定しておく -プロセス/スレッド/キャッシュ数は、なるべく理にかなった方法で *Apache MPMの設定 [#ob0e20a5] **MPMの種類 [#r18f8505] ApacheのMPMにはいくつか種類があり、必ず実行プロセスについて1つだけを指定します。同時利用はNGです。さて、どんな種類があるか? :prefork|HTTPリクエストに1つのプロセスを割り当てる。つまり、たくさんのリクエストを同時に捌きたい場合には、たくさんプロセスをたちあげておく :worker|HTTPリクエストに1つのスレッドを割り当てる。起動しておくプロセス数、プロセス内のスレッド数は設定によって変更する :itk|preforkと一緒だが、スクリプトを実行するユーザ権限を分けることができる。例えばApacheさんとか、rootさんとか、各ユーザさんとか :perchild|workerと同じ考え方だが、バーチャルホスト毎にプロセス数/実行ユーザを割り当てる :event|workerと同じく、プロセス/スレッドの組み合わせだが、非同期I/O型((リクエスト受信と応答送信を別のスレッドで処理する方式))となっており、設定如何では最も高速 一般的に使用されるのはprefork/worker。eventは2.2系ではExperimental(実験的)サポート、2.4系では標準推奨のMPMです。ちなみに、preforkよりもworkerの方が動作効率は良いです。何故ならば…プロセスの起動/停止/切り替えはOSにとって重い処理、スレッドの起動/停止/切り替えは軽い処理だからです。よし!それじゃあworkerかeventで決まり!と言いたいところですが、そうはなかなか行きません。スレッドは、メモリ空間を共有するため、きちんと排他処理されていないと誤動作する可能性が高いのです。きちんと処理されている処理系のことを、スレッドセーフな実装と言います。スレッドセーフじゃない処理系を使用する場合は使用するべきではありません。 **MPMを選択してコンパイルする [#v968b11e] /etc/portage/make.confに、以下の記載を追加します。ちなみに、今回は攻めるので、event MPMで高速なWebサーバを目指します。 APACHE2_MPMS=event # emerge apache2 **MPMのチューニング [#g3659aef] /etc/apache2/modules.d/00_mpm.confにMPMの動作パラメータが記載されています。これをいろいろいじってやればOK。 :StartServers|最初に起動する子プロセスの数 :MinSpareThreads|最小の待機スレッド数 :MaxSpareThreads|最大の待機スレッド数 :ThreadsPerChild|子プロセスの中のスレッド数 :MaxRequestWorkers|最大同時接続ワーカー数 :MaxConnectionsPerChild |子プロセスの最大数 だ、そうです。さて、うちではどうして言うかというと-。 StartServers 4 MinSpareThreads 25 MaxSpareThreads 75 ThreadsPerChild 25 MaxRequestWorkers 150 MaxConnectionsPerChild 10000 起動時、StartServers、MinSpareThreadsで待機していますが、同時接続数が増えていくと、ThreadsPerChild数を超えると、MaxRequestWorkersに到達するまで子プロセスを増やします。が、子プロセスのゾンビ化やメモリリークを防ぐために、MaxConnectionsPerChildで上限を決めているのですね。 ポイントは、MaxRequestWorkersで、同時接続の最大数。同時アクセスの最大数はココでサチるということですね。 *PHPの並列動作について [#x23dbc12] PHPをマルチスレッドで動作させるのは非推奨だと、[[PHPホームページに記載されています>http://www.php.net/manual/ja/faq.installation.php#faq.installation.apache2]]。やるならFastCGIを使えとのこと。なわけで、FastCGIの設定をしてみます。 **FastCGIをやってみる [#ba4fc5cb] さて、FastCGIの設定は、[[このページ:http://femt.ddo.jp/modules/xpwiki/?Gentoo%20Linux%E3%81%AA%E7%94%9F%E6%B4%BB%2F%E8%A4%87%E6%95%B0%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%81%AEPHP%E5%90%8C%E6%99%82%E8%B5%B7%E5%8B%95%E3%81%A7%E6%82%A9%E3%82%80]]のApache&PHP7.1の部分だけ設定すると、うまくいきますよ~ **チューニング [#za32aded] pm = dynamic #下記パラメータに従って動作する pm.max_children = 100 #最大同時接続数 pm.start_servers = 4 #最初に起動しておくプロセス数 pm.min_spare_servers = 1 #待機させておくサーバの最小数 pm.max_spare_servers = 4 #待機させておくサーバの最大数 さて。pm.max.childrenまで子プロセスを増やします。このプロセス数が、接続数の上限です。先程、Apacheの同時接続数を150にしておきましたので、うちでは2バージョンのPHPを起動しておきますので、2つで最大200まで。Apacheの奥にいるPHPに、余裕を作っておきます。 さらに、start_servers数だけ、最初に起動しておきます。全部埋まらないように、min_spare_serversで、最低限1つ、空きプロセスとして、次のリクエストに備えます。max_spare_serverで、待機しているPHPは4つまでにしておくので、使い終わったらプロセスを終了させます。 というわけで、忙しいときには増え、使い終わるとプロセスを減らすという、賢い動きをしてくれるわけですね♪ **PHPのキャッシュ(opcacheとPECL-APCu)を設定する [#j4b51446] ***opcache [#u827a9a1] PHP5.5移行、PHPに組み込まれています。opcacheはコードキャッシュで、PHPのプログラムを中間コード化してメモリにキャッシュしておきます。そのため、一度実行されたコードを再度コンパイルしないため、応答速度が改善されます。 /etc/php/XXX-phpX.X/php.iniの以下の項を設定します。 opcache.enable=1 opcache.enable_cli=1 opcache.memory_consumption=128 opcache.interned_strings_buffer=8 opcache.max_accelerated_files=10000 opcache.revalidate_freq=1 opcache.save_comments=1 **PECL-APCu [#o94d9b71] PECL-APCuは、データキャッシュで、データの読み込みを高速化してくれます。 ***コンパイル [#ob16f023] # emerge dev-php/pecl-apcu さて、インストールされたAPCuを設定いたします。/etc/php/XXX-phpX.X/extの下にある、apcu.iniに、以下の項を追加。 apc.shm_size=128M apc.ttl=86400 apc.gc_ttl=86400 これで、php-fpmを再起動してあげます。どうですかね?かなり体感早くなったんじゃありませんか~?? *MySQLのチューニング [#i44d3b73] さて、DBのチューニングってのも、課題になりますよね。そこで、こんな便利ツールがあるそうで。 **mysqltuner [#y25ba22d] # emerge mysqltuner さて、mysqltunerをインストールしましたら、実行してみます。DBの管理ユーザ&パスワード聞かれますので、答えます。うちでは、こんな表示が出てきましたよ。 General recommendations: Run OPTIMIZE TABLE to defragment tables for better performance Reduce or eliminate persistent connections to reduce connection usage Upgrade MySQL to version 4+ to utilize query caching Adjust your join queries to always utilize indexes Set thread_cache_size to 4 as a starting value Increase table_cache gradually to avoid file descriptor limits Variables to adjust: max_connections (> 151) wait_timeout (< 28800) interactive_timeout (< 28800) join_buffer_size (> 64.0M, or always use indexes with joins) thread_cache_size (start at 4) table_cache (> ) さて、このmysqltuner、サーバの運用実績から、改善事項を提示してきますので、mysqlを起動してから、24時間以上経ってから出したほうが良いみたいです。運用しながら、何回か実施してみて下さい。 ***OPTIMIZE TABLE [#yb23c069] テーブルがフラグメントされてるから、最適化しろ、だそうです。こんなコマンドでできます。 # mysqlcheck -u <管理者ユーザ> -p<パスワード> --all-databases --optimize ちなみに、InnoDBの場合は、最適化ができないので、ALTER TABLEで代用してくれるそうです。ありがたいことだ♪ ***my.cnfの調整 [#la2a6cac] 指示に従って、/etc/mysql/my.cnfを変更してあげます。何回かmysqltunerを実行した結果、あれ直せ、これ直せと指示が出ましたので、以下を調整しました。 join_buffer_size =1M table_open_cache = 8192 max_connections = 150 wait_timeout = 20000 interactive_timeout = 20000 thread_cache_size = 4 query_cache_type = 1 query_cache_limit = 16M query_cache_size = 512M skip-name-resolve = 1 innodb_buffer_pool_instances = 7 調整が済んだら、mysqlを再起動しましょう。 # /etc/init.d/mysql restart join_buffer_sizeを大きくしろ、と散々言われます。が、そもそも、インデックス作る方が高速化につながるそうなので、join_bufferをいくら増やしても、アプリ側を変更しないと追いつかない、ということで、増やさなくてもOKというネット記事がありましたので、うちではココまでにしております。 *結果 [#id87c281] 正直、爆速になりました。以前は、正直Wehページが描画される様が目で見て解るぐらいちんたらしていて、まぁ、Webアプリだからこんなもんかな、と半ば諦めていたのですが、2回め以降のページ表示が人間の体感で一瞬で終わります。人の目で見てあきらかに違うので、かなり効果があったと言えるでしょう。超快適♪
(This host) = https://femt.ddo.jp