ふとしたキッカケ
Apache httpサーバが2.2系から2.4系にアップデートされた事がキッカケでした。せっかくなので、USEフラグを攻めてみようと。そしたらば…MPMという指定がOFFになっていたのです。ヽ(~~~ )ノ ハテ?MPMってなんだろう?
Multi Processing Moduleという名称からも分かるように、mpmとはapacheの並列処理を行うmoduleです。
ほほう、なるほど…並列処理用のモジュールの指定、ということだったのね。せっかくアップデートするのであれば、ピカピカの状態で使用したい、と言うことで、Apache+PHPの実行環境を攻めて行くこととします。
MPMの種類
ApacheのMPMにはいくつか種類があり、必ず実行プロセスについて1つだけを指定します。同時利用はNGです。さて、どんな種類があるか?
- prefork
- HTTPリクエストに1つのプロセスを割り当てる。つまり、たくさんのリクエストを同時に捌きたい場合には、たくさんプロセスをたちあげておく
- worker
- HTTPリクエストに1つのスレッドを割り当てる。起動しておくプロセス数、プロセス内のスレッド数は設定によって変更する
- itk
- preforkと一緒だが、スクリプトを実行するユーザ権限を分けることができる。例えばApacheさんとか、rootさんとか、各ユーザさんとか
- perchild
- workerと同じ考え方だが、バーチャルホスト毎にプロセス数/実行ユーザを割り当てる
- event
- workerと同じく、プロセス/スレッドの組み合わせだが、非同期I/O型*1となっており、設定如何では最も高速
一般的に使用されるのはprefork/worker。eventは2.2系ではExperimental(実験的)サポート、2.4系では標準推奨のMPMです。ちなみに、preforkよりもworkerの方が動作効率は良いです。何故ならば…プロセスの起動/停止/切り替えはOSにとって重い処理、スレッドの起動/停止/切り替えは軽い処理だからです。よし!それじゃあworkerかeventで決まり!と言いたいところですが、そうはなかなか行きません。スレッドは、メモリ空間を共有するため、きちんと排他処理されていないと誤動作する可能性が高いのです。きちんと処理されている処理系のことを、スレッドセーフな実装と言います。スレッドセーフじゃない処理系を使用する場合は使用するべきではありません。
MPMを選択してコンパイルする
/etc/portage/make.confに、以下の記載を追加します。ちなみに、今回は攻めるので、event MPMで高速なWebサーバを目指します。
APACHE2_MPMS=event
# emerge apache2
MPMのチューニング
/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の並列動作について
PHPをマルチスレッドで動作させるのは非推奨だと、PHPホームページに記載されています。やるならFastCGIを使えとのこと。なわけで、FastCGIの設定をしてみます。
FastCGIをやってみる
さて、FastCGIの設定は、このページのApache&PHP7.1の部分だけ設定すると、うまくいきますよ~
チューニング
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つまでにしておくので、使い終わったらプロセスを終了させます。
というわけで、忙しいときには増え、使い終わるとプロセスを減らすという、賢い動きをしてくれるわけですね♪
opcache
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
コンパイル
# 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を再起動してあげます。どうですかね?かなり体感早くなったんじゃありませんか~??
mysqltuner
# 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
テーブルがフラグメントされてるから、最適化しろ、だそうです。こんなコマンドでできます。
# mysqlcheck -u <管理者ユーザ> -p<パスワード> --all-databases --optimize
ちなみに、InnoDBの場合は、最適化ができないので、ALTER TABLEで代用してくれるそうです。ありがたいことだ♪
my.cnfの調整
指示に従って、/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というネット記事がありましたので、うちではココまでにしております。
Page Info | |
---|---|
Page Name : | Gentoo Linuxな生活/Webサーバ高速化で悩む |
Page aliases : | None |
Page owner : | maruo |
Can Read | |
Groups : | All visitors |
Users : | All visitors |
Can Edit | |
Groups : | No one |
Users : | No one |