アルファサード株式会社 代表取締役 野田 純生のブログ


503を返すとか返さないとか言う前に。


公開日 : 2007-05-03 01:24:02


ここら辺に呼応して。

Googleのクローラーがどうかは調べていないけれど。

負荷云々の前に、まずきちんとHTTP_HEADERで攻防をしてから。

ステータスコードとその意味

200OKリクエストは正常に処理された!
301Moved Permanentlyページは移動したよ!
302Found今のところページは移動してるよ!
304Not Modifiedリクエストされたページは更新されてないからキャッシュを使いな!
401Unauthorized認証されてない!
402Payment Required金払え!
403Forbidden許可されないもんね!
404File Not Foundごめん, 見つかんないよ!
500Internal Server Errorごめん,俺が下手なせいで(Joke!)エラーなっちまったよ!
503Service Unavailableごめん,今はだめだ!

主立ったところはこんな感じ。

例えば(多分あまり意識していないであろう)Basic認証におけるHTTP_HEADERのやりとりは、


HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="パスワード入れてね!"
(CRLF+CRLF)

というレスポンスをサーバが返し、クライアントは(ID,Passwdを求めるウィンドウを出してから)再度リクエストを送り返す。


GET /basic_auth.html HTTP/1.1
Authorization: Basic (base64エンコードされたID,Passwd情報)...

つまり、これもHTTP_Headerのやりとりなのだ。もちろんCookieだってそうだ。

このしくみを理解していればBasic認証を自前で実装することもできる。ID,PasswordをDBと照合してアクセスを許可することも可能。但し、Apache+Perl CGIの環境ではこの部分のHEADER情報が(おそらく)セキュリティの面(だったと思う)で環境変数から受け取ることができない(少なくとも昔はできなかった)ので無理。PHPであれば


$_SERVER['PHP_AUTH_USER']
$_SERVER['PHP_AUTH_PW']

とかで何でもできる。善し悪しは置いておいて。

また、バーチャルホストだって普通に使っているかもしれないが、


Host: junnama.alfasado.net

ってなヘッダー情報を送ってくるからApacheが適切に解釈できるわけで、ブラウザがHostヘッダを送ってこなければApacheはデフォルトサイトのデータを返すのだ(大昔はブラウザはこんな情報送ってこなかったからバーチャルホストってのもなかった)。

本題? に戻る。負荷軽減のポイントは

  • HEADリクエストへの対応
  • ステータス304を適切に返す

の2点か。

まともな? ロボットならまずは※HEADリクエストを送ってHTTP_HEADERをチェックするだろう。

※追記:
良く考えたら後述のConditionalGETが適切に機能するならばHEADリクエストである必要はないなぁ。


HEAD /index.html HTTP/1.1
If-Modified-Since: Mar, 3 Thu 2007 01:00:00 GMT 
if_none_match: 23ab7f6be333b3df07b4df3de61a92b9

ページが更新されていないならば、HTTP_HEAD情報のみを返せば良い。
まともな? クローラーならこれで次のリクエストは送ってこない(と思う)。


HTTP/1.1 200 OK
Last-Modified: Mar, 3 Thu 2007 01:00:00 GMT 
Content-type: text/html 
Content-length: 950
Etag: 23ab7f6be333b3df07b4df3de61a92b9

あるいは(後述するが)


HTTP/1.1 304 Not Modified 
Last-Modified: Mar, 3 Thu 2007 01:00:00 GMT 
Content-type: text/html 
Content-length: 950
Etag: 23ab7f6be333b3df07b4df3de61a92b9

さて、HEADリクエストで求める答えが得られなかったクライアントはConditional GET(条件付きGET)でリクエストを送ってくる(と考える)。


GET /index.html HTTP/1.1
If-Modified-Since: Mar, 3 Thu 2007 01:00:00 GMT 
if_none_match: 23ab7f6be333b3df07b4df3de61a92b9

サーバー側の処理は

If-Modified-Since ヘッダで送られて来たタイムスタンプよりも送り返すべきデータの更新日時が新しい場合、あるいは以前送り返したEtagと値が変わっていた場合のみ


HTTP/1.1 200 OK
...HTTP_HEAD情報+CRLF+CRLF+コンテンツの内容

を送り返せば良い。

もしも更新されていなかったなら、ステータス304+返すべきHTTP_HEADER情報のみを送り返せば良い。そうすれば(それがブラウザであるならば)ブラウザのキャッシュが表示される。


HTTP/1.1 304 Not Modified 
Last-Modified: Mar, 3 Thu 2007 01:00:00 GMT 
Content-type: text/html 
Content-length: 950
Etag: 23ab7f6be333b3df07b4df3de61a92b9

まともなクローラーであればこういう振る舞いをすべきだと思う(繰り返すがGoogleのクローラーがどうかは調べていないけれど)。

少なくとも503を返す前にやるべきことをやってから考えるべきではないだろうか?

カテゴリ


このブログを書いている人
野田純生の写真
野田 純生 (のだ すみお)

大阪府出身。ウェブアクセシビリティエバンジェリスト。 アルファサード株式会社の創業者であり、現役のプログラマ。経営理念は「テクノロジーによって顧客とパートナーに寄り添い、ウェブを良くする」。 プロフィール詳細へ