連載
» 2005年09月16日 00時00分 公開

実用 Apache 2.0運用・管理術(3):httpd.confによるWebサーバの最適化 (2/3)

[鶴長鎮一,@IT]

KeepAliveの設定

 HTTPはステートレスプロトコルです。クライアント/サーバ間のTCP接続を永続させず、要求に応じて接続の開始/切断を行います。しかし、Webページは通常HTMLドキュメントや画像など、複数のファイルで構成されています。クライアントが1つのWebページを取得する間に、ファイルごとにTCP接続の開始/切断を行うのは大変非効率的です。そこで、KeepAliveを利用して1つの接続を使い回し、複数のリクエストに応えられるようにします。

 KeepAliveの動作にかかわる重要なパラメータが以下に挙げる3つのディレクティブです。

KeepAlive

 「On」にすることで、KeepAliveを有効にします。

KeepAlive On

 現在使用されているWebブラウザはApacheのKeepAliveに完全に対応しているため問題はありませんが、マイナーなクライアントや古いバージョンのWebブラウザではApacheのKeepAliveとの互換性に問題が発生する場合があります。そうしたWebブラウザがメインのクライアントとなっている場合は、KeepAliveを「Off」にすることを検討しましょう。

MaxKeepAliveRequests

 1つのKeepAliveが、開始から切断までに受け付けるリクエスト数を設定するのがMaxKeepAliveRequestsです。

MaxKeepAliveRequests 100

 大きな値を設定すると、一度に処理できるリクエスト数が多くなる代わりに、ほかの接続が割り込むタイミングが遅れることになります。1ページの読み込みが完了したらKeepAliveを終了するように、

1ページ当たりの平均的なファイル数+α

をMaxKeepAliveRequestsの数値にするとよいでしょう。

KeepAliveTimeout

 KeepAliveTimeoutは、KeepAliveで接続を維持しているクライアントからのリクエストがなくてもKeepAliveを維持する秒数を指定します。

KeepAliveTimeout 15

 値を大きくすると、1ページ分の転送が完了した後もクライアントと接続を維持したままになり、ほかのクライアントへの応答が遅れます。通常は次の値を設定します。

1ページ当たりの平均的な転送時間+α

 「1ページ当たりの平均的な転送時間」の算出は、クライアントのネットワーク環境も考慮します。ブロードバンド環境であれば、Webを1ページ表示するのに数秒程度であっても、ナローバンド環境では数十秒になることもあります。

 しかし、あまり神経質になる必要はありません。デフォルトの15秒から少しずつ減らしながら調整します。KeepAliveが無駄に残留し、サーバのリソースが消費されることを嫌うなら「2」など、極端な値を設定します。

プロセスの設定(prefork MPM)

 Apache 2.0はマルチスレッドに対応し、旧来のプロセス処理からパフォーマンスを向上させていますが、デフォルト設定ではプロセスベースの処理になっています。ここでは、プロセスベースで起動されているApacheを前提に、重要な設定項目を紹介します。

 ここで紹介する値を設定するには、メモリやプロセスの使用状況を把握しておく必要があります。その方法については後述します。

<IfModule prefork.c>
StartServers       8
MinSpareServers    5
MaxSpareServers   20
ServerLimit      256
MaxClients       256
MaxRequestsPerChild  4000
</IfModule>
prefork MPM(プロセスベース)を使用しているhttpd.confの一例

 Apacheは複数のプロセスを起動し、同時に多くのリクエストに応じます。当然、起動しておくプロセスが多いに越したことはありませんが、使用されないプロセスでリソースを消費するような無駄は避ける必要があります。しかし、リクエストが発生してから新たなプロセスを立ち上げていたら、レスポンスが悪化します。

 プロセスはサーバに大きな負荷を与え、起動には時間を要します。そこで待機プロセスを用いて、サーバのリソースが無駄にならない程度のプロセスをあらかじめ立ち上げておき、要求に備えるようにします。Apacheは、待機プロセスの消費に応じて動的にプロセス数を調整することができます。これらの動作に必要なパラメータが下記のディレクティブです。

StartServers

 StartServersは、Apacheを立ち上げた際に最初に起動するプロセス数です。サーバの立ち上げと同時に高アクセス数を記録するようなら、この値は後述するMaxClientsに近い値を設定する必要があります。しかし、待機プロセスは以下で紹介するMinSpareServers/MaxSpareServersの値に応じて動的に調整されるため、デフォルトの5〜10の値で十分です。StartServersの値を増やすと、Apacheの起動時間が長くなりサービスのダウンタイムが大きくなります。

StartServers         5

 StartServersの変更に当たっては、デフォルト値の場合と数を増やした状態とで、1プロセス当たりの起動にどれくらいの時間差が発生するかを調べておきましょう。調査結果は、MinSpareServers/MaxSpareServersの設定の参考になります。

MinSpareServers/MaxSpareServers

 Apacheは、MinSpareServers値〜MaxSpareServers値のプロセスが常時待機しているようにプロセス数を調整します。待機プロセスが消費されそうになると、新たなプロセスを生成します。

MinSpareServers      5
MaxSpareServers     10

 MinSpareServers/MaxSpareServersは、過度な待機プロセスが発生しないように、

MinSpareServers < MaxSpareServers

になる値を設定します。

 待機プロセスを使い切り、新たなプロセスの起動が間に合わない状況になっているなら徐々に値を上げ、消費されるプロセス数と起動するプロセス数のバランスを保つようにします。下で紹介しているMaxClientsの値まで上げることもできますが、無駄に高い値を設定して待機プロセスでサーバのリソースを浪費しないように注意しましょう。

MaxClients/ServerLimit

 error_logに

[Thu Aug 25 19:40:06 2005] [error] server reached MaxClients setting, consider raising the MaxClients setting

のようなエラーが出力されるようなら、MaxClientsの値を上げる必要があります。ただし、ServerLimitより大きな値を設定することはできないため、MaxClientsの値を上げる際は併せてServerLimitも変更する必要があります。

ServerLimit        150
MaxClients         150

 Apacheは、最大でMaxClients個のプロセスを起動させます。高アクセスのサーバでは当然高い値を設定し、クライアントの要求に応えられるようにする必要があります。ただし、高い値にし過ぎると、メモリを使い切りスワップが発生するなど、かえってレスポンスが悪化します。MaxClientsの設定に際しては、以下の式が目安になるでしょう。

MaxClients=使用可能なメモリ量/Apacheの1プロセスが使用するメモリ量

 式は単純ですが、事前に「使用可能なメモリ量」と「Apacheの1プロセスが使用するメモリ量」を正確に算出するのは大変難しい作業です。

 「使用可能なメモリ量」は、サーバに搭載されているメモリから、OSやApache以外のプロセスが使用するメモリを引いた値になります。「Apacheの1プロセスが使用するメモリ量」を算出するのはさらに難しく、また画像やHTMLファイルだけの静的なコンテンツの場合とPerlやPHPなどの動的コンテンツの場合とでは使用するメモリ量も変わってきます。共有メモリ分を加味する必要もあるでしょう。経験的には、静的コンテツの場合で数Mbytes、動的コンテンツで20〜30Mbytesと大きな差があり、平均を求めるのは骨が折れます。

 そこで、値を少しずつ上げていき、vmstatやtopなどのコマンドでスワップへの書き込みが発生しない値を調べる必要があります。vmstatやtopコマンドの使い方については、Linux Tips「メモリの使用量を調べるには」を参照してください。

 起動できるプロセス数には、OSの限界もあります。OSの限界を超えるMaxClientsを設定することはできません。Linuxでは、ulimitコマンドでこれを確認できます。変更もulimitコマンドを使用します。

# ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
file size               (blocks, -f) unlimited
pending signals                 (-i) 8063
max locked memory       (kbytes, -l) 32
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 8063 ←最大プロセス数
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
# ulimit -u 10000 ←max user processesの値を10000に変更
# ulimit -a ←確認
...
max user processes              (-u) 10000 ←変更後

MaxRequestsPerChild

 CGIやPHPなどを使った動的コンテンツを使用していると、Apacheのプロセス数は増えていないのに使用メモリが増えていく現象に遭遇することがあります。これはメモリリークを引き起こすようなプログラムを動的コンテンツ内で使用しているためです。例えば、データベースとの接続を必要とするプログラムが、データベースの操作後も接続を解放しないなどの原因が考えられます。

 プログラムを見直すことが第一ですが、Apache側でも使い回しているプロセスを定期的に再起動させることで、取りあえずはメモリリークを防ぐことができます。メモリリーク以外にも、プロセスを定期的に再起動することでコンテンツの不具合が改善されることがあります。これらの場合は、MaxRequestsPerChildで再起動タイミングを設定します。

MaxRequestsPerChild  0

 再起動タイミングは、不具合の程度にもよりますが、なるべく「5000」や「6000」といった大きな値を設定します。指定が「0」の場合は無制限を意味し、プロセスの再起動は行われません。画像やHTMLドキュメントのみで構成された静的コンテンツの場合は、「0」のままで使用します。

 なお、不用意に値を設定すると、プロセスの再起動に引っ張られてサーバのパフォーマンスやクライアントへのレスポンスが低下します。

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。