質問: HTTP1.1のサーバーサイドの実装をしています。 パイプライン処理はGETやHEADが連続でくるということですが、パイプライン開始のトリガーが(私が調べた限り)ないため、最初のGETを受け取った後に次に来るGET(or HEAD)の対処が難しいと考えています。 GET /A.html\r\n \r\n GET /B.html\r\n \r\n GET /C.html\r\n \r\n 上記の場合、 最初に「GET /A.html」を受け取っているので、サーバーはそのコンテンツを返すべきですが、 もしこれが上記のようにパイプラインなら、二つ目の「GET B.html」が来る可能性があるのでrecv()で待機に入る必要があります。ですが、このrecv()はいつまでやるべきでしょうか? タイムアウトするまでだとしても、1秒とか待機していてはロスですし、短すぎてもまだクライアントサイドがデータ送信中の可能性があります。もしくは二つ目のGETが来ない可能性もあります。 あと、そもそものお話ですが、HTTP1.1のパイプラインは一般的によく使われているのでしょうか? 最近のブラウザとサーバーでは実装されているようですが、 ブラウザはデフォルトでパイプラインでコンテンツを取得しにいくのか、滅多にこのような取得方法は行われないのか、ご存じの方がいらしたら教えていただけると助かります。 (最初の1枚目のコンテンツはリクエストとレスポンスが1対1で、その中身をパイプラインで取得しにいく、という感じだと想像しています)
回答: HTTP/1.1 Pipelining は、最初にリクエストを複数受け取り、受け取った順番(FIFO)でレスポンスを送り返すだけの機能です。実装するだけなら簡単かもしれません。これは確か、サーバサイドコンテンツ生成処理の並列化が目的の機能だったと思います。 きちんと調べきってはいないのですが、最近の状況を知らなかったので、この機会に少し調べてみました。 ■ HTTP Pipelining: どのタイミングで切断するか W3C の Hypertext Transfer Protocol -- HTTP/1.1 仕様に以下のような言及がありました。 > > **8.1.4 Practical Considerations** > > > Servers will usually have some time-out value beyond which they will no longer maintain an inactive connection. Proxy servers might make this a higher value since it is likely that the client will be making more connections through the same server. The use of persistent connections places no requirements on the length (or existence) of this time-out for either the client or the server. > > ... > > A client, server, or proxy MAY close the transport connection at any time. For example, a client might have started to send a new request at the same time that the server has decided to close the "idle" connection. From the server's point of view, the connection is being closed while it was idle, but from the client's point of view, a request is in progress. > > ... > > Servers SHOULD always respond to at least one request per connection, if at all possible. Servers SHOULD NOT close a connection in the middle of transmitting a response, unless a network or client failure is suspected. > > ... > > > 抜粋すると「サーバはいつ切断してもよいが、レスポンスを返している途中で接続を切るべきではない」「クライアントはサーバに接続を切られた場合に常に備えるべきだ」ということらしい。ここから、、 * サーバは、クライアントから受け取った未解決のリクエストを無視して切断して良い * サーバによる切断のタイミングは、レスポンス送信中より、送り切った時点が良い と読めます。 ■ HTTP Pipelining: 接続がタイムアウトをするべき時間 サーバ用の具体的なタイムアウト値は調べきりませんでした。決まっていないと思います。極端な話、最後のレスポンスを送り切ったら、即切りしてよいのではないでしょうか。どのぐらいコネクションを維持するかどうかは、 Keep-Alive 機能の領分だと理解しています。 (Apache のKeep-Alive の Timeout デフォルト値は、 5-15 秒) クライアントサイドの Firefox を調べたところ、config に "network.http.pipelining.read-timeout" があり、デフォルト 30 秒と設定されていました。しかしコメントに、`The amount of time a pipelined transaction is allowed to wait before being canceled and retried in a non-pipeline connection` とあり、サーバのタイムアウトとはリンクしなさそうでした。(ここで面白かったのは、 pipelining の実装が、サーバの種類によって機能の On/Off を切り替えるようなものになっていたことです。) ■ HTTP Pipelining をサポートする ブラウザ ### Desktop Browsers * **Opera**: バージョン 4 からフルサポート。 * **Chrome**: サポートしない。バージョン 17 で実験機能として導入、26 で除去された。 (#8991 /#364557) * **Firefox**: サポートするが、デフォルト無効になっている。 (#2654354) * **Safari**: サポートしない。 * **Internet Explorer**: サポートしない。 ### Mobile Browsers モバイルデバイスでは以下の3つ * **Mobile Opera**: フルサポート。 * **Mobile Safari** iOS 5 からサポートしてるぽい * **Android Browser**: 少なくとも 2.x からサポートがある ### Pipelining サポートのあるブラウザのシェア 以上のサポート具合から、 * **Desktop Browser**: 2% 程 * **Mobile Browser** : 50% 程 のブラウザで、 HTTP/1.1 Pipelining が使えていることになります。 ■ 雑感 Pipelining は、モバイル機器を対象にすれば意味がある機能です。パフォーマンスが理論上は速くなるはずだったのに、実際は期待したほど速くならず、バギーなサーバの存在から、疎まれ、壊れ仕様のような扱いになっています。んで、反省は、 SPDY, HTTP/2.0 に生かされているようです。 以下、参考サイト: * Status of HTTP Pipelining in Chromium * Making HTTP Pipelining Usable on the Open Web * Network Performance Effects of HTTP/1.1, CSS1, and PNG * HTTP Pipelining – Big in Mobile * HTTP pipelining - Wikipedia * HTTP Pipelining is a Hit and Miss