2007年1月15日

HTTP/1.1 の「条件付きGET」を利用して PHP ファイルアクセスによるサーバ負荷を削減する

January 15,2007 12:50 AM
Tag:[, ]
Permalink

Movable Type 等で PHP 化PHP モジュール化によりファイルの拡張子を .php で運用している場合の、サーバ負荷・ネットワークトラフィックを削減する方法をご紹介します。

1.問題点

HTML ファイルの拡張子を .php にしている場合、HTTP/1.1 で規定されている「条件付き GET」が行われません。ブラウザはこのようなサイトに対し無条件に GET を行ってしまうため、サーバ負荷やネットワークトラフィック増加の要因の一つになっています。

2.条件付き GET とは

「条件つき GET」は RFC2616(HTTP/1.1) 9.3 で定義されています。以下和訳を引用します。

RFC2068 9.3 GET(RFC2616は更新版)

GET メソッドは Request-URI で識別される (エンティティの形式においての)情報ならなんでも回収する事を意味する。もし Request-URI が data-producing プロセスを参照しているなら、それはリソースのエンティティとして返されるであろう作られたデータである。これはもしそのテキストがプロセスの出力で生じるのでなければ、プロセスのソーステキストではない。

もし If-Modified-Since, If-Unmodified-Since, If-Match, If-None-Matchや If-Range ヘッダフィールドをリクエストメッセージが含んでいるなら、GET メソッドのセマンティクスは "条件付き GET" に変わる。条件付き GETメソッドはエンティティがその条件付きヘッダフィールドによって表される状況の元でのみ転送される事をリクエストする。条件付き GET メソッドはキャッシュされるエンティティに複数のリクエストを必要としたりクライアントによってすでに保持されたデータを転送する事なしに再び新しくされる事を可能にする事により、ネットワークの不必要な使用を減少する目的を持つ。

要するに、「前回アクセス以降からページの更新が行われていない場合はサーバから改めてデータを送信しない仕組みがある」というようなことが書かれています。

3.条件付き GET の振る舞い

2項の説明だけでは良く分からないので、Firefox 2.0 の Live HTTP Headers で、当サイトのトップページにアクセスした時の HTTP ヘッダを例に、具体的な動作を説明します。

3.1 条件付きGETなしの場合

リスト3.1.1 リクエストヘッダ(条件付きGETなし)

GET / HTTP/1.1
Host: www.koikikukan.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;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
Keep-Alive: 300
Connection: keep-alive
Cookie: 略
Cache-Control: max-age=0

リスト3.1.2 レスポンスヘッダ(条件付きGETなし)

HTTP/1.x 200 OK
Date: Sun, 14 Jan 2007 14:21:19 GMT
Server: Apache/1.3.37 (Unix)
X-Powered-By: PHP/4.4.4
Keep-Alive: timeout=3, max=8
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8

条件付き GET が行われていない状態では、リクエスト・レスポンスは上記のようなヘッダになります。この状態ではアクセスする度に 200 OK を返却、つまりページが更新・未更新に関わらず、サーバは常にデータ(リクエストボディ)を返却します。

3.2 条件付きGETあり(ブラウザで初回アクセス時)

リスト3.2.1 リクエストヘッダ(条件付きGETあり:初回アクセス)

GET / HTTP/1.1
Host: www.koikikukan.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;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
Keep-Alive: 300
Connection: keep-alive
Cookie: 略
Cache-Control: max-age=0

リスト3.2.2 レスポンスヘッダ(条件付きGETあり:初回アクセス)

HTTP/1.x 200 OK
Date: Sun, 14 Jan 2007 14:22:45 GMT
Server: Apache/1.3.37 (Unix)
Etag: "cc8929434ffafd940e5956b71a0be1f5"
X-Powered-By: PHP/4.4.4
Last-Modified: Sun, 14 Jan 2007 14:22:32 GMT
Keep-Alive: timeout=3, max=8
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8

条件付き GET(というか今回のカスタマイズ)が行われている場合、HTTP レスポンスに Etag / Last-Modified フィールドを付与して返却します。Etag は更新時刻などから生成されたハッシュ値、Last-Modified は更新時刻です。
リクエストを送信したブラウザはこの情報をページ単位に保持します(200 OK なのでこの時はリクエストボディも同時に返却します)。

3.3 条件付き GET あり(2回目以降のアクセス)

リスト3.3.1 リクエストヘッダ(条件付きGETあり:2回目以降)

GET / HTTP/1.1
Host: www.koikikukan.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;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
Keep-Alive: 300
Connection: keep-alive
Cookie: 略
If-Modified-Since: Sun, 14 Jan 2007 14:22:32 GMT
If-None-Match: "cc8929434ffafd940e5956b71a0be1f5"
Cache-Control: max-age=0

リスト3.3.2 レスポンスヘッダ(条件付きGETあり:2回目以降)

HTTP/1.x 304 OK
Date: Sun, 14 Jan 2007 14:23:07 GMT
Server: Apache/1.3.37 (Unix)
Etag: "cc8929434ffafd940e5956b71a0be1f5"
X-Powered-By: PHP/4.4.4
Last-Modified: Sun, 14 Jan 2007 14:22:32 GMT
Keep-Alive: timeout=3, max=8
Connection: Keep-Alive
Content-Type: text/html; charset=utf-8

2回目以降のアクセスでは、前回アクセスしたレスポンスヘッダに含まれる Etag / Last-Modified フィールドの値を、今回のリクエストヘッダの If-Modified-Since / If-None-Match フィールドに設定して送信します。

リクエストを受信した HTTP/1.1 サーバでは、サーバ自身が保持するページ情報と比較して、ページの更新・未更新を判断します(この辺りは推測で書いてます。間違っていたらすいません)。

「304 Not Modified」はページが更新されていない時に返却するレスポンスコードです(304 にレスポンスボディは含まない仕様です)。304 レスポンスを受信したブラウザはサーバからデータをダウンロードせず、ローカルキャッシュを表示します。

つまり、PHP ファイルで「条件付き GET」を有効にし、304 Not Modified を返却できるようにすれば、結果的にサーバ・ネットワークの負荷を削減することができる、という訳です。

4.対処方法

対処方法は下記のサイトで紹介されています。当サイトでも利用させて頂きました。ありがとうございました。

Ogawa::Memoranda「条件付きGET」のススメ

上記は Movable Type 利用で

  • スタティックページ生成
  • ページを PHP モジュール化
  • サイドバーの部品を PHP を利用したインクルード

を前提にされています。

ダイナミックパブリッシングを利用している場合はデフォルト機能として、条件付き GET が利用できます(関連記事「Movable Type の再構築を不要にする「ダイナミック・パブリッシング」(その2:設定方法)」)。

5.その他のページについて

該当ページに含まれる外部ファイルは全て HTTP によって取得されますが、

  • CSS(.css)
  • JavaScript(.js)
  • 画像(.jpg / .gif / .png 等)

は HTTP/1.1 サーバで 304 を返却しています。例えば CSS を修正すると、スタイルシートファイルだけが新たに読み込まれます。この仕組みのお陰で、当サイトのように外部ファイルを大量に読み込んでいるページでも、タイムラグの少ない表示ができるという訳です。

6.参考

Comments [13] | Trackbacks [6]
Now loading...
ギターに入った猫
掲載広告募集
Styles
Font Size
Default
For defective color vision
Gray Scale
RGB Color
Search this site

このブログをメールで購読する by:FeedBurner

AMN
Categories
Monthly Archives
2020年
2019年
2018年
2017年
2016年
2015年
2014年
2013年
2012年
2011年
2010年
2009年
2008年
2007年
2006年
2005年
2004年
2003年
BlogPeople
Syndicate this site
FeedBurner(RSS1.0/RSS2.0/Atom)
Counter
これまでのアクセス
Powered by
Movable Type 6.0.3