Skip to content

Instantly share code, notes, and snippets.

@peco8
Created October 29, 2020 05:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save peco8/54b21f779ea6d649804b1309689680a4 to your computer and use it in GitHub Desktop.
Save peco8/54b21f779ea6d649804b1309689680a4 to your computer and use it in GitHub Desktop.
Apacheチューニング

mpm関連

パラメータ説明

項番 項目 説明 補足
1 StartServers Apache起動時の子プロセス数 Apache起動時にまずはここで設定された数の子プロセスを起動します
2 MinSpareServers 待機時の最小子プロセス数 子プロセスがMinSpareServersより少なくなったら、この値まで子プロセスを上げます
3 MaxSpareServers 待機時の最大子プロセス数 子プロセスがMaxSpareServersより大きくなったら、この値まで子プロセスを下げます
4 ServerLimit 設定可能なサーバプロセス数の上限 MaxClientsを256以上に設定したい場合はServerLimitも設定する必要があります。また、 MaxClientsの上に書かないと効きません
5 MaxClients 最大の小プロセス数 この数≒最大の同時接続数です
6 MaxRequestsPerChild 1子プロセスが処理するリクエスト数 ここで設定された数のリクエストを処理すると子プロセスが死んで、新しい子プロセスに生まれ変わります。"0"にすると無制限にリクエストを処理します

チューニング

  • 忙しいサイトなら1-5は全て同じ値に設定してしまいましょう
  • どうせ忙しいサイトならMaxClientには達するんだと思います。であれば、変にメモリをケチらずに最初からMaxClientまで子プロセスを起動してしまったほうがレスポンスが良いです
  • 急激なトラフィック増の際に多くの子プロセスが一気に起動することでシステムのロードがスパイクし、レスポンスを返せなくなることがあるからです
  • mod_wsgiとかmod_perlとか読み込んでいる場合は特に子プロセス起動時のオーバーヘッドは馬鹿にできません
  • かといって、MaxRequestsPerChildを"0"にして子プロセスを殺さないようにするのはやめたほうが良いです。子プロセスのメモリ使用量が肥大化し、システムでスワップが発生する可能性があります。

MaxClient数の算出方法

  • サーバの物理メモリを消費し尽くしてスワップさせないことが重要です
  • httpd1プロセスあたりのメモリ使用量はtopコマンドでおおまかに把握することができます
    • topコマンドで表示されるRES(物理メモリ使用量)です
    • 各プロセス毎に処理している内容によりメモリ量の増減がありますので、いくつかのhttpdプロセスをサンプリングしておおまかに平均値を算出しましょう
  • サーバの物理メモリ量 > 上記で算出した1httpdプロセスあたりのメモリ使用量の平均値×MaxClient数+他のプロセスが使うであろうメモリ使用量 となるようにMaxClient数を設定しましょう
top - 17:29:42 up 6 days, 17 min,  4 users,  load average: 0.92, 1.10, 1.23
Tasks: 237 total,   2 running, 235 sleeping,   0 stopped,   0 zombie
Cpu(s): 24.0%us,  0.8%sy,  0.0%ni, 74.7%id,  0.0%wa,  0.0%hi,  0.5%si,  0.1%st
Mem:  15343788k total, 10152612k used,  5191176k free,   231068k buffers
Swap:        0k total,        0k used,        0k free,  2336312k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
26835 apache    20   0  328m  59m 6400 R 29.6  0.4   0:48.24 httpd
26870 apache    20   0  331m  62m 5884 S 27.2  0.4   0:42.28 httpd
26607 apache    20   0  317m  49m 5872 S 20.3  0.3   0:25.53 httpd
27481 apache    20   0  316m  48m 5876 S 12.3  0.3   0:36.53 httpd
26730 apache    20   0  317m  48m 5880 S  9.6  0.3   0:34.03 httpd
26583 apache    20   0  320m  51m 5884 S  1.3  0.3   0:32.28 httpd

タイムアウト関連

パラメータ説明

項番 項目 説明 補足
1 Timeout リクエストを受け取ってから処理完了までの待機時間 下記のそれぞれの時間にTimeoutが設定されます。1. GET リクエストを受け取るのにかかる総時間 2. POST や PUTリクエストにおいて、次の TCP パケットが届くまでの待ち時間 3. レスポンスを返す際、TCP の ACK が帰ってくるまでの時間
2 KeepAlive 持続的接続を許可する HTTPで定義されているKeepAlive接続を有効にする設定。1つのTCP接続で複数のHTTPリクエストが処理されるようになる
3 MaxKeepAliveRequests 持続的接続で許されるリクエスト数 1回のKeepAlive接続で処理可能なリクエスト数
4 KeepAliveTimeout 持続的な接続で次のリクエストを待つ時間 KeepAliveをOnにしていた場合のみ有効

チューニング

  • Timeoutのデフォルト値は300秒ですが、長過ぎますので、短くしましょう。応答のないクライアントを5分も待つやさしさは不要です。我々は忙しいんです
  • KeepAliveは幻想の機能です。忙しいサイトなら使うのやめましょう。忙しくないサイトならどちらでも良いと思います
  • KeepAliveを有効にすれば、たしかに1回の接続でクライアントから複数のリクエストを送ることができるため、TCP接続のオーバーヘッドやコネクション数が抑えられる気がします
  • しかし、それは幻想です。結局、1クライアントから複数のTCPコネクションを張られ、そのコネクションが長時間専有されることで、Apacheの子プロセスをあっという間に消費しつくされてしまいます
  • KeepAliveをOffにしていればMaxKeepAliveRequestsやKeepAliveTimeoutはいくつでもかまわないです
  • 上記のようにKeepAliveは切ったほうが良いですが、AWSのELB配下では切らない方が良いようです → Amazon ELBをうまくつかうには、KeepAliveを有効にしよう。Timeoutは60秒よりだいぶ長くしよう。その背景。

ログファイル関連

HostnameLookups

  • アクセスをログファイルに記録する際に接続元IPアドレスをDNSで逆引きするオプションです
  • DNSの逆引きは時間がかかることが多いですので、Offにするのは必須です

Apacheチューニングのためのメモリ使用量計算

「/proc/(pid)/status」のメモリサイズからメモリ消費量をリストアップするスクリプトを準備した。

「サーバ/インフラを支える技術」に載っている、id:naoyaさんの共有しているメモリのサイズを計算するスクリプトとあわせて、エクセルに落とし込んでごにょごにょと計測してみる。
[www]~ $ cat memory_size.sh 
#!/bin/sh

GREP="/bin/grep"
AWK="/bin/awk"
PRINTF="/usr/bin/printf"

if [ $# -lt 1 ]; then
    echo "usage: ${0} [pid ...]" 1>&2
    exit 100
fi

$PRINTF "PID\tRSS\t(peak)\tVM\t(peak)\n"

for p in $@
do
    status="/proc/${p}/status"
    if [ -f $status ]; then
        rsssize=`$GREP '^VmRSS:' $status | $AWK '{print $2}'`
        rsspeak=`$GREP '^VmHWM:' $status | $AWK '{print $2}'`
        vmsize=`$GREP '^VmSize:' $status | $AWK '{print $2}'`
        vmpeak=`$GREP '^VmPeak:' $status | $AWK '{print $2}'`
        $PRINTF \
            "%d\t%d\t(%d)\t%d\t(%d)\n" \
            $p \
            $rsssize \
            $rsspeak \
            $vmsize \
            $vmpeak
    fi
done
for p in `pgrep httpd`; do grep "^VmHWM:" /proc/$p/status |awk '{print $2}'; done

で、すみそうな気も。

[www]~ $ ./memory_size.sh `pgrep httpd`
[www]~ $ sudo ./shared_memory_size.pl `pgrep httpd`

からエクセルにデータをもっていて、ごにょごにょと(古いプロセスと新しいプロセスのデータは破棄して、平均を算出、共有を考慮した消費量を予測)……。

(Apache+CakePHPのWebサービスを計測して)おおざっぱに、↓のような数値が算出できた。いまいち計算結果に自信がもてないけど……。

実メモリ上ページサイズ
平均26.77MB
最大31.38MB
最小20.9MB
実メモリ上ページサイズ(ピーク)
平均31.34MB
最大32.91MB
最小30.21MB
共有率
平均32%
最大41%
最小27%

計算結果から、Apacheプロセスのメモリ使用量を32MBと想定、平均して32%程度のメモリを共有するものとして、Apacheプロセスが消費するメモリの予想は平均21.76MB程度か。

Webサーバには4GBを搭載しているので、OSが512MB程度占有するものとして、「(4GB - 512MB) / 21.76MB」でApacheに割り当てられそうなプロセス数は164と算出できる。

余裕をもたせるとして、100~150程度の設定が妥当そうか。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment