naoya です。最近、とうとう花粉症の季節に入ったので、生まれて初めて空気清浄機を購入しました。
さて、今日は Apache HTTP サーバの MPM (Multi Processing Module) について解説したいと思います。普段、ウェブサーバを構築するとき、Apache HTTP サーバを使うことが多いと思いますが、Apache HTTP サーバを使う上で MPM について理解しておくことは大事です。
この MPM ですが、Apache HTTP サーバではリクエストを処理する部分のことをさします。MPM は、Apache HTTP サーバ 2.0 系から採用されています。Apache HTTP サーバの MPM には、次の種類があります。
- prefork
- worker
- perchild
- winnt
それぞれの MPM について解説します。まずは、一番代表的な prefork MPM について解説します。prefork MPM の特徴は、次のとおりです。
- Apache HTTP サーバ 1.3 系以前のモデル
- 1 つのリクエストに対して、1 プロセスを割り当てる
- 負荷に応じて、子プロセスを増減させる
prefork MPM は、次に解説する worker MPM と同じくらいよく使われる MPM です。PHP で使うときは、PHPで書かれたwebサービスを高速化する にもあるとおり、prefork MPM を使う必要があります。PHP を使うとき、worker MPM を使うことは推奨されていないので注意してください。
prefork MPM のデフォルト設定は、次のようになっています。prefork MPM では、ServerLimit と MaxClients は同じ値を設定します。
StartServers 8
MinSpareServers 5
MaxSpareServers 20
ServerLimit 256
MaxClients 256
MaxRequestsPerChild 4000
関連するディレクティブの説明は、次のとおりです。
- StartServers: 最初に起動する子プロセスの数
- MinSpareServers: 待機する子プロセスの最小数
- MaxSpareServers: 待機する子プロセスの最大数
- MaxClients: 生成する子プロセスの最大数
- MaxRequestsPerChild: それぞれの子プロセスが扱うリクエスト数の制限数
フォト蔵 のウェブサーバも prefork MPM を使っています。フォト蔵のウェブサーバの設定は、次のとおりです。
StartServers 8
MinSpareServers 5
MaxSpareServers 30
ServerLimit 300
MaxClients 300
MaxRequestsPerChild 50
MaxRequestsPerChild の値が小さいのが特徴だと思います。MaxRequestsPerChild を小さくしている理由は、PHP を使っているとかなりメモリを消費するため、頻繁に子プロセスを生成しなおしたいためです。
prefork MPM を使う場合、大量のアクセスを捌きたい場合には MaxClients の値を増やせばいいのですが、あまり増やしすぎてしまうとメモリ不足などになることが多いので、MaxClients を増やすときは ab(Apache Bench) コマンドなどを使って負荷テストを粉って、どのくらいまで設定できるのか見極める必要があります。
次に workder MPM について解説します。worker MPM の特徴は、次のとおりです。
- スレッド対応型
- リクエスト処理は、スレッドが対応する
- 負荷に応じて、子プロセス数を増減させる
- 1 子プロセスあたりのスレッド数は固定になっている
worker MPM は、子プロセス数を増減させるというところは prefork MPM と似ていますが、リクエスト処理をスレッドが対応するというところが大きく違っています。worker MPM は子プロセスを生成したとき、リクエスト処理をするスレッドを最初にすべて生成するので、新しいリクエストがきたとき、prefork MPM のように子プロセスの生成を待つ必要がないので prefork MPM よりパフォーマンスがいいです。(*1)
worker MPM のデフォルト設定は、次のようになっています。
StartServers 2
MaxClients 150
MinSpareThreads 25
MaxSpareThreads 75
ThreadsPerChild 25
MaxRequestsPerChild 0
関連するディレクティブの説明は、次のとおりです。
- StartServers: 最初に起動する子プロセスの数
- MinSpareThreads: アイドル状態のスレッド最小数
- MaxSpareThreads: アイドル状態のスレッド最大数
- MaxClients: 生成する子プロセスの最大数
- ThreadsPerChild: 子プロセスそれぞれに生成されるスレッド数
- MaxRequestsPerChild: それぞれの子プロセスが扱うリクエスト数の制限数
次に perchild MPM について解説します。perchild MPM の特徴は、次のとおりです。
- スレッド対応型
- リクエスト処理は、スレッドが対応する
- 負荷に応じて、スレッド数を増減させる
- 子プロセスの数は固定になっている
perchild MPM は、worker MPM の反対のような特徴をもっており、スレッド数だけが増減する仕組みとなっています。そのため、子プロセスの生成を待つ必要がなく、スレッドも必要なだけになるため、もっともリソースを有効に使うことができる MPM といえます。ただし、prechild MPM は不安定な面もあるという情報があるので、本番環境で使う前には入念なテストが必要です。
最後に winnt MPM について解説します。winnt MPM の特徴は、次のとおりです。
- スレッド対応型
- リクエスト処理は、スレッドが対応する
- Windows NT に特化したスレッドモデル
winnt MPM は、その名の通り Windows NT 向けに特化した MPM です。Windows 上の Apache HTTP サーバでは、winnt MPM がデフォルトで使われます。
というわけで、今回は Apache HTTP サーバの MPM について解説しました。普段から使っているオープンソースでも内部の仕組みを理解しておくと、何かのトラブルに遭遇したときに助けのヒントになることがあるので、仕組みを理解するということを大事にしてきたいと思います。
(*1) 追記:prefork MPM より worker MPM の方がパフォーマンスが高い理由は、リクエスト処理をするために子プロセスを生成するではなくスレッドを使うところにありますが、プロセスとスレッドの生成コストの違いについては別の機会にエントリしたいと思います。