Y's note

Web技術・プロダクトマネジメント・そして経営について

本ブログの更新を停止しており、今後は下記Noteに記載していきます。
https://note.com/yutakikuchi/

Apacheのチューニング

Apacheをより有効的に利用するためのノウハウメモです。設定に用いたマシンはMacOSXApacheのバージョンは2.2としています。

http headers

http://www.yahoo.co.jp/

GET / HTTP/1.1
Host: www.yahoo.co.jp
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 8.12; MSIEMobile 6.5) KDDI-TS01 Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; KDDI-TS01; Windows Phone 6.5.3.5)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Cookie: B=XXXXXXXXXXX

HTTP/1.1 200 OK
Date: Sun, 09 Oct 2011 03:16:08 GMT
P3P: policyref="http://privacy.yahoo.co.jp/w3c/p3p.xml", CP="CAO DSP COR CUR ADM DEV TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE GOV"
Expires: -1
Pragma: no-cache
Cache-Control: no-cache, private, no-store, must-revalidate
X-XRDS-Location: http://open.login.yahoo.co.jp/openid20/www.yahoo.co.jp/xrds
Vary: Accept-Encoding
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
----------------------------------------------------------
http://news.c.yimg.jp/images/topics/20111009-00000003-sph-000-thumb.jpg

GET /images/topics/20111009-00000003-sph-000-thumb.jpg HTTP/1.1
Host: news.c.yimg.jp
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 8.12; MSIEMobile 6.5) KDDI-TS01 Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; KDDI-TS01; Windows Phone 6.5.3.5)
Accept: image/png,image/*;q=0.8,*/*;q=0.5
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Referer: http://www.yahoo.co.jp/

HTTP/1.1 200 OK
Date: Sat, 08 Oct 2011 23:58:52 GMT
Cache-Control: max-age=2592000
Expires: Mon, 07 Nov 2011 23:58:52 GMT
Last-Modified: Sat, 08 Oct 2011 23:58:51 GMT
Accept-Ranges: bytes
Content-Length: 4013
Content-Type: image/jpeg
Age: 11836
Via: HTTP/1.1 l7cache4047.img.bbt.yahoo.co.jp (YahooTrafficServer/1.18.6 [cHs f ]), HTTP/1.1 l7switch4008.img.bbt.yahoo.co.jp (YahooTrafficServer/1.19.8 [cHs f ])
Server: YTS/1.19.8
Connection: keep-alive
  • yahooのTopページにアクセスした時のHttp Request/Response Headerの情報。
  • サイトにアクセスした時のHttpHeaderでサーバサイドの設定をなんとなく理解する事が可能。Cacheの設定、KeepAliveの有効期限、動的コンテンツと静的コンテンツの切り分けなど。
  • yahooでは動的コンテンツ配信するサーバと静的な画像やCSSを配信するサーバを別ドメインで構えていて、それぞれに対して設定を分けている様子。ドメインを分けるとブラウザは並列してリクエストが可能。また画像配信のサーバは間にキャッシュ専用のProxyサーバを挟んでいるみたい。
  • 現在Yahooのトップページにアクセスすると402ms(onload :1.56s)でコンテンツの閲覧が可能。とても早い。
  • 今日の記事ではApacheのチューニング/http header周りについて記録する。

preforkとworkerモデル

  • Apache2.0以降、サーバでリクエストする処理がモジュール化(MPM:マルチプロセッシングモジュール)され数種類から選ぶ事が可能になった。代表的なものとしてpreforkとworkerがある。
  • preforkとはクライアントからのリクエストを子プロセスで起動し、子プロセスがフリーズしても他のプロセスには影響しないモデル。
  • workerはApacheの子プロセスがマルチスレッドで動作。クライアントに対してはスレッドが応答。1つのプロセスがマルチスレッドを利用して複数の通信を受け付ける。preforkと比較して子プロセスの起動を少なくできるのでメモリの使用量を減らす事が可能。
  • 場合にもよるがworkerモデルを扱う場合は注意が必要。不安定という話もある。(PHPのいくつかのモジュールが動かない)workerモデルがテストして問題なければメリットはある。
vailable, but does not work with some modules (such as PHP).
  • apacheのバージョン/状態をを確認するにはhttpd -V
$ httpd -V
Server version: Apache/2.2.17 (Unix)
Server built:   Dec  1 2010 09:58:15
Server's Module Magic Number: 20051115:25
Server loaded:  APR 1.3.8, APR-Util 1.3.9
Compiled using: APR 1.3.8, APR-Util 1.3.9
Architecture:   64-bit
Server MPM:     Prefork
  threaded:     no
    forked:     yes (variable process count)
Server compiled with....
 -D APACHE_MPM_DIR="server/mpm/prefork"
 -D APR_HAS_SENDFILE
 -D APR_HAS_MMAP
 -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
 -D APR_USE_FLOCK_SERIALIZE
 -D APR_USE_PTHREAD_SERIALIZE
 -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 -D APR_HAS_OTHER_CHILD
 -D AP_HAVE_RELIABLE_PIPED_LOGS
 -D DYNAMIC_MODULE_LIMIT=128
 -D HTTPD_ROOT="/usr"
 -D SUEXEC_BIN="/usr/bin/suexec"
 -D DEFAULT_PIDLOG="/private/var/run/httpd.pid"
 -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
 -D DEFAULT_LOCKFILE="/private/var/run/accept.lock"
 -D DEFAULT_ERRORLOG="logs/error_log"
 -D AP_TYPES_CONFIG_FILE="/private/etc/apache2/mime.types"
 -D SERVER_CONFIG_FILE="/private/etc/apache2/httpd.conf"
  • 読み込まれているモジュールを確認するのはhttpd -l prefork.cが設定されているのが分かる。
$ httpd -l
Compiled in modules:
  core.c
  prefork.c
  http_core.c
  mod_so.c
  • MacOSXの場合、以下のようにport installコマンドを実行するとworkerモデルに設定し、起動してくれる。起動時に切り替えれると便利だなと思っているのだが、やり方を現在調査中。
$ port variants apache2
apache2 has the variants:
   eventmpm: Use event MPM (experimental)
     * conflicts with preforkmpm workermpm
   no_startupitem: Do not create a startup item
   openldap: Enable LDAP support through OpenLDAP
[+]preforkmpm: Use prefork MPM
     * conflicts with eventmpm workermpm
   universal: Build for multiple architectures
   workermpm: Use worker MPM
     * conflicts with eventmpm preforkmpm
$ sudo port install apache2 +workermpm
$ port installed | grep apache
  apache2 @2.2.21_0+workermpm (active
  • CentOSの場合だとApacheの設定ファイルを書き換えてリスタートすればprefork/workerモデルの切り替えが可能。defaultはpreforkモデルの設定の様子。
$ sudo vim /etc/sysconfig/httpd
HTTPD=/usr/sbin/httpd.worker  #これを指定する
$ sudo /etc/init.d/httpd restart
  • prefork,workerの切り替えでStartServersなどのパラメータを変更できるような仕組みになっている。
$ vi -R /private/etc/apache2/extra/httpd-mpm.conf
# prefork MPM
# StartServers: number of server processes to start
# MinSpareServers: minimum number of server processes which are kept spare
# MaxSpareServers: maximum number of server processes which are kept spare
# MaxClients: maximum number of server processes allowed to start
# MaxRequestsPerChild: maximum number of requests a server process serves
<IfModule mpm_prefork_module>
    StartServers          1
    MinSpareServers       1
    MaxSpareServers      10
    MaxClients          150
    MaxRequestsPerChild   0
</IfModule>

# worker MPM
# StartServers: initial number of server processes to start
# MaxClients: maximum number of simultaneous client connections
# MinSpareThreads: minimum number of worker threads which are kept spare
# MaxSpareThreads: maximum number of worker threads which are kept spare
# ThreadsPerChild: constant number of worker threads in each server process
# MaxRequestsPerChild: maximum number of requests a server process serves
<IfModule mpm_worker_module>
    StartServers          2
    MaxClients          150
    MinSpareThreads      25
    MaxSpareThreads      75
    ThreadsPerChild      25
    MaxRequestsPerChild   0
</IfModule>

設定ファイルチューニング

httpd.confに設定するパラメータをチューニングする。パラメータの説明は次の通り

パラメータ 説明
StartServers Apache起動時のプロセス数
MinSpareServers 予め待機させておくプロセス起動の最小値
MaxSpareServers 予め待機させておくプロセス起動の最大値
MaxRequestsPerChild プロセスの処理数が値を超えたらプロセスを終了させる
ThreadsPerChild プロセスあたりのスレッド数
ServerLimit プロセスの最大数
ThreadLimit スレッドの最大数
MaxClients 同時接続可能数
Timeout システム処理のTimeout
KeepAlive 通信状態を保持する機能
MaxKeepAliveRequests KeepAliveで接続している間に処理するリクエスト数
KeepAliveTimeout KeepAliveの有効時間

設定値サンプル

StartServers 2
ServerLimit 32
ThreadLimit  128
MaxClients 4096
ThreadsPerChild 128
MinSpareServers 25
MaxSpareServers 75
MaxRequestsPerChild 0
Timeout 60
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5
  • 重要な項目はThreadsPerChild,MaxClients,KeepAlive,ServerLimit,ThreadLimit
  • ThreadsPerChild,MaxClientsはサーバのリソース消費量に影響は与えない。
  • ServerLimit,ThreadLimitは共有メモリのサイズに依存。
  • パラメータの算出式は MaxClients = プロセス数 × ThreadsPerChild。上の例の場合 4096 = 32 × 128
  • メモリが充実しているマシン(4GBとか)なら10000クライアント接続ぐらい可能。(リバースProxyサーバなら)

mod_ほにゃらら

以下apacheのモジュールで導入するとよりシステム処理がより高速になったりセキュリティレベルを高める事ができる。

モジュール名 役割
mod_rewrite 特定の条件を指定し、アクセスを振り分ける事ができる。Redirect/Rewrite等が可能
mod_perl/mod_php サーバ内部でプロセスを常駐
mod_gzip/mod_deflate クライアント側への転送データを圧縮し、データ通信量を削減
mod_dosdetector Dos攻撃を判定。特定のIPから閾値以上のアクセス等をabuse
mod_proxy リバースProxyの設定が可能
mod_ssl ApacheSSL対応にする事が可能

keepAlive

  • httpの仕様でサーバとのConnectionをまとめる事ができる。例えばHTMLの内部に多数の画像を取得するタグが埋め込まれている時に都度同じサーバに対してConnectionを確立してしまうと接続のOverHeadが発生し処理が遅くなってしまう。それを回避するために一度確立したConnectionを特定の時間内で再利用することが出来る仕組み。
  • KeepAliveをONにするとWebサーバ側に負担がかかる。なぜならば特定クライアントとの接続を占有してしまうから。
  • リバースProxyを使う場合、クライアント-リバースProxy間はKeepAliveをOnに設定し、リーバスProxy-Webサーバ間はKeepAliveをOffにする。これはリバースProxyサーバ内部のメモリ使用率は低く、Webサーバはメモリ負荷が高くなるという処理の特性を考えての設定。
  • KeepAliveの設定例
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5

gzip,deflate

  • Apache1.3系ならmod_gzip,2系ならmod_deflateを利用し、データ転送量を圧縮する。
  • データ転送量を抑える反面、サーバサイドのCPUが高負荷になる可能性がある。
  • 設定は簡単でhttpd.confにLoadModuleとどのファイルにdeflate処理をかけるかを記述するだけ。
  • deflateの設定例
LoadModule deflate_module libexec/apache2/mod_deflate.so
AddOutputFilterByType DEFLATE text/html text/plain text/xml
LoadModule gzip_module libexec/mod_gzip.so
AddModule mod_gzip.c
mod_gzip_on Yes
mod_gzip_keep_workfiles No
mod_gzip_minimum_file_size  1002
mod_gzip_maximum_file_size  0
mod_gzip_maximum_inmem_size 60000
mod_gzip_dechunk Yes
mod_gzip_temp_dir "/tmp"(注1)
mod_gzip_item_include  mime "application/x-httpd-cgi"
mod_gzip_item_include  mime "application/x-httpd-php"
mod_gzip_item_include  mime text/*
mod_gzip_item_include  mime "httpd/unix-directory"
mod_gzip_item_include  file "\.shtml$"
mod_gzip_item_include  file "\.htm$"
mod_gzip_item_include  file "\.html$"
mod_gzip_item_include  file "\.php$"
mod_gzip_item_include  file "\.pl$"
mod_gzip_item_include  file "\.cgi$"
mod_gzip_item_exclude  file "\.css$"
mod_gzip_item_exclude  file "\.js$"
mod_gzip_item_exclude  mime "image/.*"
mod_gzip_min_http 1001

Apache Bench

  • ApacheのBenchマークスクリプト(ab)を使う。
  • abを得た結果から重たいページが一目瞭然となる。
  • PHPのcodeのパフォーマンス状態を解析したいのであればxdebug + webgrindという方法もある。
  • abの使い方
$ ab -option URL
  • オプション一覧
オプション 説明
-n int リクエストする総数
-c int 同時リクエスト数
-t int レスポンスの待ち時間を秒で指定
-p filename ファイル送信名を指定
-T content-type Content-Typeを指定
-v int 動作情報を表示
-w テスト結果をHTMLで出力
-x attribute HTML出力のtableタグに属性を追加
-y attribute HTML出力のtrタグに属性を追加
-z attribute HTML出力のtd/thタグに属性を追加
-C CookieName=value Cookieを送信
-A UserName:Pass ベーシック認証を特定のUser/Passで通過させる
-P UserName:Pass 認証の必要なプロキシを通してテストさせる
-X ProxyServer:Port プロキシ経由でのリクエスト
-V abバージョン番号表示
-k KeepAliveを有効化
  • Yahoo!のサイトに10×10のRequestをしてみたが、ほとんど失敗している。(おそらくDOS攻撃を防いでいる)
$ ab -n 100 -c 10 http://www.yahoo.co.jp/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking www.yahoo.co.jp (be patient).....done


Server Software:        
Server Hostname:        www.yahoo.co.jp
Server Port:            80

Document Path:          /
Document Length:        25674 bytes

Concurrency Level:      10
Time taken for tests:   2.956 seconds
Complete requests:      100
Failed requests:        92
   (Connect: 0, Receive: 0, Length: 92, Exceptions: 0)
Write errors:           0
Total transferred:      2625836 bytes
HTML transferred:       2570936 bytes
Requests per second:    33.83 [#/sec] (mean)
Time per request:       295.561 [ms] (mean)
Time per request:       29.556 [ms] (mean, across all concurrent requests)
Transfer rate:          867.60 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       28   42  11.8     38      66
Processing:   212  250  18.8    249     299
Waiting:       33   49   9.2     49      82
Total:        240  292  19.1    290     337

Percentage of the requests served within a certain time (ms)
  50%    290
  66%    301
  75%    302
  80%    303
  90%    330
  95%    335
  98%    336
  99%    337
 100%    337 (longest request)
  • パフォーマンスの重要となる指標はRequests per second(秒間あたりの処理数),Time per request(1リクエストあたりの処理時間)。rpsは数値が大きい方が良いし、tprは少ない方がより良い。

リバースProxyを使う

  • リバースProxyとはクライアントとWebサーバ間に設置して、事前/事後処理を行うProxyサーバ。リバースProxyはWebサーバ間の処理振り分けが可能。
  • リーバスの意味はWAN→LANの流れで処理を要求するから(通常のProxyサーバLAN→WANで働くから)。
  • httpリクエスト処理の振り分け、メモリの効率的な使用、データのバッファリング、キャッシュなどが導入のメリット
  • Apache,lighttpd,squidを利用することで実現が可能。
  • Apacheの場合はmod_proxyを利用する。
  • 静的/動的コンテンツを含むページの場合は導入した方が良い。コンテンツの特性によりリクエスト先を分ける等。

mod_proxy

  • mod_proxyの簡単な設定について記述する。
  • httpd.confにモジュールを追加する。
LoadModule proxy_module libexec/apache2/mod_proxy.so
  • 覚えておくべきディレクティブ
名前 説明
ProxyRequests フォワードプロキシサーバとしての動作の有効/無効の設定
ProxyPass リモートサーバをローカルサーバの名前空間マッピング
ProxyPassReverse HTTP リダイレクト応答の Location, Content-Location, URI ヘッダの調整
ProxyPassReverseCookieDomain リバースProxyサーバからのSet-CookieヘッダのDomain文字列を調整
ProxyPassReverseCookiePath リバースProxyサーバからのSet-Cookie ヘッダの Path 文字列を調整
  • ProxyPassを使っている場合はProxyRequestsのディレクティブはoffにすべき。
  • 単純なディレクティブ設定例
ProxyRequests Off
ProxyPass /foo http://www.example.com
ProxyPassReverse /foo http://www.example.com
ProxyPassReverseCookieDomain www.example.com www.example1.com
ProxyPassReverseCookiePath / /proxy/
    • /fooへのアクセスをwww.example.comにプロキシリクエストに変換(ProxyPass)。
    • /fooへのアクセスでwww.example.comがリダイレクトした時にリダイレクト先の情報をHttpHeaderに書き込む(ProxyPassReverse)
    • ヘッダのURLの代わりにSet-CookieヘッダのDomain文字列を書き換え。www.example.comをwww.example1.comに変更 (ProxyPassReverseCookieDomain)。
    • ヘッダのURLの代わりにSet-Cookieヘッダのpath文字列を書き換え。 / を/proxyに変更(ProxyPassReverseCookiePath)