Tuesday, January 20, 2015

H2O version 0.9.1 released with support for HTTP2 dependency-based prioritization

Today I am pleased to announce the release of H2O version 0.9.1. The release tar-ball can be found in the releases section of the GitHub repository.

H2O is an optimized HTTP server with support for HTTP/1.x and the upcoming HTTP/2 protocol.

Version 0.9.1 contains many improvements that have gone into the source tree since the initial release, including contributions by people other than the original developers. I am very happy and thankful to those who have started sending pull-requests to H2O.

The full list of the changes can be found in the changelog. But on this blogpost I would like to concentrate on the issues regarding HTTP/2.

■Support for draft-16

H2O version 0.9.1 supports both draft-14 and draft-16. Draft-16 is the latest draft of HTTP/2, now at the final stage of becoming an RFC standard. Draft-14 is still supported for interoperability with older user-agents.

■Dependency-based prioritization

Dependency-based prioritization is one of the key functions of HTTP/2. It allows the web browsers to control the order in which the server sends the responses (e.g. send CSS files before HTML). Firefox/37 is going to start using the prioritization method, and we are happy to be able to support it. For more information about dependency-based prioritization and how it would be used, I would suggest reading Bits Up!: HTTP/2 Dependency Priorities in Firefox 37.

As Mozilla has enabled HTTP/2 by default in Firefox/35, it is now possible to take the benefit of using HTTP/2 to serve contents to the users faster than ever. I hope that H2O could be of some help in doing so.

Thursday, January 15, 2015

[メモ] TCP上(もしくはHTTP)にリトライ可能なアプリケーションプロトコルを実現する方法

HTTP/1.1の持続的接続においては、サーバがリクエストを受け取ったあとに異常終了したのか、リクエストを受け取らずに接続を閉じたのか判別することができない。このため、べき等性の保証がないアプリケーションにおいて、リトライを行うべきか否か自動的に判断できなくなる場合がしばしば発生する

リトライ可能か否か(ピアがメッセージの処理を開始した否か)を判別するには、より細かな情報交換を行う別種のプロトコルを採用しても良いが、複雑なプトロコルはパフォーマンスに悪影響を及ぼす可能性が高いので避けたいところである。

というわけで、以下本題。

pipeliningを行わないHTTP/1.1のような単純なリクエスト/レスポンス型プロトコルをそのままに、アプリケーションレイヤへのリクエスト到達可否を判定する手軽な方法としては、SO_LINGERを用いる方法がある。具体的には、以下のような形式でサーバを実装する。
while (1) {
  receive_request();
  use_RST_for_close(); // SO_LINGERを使い、RSTで切断するよう設定
  handle_request();
  send_response();
  use_graceful_close(); // SO_LINGERを使い、graceful closeを行うよう設定
}
クライアントサイドでは、リクエスト送信後にEPIPE(write(2)の場合)かECONNRESET(read(2)の場合)を受け取った場合のみ、リクエストを再送すればよい。

別解としては、サーバが接続を切断する際に「HTTP/1.1 599 Going Away」のようなレスポンスを(たとえリクエストを受信していなくとも)送信するという方法が考えられる(この場合はlingering closeを行わない)。クライアントは、サーバからこのレスポンスを受信した場合のみ、リクエスト再送を行えば良い。

追記: H2Oでは後者の方式をサポートしようかと考えている。そうすれば「Docker と SO_REUSEPORT を組み合わせてコンテナのHot Deployにチャレンジ - blog.nomadscafe.jp」で挙げられているようなデプロイ手法において、(例示されている常にリトライする方法とは異なり)安全なホットデプロイが実現可能になる。

注: パイプライン処理については行わない前提で考える