BLOG | システム監視・サーバ監視・障害監視・ネットワーク監視・システム運用・MySQL・Web地図を提供

BLOG エントリ一覧

前回からの続きです。

httpd.confに

CODE:

  1. FileETag None

を付与するとレスポンス内容は以下の通り、Etagが返却されなくなる。

CODE:

  1. HTTP/1.x 200 OK
  2. Date: Tue, 08 May 2007 06:39:22 GMT
  3. Server: Apache/2.2.4 (Unix)
  4. Last-Modified: Sat, 20 Nov 2004 20:16:24 GMT
  5. Accept-Ranges: bytes
  6. Content-Length: 44
  7. Connection: close
  8. Content-Type: text/html

Etagが返却されないので、次回以降のリクエストには「If-None-Match:」も
当然付与されなくなる。

FileETagの記載方法は以下のようなパターンが考えられます。

  • /usr/local/apache2/htdocs/images配下のコンテンツにはETagを付けない
  • 画像ファイルの拡張子を持つコンテンツにはETagを付けない
  • すべてのコンテンツにETagを付けない

結局どのように設定すべきなのかということですが

動的ページについてはそもそもファイルではないのでいずれにせよEtagは返却されません。
なので関係ありません。

静的コンテンツについては負荷分散サーバーの振り分け論理によって替わってきます。

1)ラウンドロビン等、毎回異なるWWWサーバーへアクセスする可能性がある場合

FileETag None

FileETag MTime Size
とすべきです。

2)ソースIPアドレス等で一貫性のある振り分け論理の場合

基本的に同一ユーザは同一WWWサーバーに振り分けられるので、初期設定のままでかまわないはずです。

あと、もう少しだけmod_cacheを深追いしてみる という記事に、Firefox 1.5/2.0、IE7が以下のケースでどんなリクエストを送信するのか整理されていました。

  • 通常のページロード
  • リロードボタン
  • 強制リロード(Firefoxの強制リロードはCtrl+Reload、IE7の強制リロードはShift+Reload)

このページ の記事全体がとてもためになります。

 

関連会社インターオフィスのブログ記事を転載しています。

実例から入ります。
http://xxxxxxxx/をリクエストします。
このURLへのアクセスは始めてです。

以前、書いた Firefoxのプラグイン Live HTTP Headers でHTTP通信のみをトレースしました。

———————————————————-
以下がリクエスト内容(初回アクセス)
———————————————————-

CODE:

  1. GET / HTTP/1.1
  2. Host: xxxxxxxx
  3. User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; ja; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3
  4. Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
  5. Accept-Language: ja,en-us;q=0.7,en;q=0.3
  6. Accept-Encoding: gzip,deflate
  7. Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7
  8. Keep-Alive: 300
  9. Connection: keep-alive

———————————————————-
以下がレスポンス内容(初回アクセス)
———————————————————-

CODE:

  1. HTTP/1.x 200 OK
  2. Date: Mon, 07 May 2007 11:49:33 GMT
  3. Server: Apache/2.2.4 (Unix)
  4. Last-Modified: Sat, 20 Nov 2004 20:16:24 GMT
  5. Etag: “4c602bd-2c-4c23b600″
  6. Accept-Ranges: bytes
  7. Content-Length: 44
  8. Connection: close
  9. Content-Type: text/html

そこでリロードして、再度リクエストを出しました。

———————————————————-
以下がリクエスト内容(2回目のアクセス)
———————————————————-

CODE:

  1. GET / HTTP/1.1
  2. Host: xxxxxxxx
  3. User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; ja; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3
  4. Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
  5. Accept-Language: ja,en-us;q=0.7,en;q=0.3
  6. Accept-Encoding: gzip,deflate
  7. Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7
  8. Keep-Alive: 300
  9. Connection: keep-alive
  10. If-Modified-Since: Sat, 20 Nov 2004 20:16:24 GMT
  11. If-None-Match: "4c602bd-2c-4c23b600"
  12. Cache-Control: max-age=0

———————————————————-
以下がレスポンス内容(2回目のアクセス)
———————————————————-

CODE:

  1. HTTP/1.x 304 Not Modified
  2. Date: Mon, 07 May 2007 11:51:27 GMT
  3. Server: Apache/2.2.4 (Unix)
  4. Connection: close
  5. Etag: “4c602bd-2c-4c23b600″

ここで注目は
1)初回アクセスのレスポンス中の

CODE:

  1. Etag: “4c602bd-2c-4c23b600″

2)2回目アクセスのリクエスト中の

CODE:

  1. If-None-Match: “4c602bd-2c-4c23b600″

3)2回目アクセスのレスポンス中の

CODE:

  1. HTTP/1.x 304 Not Modified
  2. Etag: “4c602bd-2c-4c23b600″

です。

このEtagとはエンティティTAGのことで、apacheのマニュアルからから引用すると、

FileETag ディレクティブは ドキュメントがファイルに基づいたものであるときに、 ETag (エンティティタグ) 応答ヘッダフィールドを作成するときに使用する ファイルの属性を設定します。 (ETag の値はネットワークの帯域を節約するための キャッシュの管理で使われます。) Apache 1.3.22 以前では、ETag の値は 常にファイルの inode, サイズ、最終修正時刻 (mtime) から作成 されていました。FileETag ディレクティブにより、これらのどれを使うかを 選ぶことができます。

となります。

つまり、

  1. 静的コンテンツ(html、画像、css、javascript等)をapacheに要求するとapacheはinode, サイズ、最終修正時刻 (mtime) からEtagの値を算出してレスポンスに含めます。
  2. ブラウザはあるページにアクセスしようとした時に、それが自分のキャッシュにあると、If-None-Matchヘッダーに以前のEtagの値を付与してサーバーに送信します。
  3. apacheはリクエストを受け取って、そのEtagの値が改めて算出し直したEtagの値と等しければ「304 Not Modified」を返し、異なっていれば、レスポンスコード200と実際のコンテンツを返却します。

※ここではIf-Modified-Sinceのことは省略しています。

WWWサーバーが一台であれば、コンテンツファイルは1個しかないので、「ファイルの実際の更新」=「Etagの変更というか変化」になるので問題ないのですが、負荷分散ルーター配下にWWWサーバーが複数台あって個別にファイルを配置している場合、まったく同じ内容のファイルを置いても、どうしてもinodeが異なるゆえに異なるEtagになってしまいます。

ファイルが変更されたと認識されて、 「304 Not Modified」ではなく、レスポンスコード200と実際のコンテンツが返却されてしまいます。

例えば、負荷分散ルーターの振り分け論理がラウンドロビンだったりすると、アクセスするたびに、別のEtagになってしまい、必要以上の負荷をネットワークに与えることになります。

これを解決するために

Etagの生成をサイズ、最終修正時刻 (mtime) からのみに指定

CODE:

  1. FileETag MTime Size

とか

Etag自体を返却しない(この場合If-None-Matchヘッダーも送信されなくなる)

CODE:

  1. FileETag None

等の対応策をとります。

さらに詳しい話はまた次回に。

 

関連会社インターオフィスのブログ記事を転載しています。

Apacheチューニング: ロギングを高速化する

という記事に

CODE:

  1. BufferedLogs On

によるアクセスログのバッファリングの記事がありました。試したことのないディレクティブだったので、実験してみました。

環境は

  • CentOS5
  • Apache/2.2.4

で、貧弱なサーバーです。

チェック方法

CODE:

  1. /usr/local/apache2/bin/ab -n 10000 -c 100 http://stockholm/

1回実行後に2回さらに実行して、後半2回の平均を取る

設定1)バッファリングなしで、cronlogなし

※CustomLog logs/access_log combined

CODE:

  1. Server Software:        Apache/2.2.4
  2. Server Hostname:        stockholm
  3. Server Port:            80
  4.  
  5. Document Path:          /
  6. Document Length:        44 bytes
  7.  
  8. Concurrency Level:      100
  9. Time taken for tests:   11.973132 seconds
  10. Complete requests:      10000
  11. Failed requests:        0
  12. Write errors:           0
  13. Total transferred:      2909570 bytes
  14. HTML transferred:       441452 bytes
  15. Requests per second:    835.20 [#/sec] (mean)
  16. Time per request:       119.731 [ms] (mean)
  17. Time per request:       1.197 [ms] (mean, across all concurrent requests)
  18. Transfer rate:          237.28 [Kbytes/sec] received
  19.  
  20. Connection Times (ms)
  21. min  mean[+/-sd] median   max
  22. Connect:        0   12  11.3     10      74
  23. Processing:    20  105  16.5    105     482
  24. Waiting:        9   73  26.5     74     461
  25. Total:         23  118  19.6    117     493
  26.  
  27. Percentage of the requests served within a certain time (ms)
  28. 50%    117
  29. 66%    122
  30. 75%    126
  31. 80%    128
  32. 90%    137
  33. 95%    145
  34. 98%    155
  35. 99%    161
  36. 100%    493 (longest request)
  37.  
  38. Server Software:        Apache/2.2.4
  39. Server Hostname:        stockholm
  40. Server Port:            80
  41.  
  42. Document Path:          /
  43. Document Length:        44 bytes
  44.  
  45. Concurrency Level:      100
  46. Time taken for tests:   12.232209 seconds
  47. Complete requests:      10000
  48. Failed requests:        0
  49. Write errors:           0
  50. Total transferred:      2900000 bytes
  51. HTML transferred:       440000 bytes
  52. Requests per second:    817.51 [#/sec] (mean)
  53. Time per request:       122.322 [ms] (mean)
  54. Time per request:       1.223 [ms] (mean, across all concurrent requests)
  55. Transfer rate:          231.52 [Kbytes/sec] received
  56.  
  57. Connection Times (ms)
  58. min  mean[+/-sd] median   max
  59. Connect:        0    0   2.1      0      28
  60. Processing:    15  120 237.3    115   12182
  61. Waiting:       14  120 237.3    115   12181
  62. Total:         15  120 237.4    115   12182
  63.  
  64. Percentage of the requests served within a certain time (ms)
  65. 50%    115
  66. 66%    115
  67. 75%    116
  68. 80%    116
  69. 90%    120
  70. 95%    128
  71. 98%    142
  72. 99%    150
  73. 10012182 (longest request)

Requests per second: 826.355 (平均)

設定2)バッファリングなしで、cronlogあり

※CustomLog “|/usr/local/sbin/cronolog /usr/local/apache2/logs/access_log.%Y-%m-%d” combined

CODE:

  1. Server Software:        Apache/2.2.4
  2. Server Hostname:        stockholm
  3. Server Port:            80
  4.  
  5. Document Path:          /
  6. Document Length:        44 bytes
  7.  
  8. Concurrency Level:      100
  9. Time taken for tests:   12.177233 seconds
  10. Complete requests:      10000
  11. Failed requests:        0
  12. Write errors:           0
  13. Total transferred:      2900000 bytes
  14. HTML transferred:       440000 bytes
  15. Requests per second:    821.20 [#/sec] (mean)
  16. Time per request:       121.772 [ms] (mean)
  17. Time per request:       1.218 [ms] (mean, across all concurrent requests)
  18. Transfer rate:          232.57 [Kbytes/sec] received
  19.  
  20. Connection Times (ms)
  21. min  mean[+/-sd] median   max
  22. Connect:        0    0   1.7      0      29
  23. Processing:    18  120  80.6    113    3127
  24. Waiting:       17  117  61.1    112    2298
  25. Total:         18  120  80.6    113    3127
  26.  
  27. Percentage of the requests served within a certain time (ms)
  28. 50%    113
  29. 66%    114
  30. 75%    115
  31. 80%    115
  32. 90%    116
  33. 95%    118
  34. 98%    149
  35. 99%    558
  36. 100%   3127 (longest request)
  37.  
  38. Server Software:        Apache/2.2.4
  39. Server Hostname:        stockholm
  40. Server Port:            80
  41.  
  42. Document Path:          /
  43. Document Length:        44 bytes
  44.  
  45. Concurrency Level:      100
  46. Time taken for tests:   12.72722 seconds
  47. Complete requests:      10000
  48. Failed requests:        0
  49. Write errors:           0
  50. Total transferred:      2900000 bytes
  51. HTML transferred:       440000 bytes
  52. Requests per second:    828.31 [#/sec] (mean)
  53. Time per request:       120.727 [ms] (mean)
  54. Time per request:       1.207 [ms] (mean, across all concurrent requests)
  55. Transfer rate:          234.58 [Kbytes/sec] received
  56.  
  57. Connection Times (ms)
  58. min  mean[+/-sd] median   max
  59. Connect:        0    0   1.6      0      28
  60. Processing:     1  119 1051.5      3   11423
  61. Waiting:        0   17 131.2      3    8634
  62. Total:          1  119 1051.5      3   11423
  63.  
  64. Percentage of the requests served within a certain time (ms)
  65. 50%      3
  66. 66%      4
  67. 75%      6
  68. 80%      7
  69. 90%      8
  70. 95%    113
  71. 98%    654
  72. 99%   1101
  73. 10011423 (longest request)

Requests per second: 824.755 (平均)

設定3)バッファリングありで、cronlogあり

※CustomLog “|/usr/local/sbin/cronolog /usr/local/apache2/logs/access_log.%Y-%m-%d” combined

CODE:

  1. Server Software:        Apache/2.2.4
  2. Server Hostname:        stockholm
  3. Server Port:            80
  4.  
  5. Document Path:          /
  6. Document Length:        44 bytes
  7.  
  8. Concurrency Level:      100
  9. Time taken for tests:   11.347721 seconds
  10. Complete requests:      10000
  11. Failed requests:        0
  12. Write errors:           0
  13. Total transferred:      2909280 bytes
  14. HTML transferred:       441408 bytes
  15. Requests per second:    881.23 [#/sec] (mean)
  16. Time per request:       113.477 [ms] (mean)
  17. Time per request:       1.135 [ms] (mean, across all concurrent requests)
  18. Transfer rate:          250.36 [Kbytes/sec] received
  19.  
  20. Connection Times (ms)
  21. min  mean[+/-sd] median   max
  22. Connect:        0   11  10.7      8      70
  23. Processing:    18  100  16.8    100     457
  24. Waiting:        9   71  26.0     79     406
  25. Total:         18  111  20.6    110     476
  26.  
  27. Percentage of the requests served within a certain time (ms)
  28. 50%    110
  29. 66%    115
  30. 75%    119
  31. 80%    122
  32. 90%    132
  33. 95%    141
  34. 98%    151
  35. 99%    157
  36. 100%    476 (longest request)
  37.  
  38. Server Software:        Apache/2.2.4
  39. Server Hostname:        stockholm
  40. Server Port:            80
  41.  
  42. Document Path:          /
  43. Document Length:        44 bytes
  44.  
  45. Concurrency Level:      100
  46. Time taken for tests:   11.505531 seconds
  47. Complete requests:      10000
  48. Failed requests:        0
  49. Write errors:           0
  50. Total transferred:      2900000 bytes
  51. HTML transferred:       440000 bytes
  52. Requests per second:    869.15 [#/sec] (mean)
  53. Time per request:       115.055 [ms] (mean)
  54. Time per request:       1.151 [ms] (mean, across all concurrent requests)
  55. Transfer rate:          246.14 [Kbytes/sec] received
  56.  
  57. Connection Times (ms)
  58. min  mean[+/-sd] median   max
  59. Connect:        0   35  27.7     32     107
  60. Processing:    26   78  17.8     75     131
  61. Waiting:        1   40  24.2     37     110
  62. Total:         27  113  16.0    114     212
  63.  
  64. Percentage of the requests served within a certain time (ms)
  65. 50%    114
  66. 66%    120
  67. 75%    124
  68. 80%    127
  69. 90%    134
  70. 95%    140
  71. 98%    144
  72. 99%    146

Requests per second: 875.19 (平均)

やはり5-6%はあきらかに効果があるようです。

静的コンテンツ用のサーバーの場合は使える設定だと思います。

ちなみに

設定4)アクセスログの出力自体を停止

の場合は

Requests per second: 902.15 (平均)

なのでバッファリングした時と比べると1%くらいしか性能向上しませんでした。

 

関連会社インターオフィスのブログ記事を転載しています。

先日からの続きです。

以下は先日の記事からの引用です
==================================================

2種類のリクエストが混在すること

また、我々が開発するような動的ページを中心としてサイトの場合、一回の(一連の)リクエストは通常

  • プログラムによる動的なhtmlの生成

数百ミリ秒~数秒を要する
通常は一連のリクエスト中の最初の一回

  • 上記のhtmlから参照される静的コンテンツ(css,javascript,画像等)

数ミリか数10ミリ秒以下の場合が多い
リクエスト数が多い(数10個以上)

の2種類から成り立ちます。
==================================================
というところからでした。

動的なページを含むサイトは非常に異なる性質の要求を同時に処理している

プログラムによる動的なhtmlの生成

一回の(一連の)リクエストの中で通常一件しか含まれません。その処理が済んだら、ユーザは暫くの間、その内容を読んでいるので、そもそもkeep-alive設定は必要ないわけです。

上記のhtmlから参照される静的コンテンツ(css,javascript,画像等)

こちらは上記とは逆に非常にkeep-aliveが有効なケースです。

この2種類の処理を同じ設定で対応するというところに矛盾があるわけです。

よって、以下の方法が一番良いというか、是非採用すべき方法だと思います。

  • 動的ページ用WWWサーバーと静的ページ用WWWサーバーは分離
    • もし、両者を分離する余裕がない場合(ここではある程度以上の規模サイトの話をしているので、そもそも余裕はあると思いますが)、バーチャルホストとして分離する等の方法を採用出来ます。
  • 動的ページ用WWWサーバーはkeep-aliveをOFF
  • 静的ページ用WWWサーバーはkeep-aliveをON
    • 更に、MaxKeepAliveRequests は一回の(一連の)リクエストあたりの平均的な要求ファイル数より少し(多くではなく)少なく設定
    • KeepAliveTimeoutは1-2秒程度の非常に短い値を設定
    • これはtcpコネクションが無駄に掴まれてしまうことをなによりも恐れるためです

最後にkeep-aliveに関する話題を挙げておきます。

 

関連会社インターオフィスのブログ記事を転載しています。

keep-aliveについての簡単な解説

1つのWebページをブラウザが表示するにあたっては、メインのhtmlファイルに加えて、そのhtml上に記述された画像、css、javascript等のファイルをサーバーからダウンロードする必要があります。画像が多いページの場合、1個のhtmlに対して100も200も画像をダウンロードする必要があります。もしkeep-aliveを使用しないとそのすべてのリクエストについて、別々のTCP接続の開始・切断を行うことになってしまいます。keep-aliveを利用すると、通常一つのブラウザからのリクエストを一つのTCP接続で処理することができます。

TCP/IPのコネクションについては、以下のサイトにわかりやすく解説されています。

Apacheで、KeepAliveを有効とするか否かを決定するのが「KeepAlive」ディレクティブです。 KeepAliveの設定は「MaxKeepAliveRequests」ディレクティブと「KeepAliveTimeout」ディレクティブで指定します。

  • MaxKeepAliveRequests
    • 接続してから切断するまでに受け付けるリクエストの数
  • KeepAliveTimeout
    • 接続しているセッションからのリクエストが来なくなってから切断するまでの待ち時間

KeepAliveはそもそもONにすべきか、OFFにすべきか

通常はONにすべきというのがほとんどの意見だと思います。

でも「sanonosaシステム管理コラム集」のような意見もあるようです。

ほんとうのところはどうなんでしょうか?

上記の記事ではIISのようですし、設定値が記述されていないので なんとも言えません。

  • KeepAliveの MaxKeepAliveRequestsを必要以上に大きくしすぎること
  • KeepAliveの KeepAliveTimeoutを必要以上に大きくしすぎること

はTCPコネクションを無駄遣いしてしまうことは間違いありません。

そもそもKeepAliveをONにすることはTCPコネクションを無駄遣いしないようにしているのですから本末転倒ということになってしまいます。

ブラウザからの一連の接続が終了したら出来る限り素早くTCPコネクションを切断することが望ましいわけです。しかし、MaxKeepAliveRequestsやKeepAliveTimeoutの設定は固定値であり、接続毎に動的に変更することは出来ません。

※「リクエスト間隔を考慮したウェブサーバのkeep-alive 時間の自動設定」という論文が日本ソフトウェア科学会第22 回大会(2005 年度)論文集に記載されています。興味のある方は読んでみて下さい。

対象のサイトに対するリクエストの平均的な要求値を算出して、

  • MaxKeepAliveRequestsは、一回の(一連の)リクエストあたりの要求ファイル数より少し多く設定する
  • KeepAliveTimeoutは、一回の(一連の)リクエストあたり空き時間より少し長く設定する

のがやはり正解かなと思います。

例えばユーザがインターネットに接続する帯域が細いと一回の(一連の)リクエストあたり空き時間は長くなります。

実際のサイトの計測は、Web DeveloperのNETオプションを利用すれば簡単に算出できます。
※これは一回あたりの実測ができるだけで、平均となるとアクセスログからなんらかのスクリプトを作成して算出する必要がありますが。

仮に、一回の(一連の)リクエストがファイル数で50個、全部で1秒以内で終了するとします。

にも関わらず、

  • MaxKeepAliveRequests 100
  • KeepAliveTimeout 15

とされていたとすると、そのTCPコネクションは15秒の間、無駄になってしまう訳です。

2種類のリクエストが混在すること

我々が開発するような動的ページを中心としてサイトの場合、一回の(一連の)リクエストは通常

  • プログラムによる動的なhtmlの生成

数百ミリ秒~数秒を要する
通常は一連のリクエスト中の最初の一回

  • 上記のhtmlから参照される静的コンテンツ(css,javascript,画像等)

数ミリか数10ミリ秒以下の場合が多い
リクエスト数が多い(数10個以上)

の2種類から成り立ちます。

次回に続きます

 

関連会社インターオフィスのブログ記事を転載しています。