今回は、HTTPのパイプラインの話。

「RFC2616の同時接続数の規定」@水無月ばけらのえび日記
HTTPの同時接続数はどうあるべきか? (slashdot.jp) 」というお話。誰も原文を引用していないのが悲しかったので、引いておきます。
スラッシュドット ジャパン | HTTPの同時接続数はどうあるべきか?-taka2さんのコメント
それなら、「同時接続」しなくても、結果が返ってくる前に次のリクエストを送出して「リクエスト送信」と「結果受信」を並行して行えるようになれば、スループットの向上は見込める。 それがパイプライン化 [mozilla-japan.org]で、同時接続するよりも効率が良い。

パイプライン化の前に、HTTPで何が行われているのかを、実際に見てみよう。telnetコマンドがある環境であれば、以下のように手で実行することが出来る。ここでは簡潔のためにHEADリクエストを使った。

% telnet b.hatena.ne.jp http
Trying 61.196.246.69...
Connected to b.hatena.ne.jp.
Escape character is '^]'.
HEAD / HTTP/1.1
Host: b.hatena.ne.jp

HTTP/1.1 200 OK
Date: Thu, 21 Dec 2006 07:56:39 GMT
Server: Apache
X-Framework: Hatena/2.0
Content-Type: text/html; charset=utf-8
Vary: Accept-Encoding

HEAD /hotentry HTTP/1.1
Host: b.hatena.ne.jp

HTTP/1.1 200 OK
Date: Thu, 21 Dec 2006 07:56:39 GMT
Server: Apache
X-Framework: Hatena/2.0
Content-Type: text/html; charset=utf-8
Vary: Accept-Encoding

HEAD /news HTTP/1.1
Host: b.hatena.ne.jp

HTTP/1.1 200 OK
Date: Thu, 21 Dec 2006 07:56:39 GMT
Server: Apache
X-Framework: Hatena/2.0
Content-Type: text/html; charset=utf-8
Vary: Accept-Encoding

HEAD /entrylist?sort=hot HTTP/1.1
Host: b.hatena.ne.jp
Connection: close

HTTP/1.1 200 OK
Date: Thu, 21 Dec 2006 07:56:39 GMT
Server: Apache
X-Framework: Hatena/2.0
Content-Type: text/html; charset=utf-8
Vary: Accept-Encoding
Connection: close

Connection closed by foreign host.

クライアント(あなた)リクエスト(request)と、サーバー(ここではb.hatena.ne.jp)のリスポンス(response)が交互に繰り返されている様子がわかるだろう。

パイプラインというのは、要はこういうことである。

HEAD / HTTP/1.1
Host: b.hatena.ne.jp

HEAD /hotentry HTTP/1.1
Host: b.hatena.ne.jp

HEAD /news HTTP/1.1
Host: b.hatena.ne.jp

HEAD /entrylist?sort=hot HTTP/1.1
Host: b.hatena.ne.jp
Connection: close

HTTP/1.1 200 OK
Date: Thu, 21 Dec 2006 08:09:02 GMT
Server: Apache
X-Framework: Hatena/2.0
Content-Type: text/html; charset=utf-8
Vary: Accept-Encoding

HTTP/1.1 200 OK
Date: Thu, 21 Dec 2006 08:09:02 GMT
Server: Apache
X-Framework: Hatena/2.0
Content-Type: text/html; charset=utf-8
Vary: Accept-Encoding

HTTP/1.1 200 OK
Date: Thu, 21 Dec 2006 08:09:02 GMT
Server: Apache
X-Framework: Hatena/2.0
Content-Type: text/html; charset=utf-8
Vary: Accept-Encoding

HTTP/1.1 200 OK
Date: Thu, 21 Dec 2006 08:09:02 GMT
Server: Apache
X-Framework: Hatena/2.0
Content-Type: text/html; charset=utf-8
Vary: Accept-Encoding
Connection: close

要は、複数のリクエストをまとめて出すと、複数のリスポンスがまとめて返ってくるということである。まとめて処理すれば速くなるというのは、Webに限らず世の中の鉄則である。HTTP/1.1では、まず接続(connection)をまとめることで一回の接続で受け取れるリクエストを増やし、そしてさらにパイプラインで複数のリクエストをまとめて処理できるようにしたというわけだ。

しかし、接続をまとめる、すなわちpersistent connectionの方は事実上どのWebサイトも対応しているのだが、リクエストのパイプラインの方は、一部Webサイトがまだ未対応のようなのだ。

たとえば「リクナビNEXT/リクルートの転職サイト」。ここではパイプラインをオンにすると、画像が全く取れなくなってしまう。Firefoxをお持ちであれば、about:configとアドレスバーに打ってから、filter:にpipeと打ち込んで現れるnetwork.http.pipeliningをダブルクリックすることで設定を変更できるので試してほしい。なお、デフォルトではfalseになっている。

一見複数のリクエストをまとめて処理するのは簡単そうだが、クライアントから見て同一ホストのWebサイトでも、裏ではreverse proxyなどを用いて複数のサーバーから構成されているのが高負荷のサイトでは常識となっている。このような場合は、フロントエンド、すなわちクライアントと直接接続しているサーバー(たいていreverse proxy)がリクエストをまとめなければならないが、実際にコンテンツを持っているサーバーから見れば、このリクエストはまとまって見えるとは限らない。

Firefoxがパイプラインをデフォルトではoffにしているのは、こういった事情があるのだと思われる。

とはいえ、私がよく見るサイトでは、パイプラインをonにしておかしくなるのは、リクナビNEXTぐらいだった。パイプラインのご利益は、むしろサーバーの方にこそあるので、もっと普及してほしい技術なのだが。

ちなみに、Apacheなど通常のWebサーバー単位では、すでにこの技術に対応している。設定変更などは不要である。むしろ問題はリクナビNEXTなど、高負荷で複数のサーバーから構成されているWebサイトが全体としてこれをサポートしているかだろう。

Dan the Man with Too Many HTTP Requests to Process