5月 132019
目次
概要
参照 RFC7230 6
- HTTP は、リクエスト・レスポンスのセットを TCP コネクション上で送受信する
- HTTP/1.0 の既定では、1 つのリクエスト・レスポンスが完了したら TCP コネクションは閉じられる
Connection: keep-alive
リクエストヘッダーにより TCP コネクションを閉じず再利用する持続的接続 (Persistent Connection) ができるようになった
- HTTP/1.1 では持続的接続は既定で有効であり、
Connection: keep-alive
は必要ない- HTTP/1.0 サーバーとの持続的接続を望む場合は送信される
- HTTP/1.1 における「コネクション」とは、メッセージ経路全体ではなく隣接ノード間 (クライアントとプロキシ間など) のコネクションのことを指す
コネクションの持続性
参照 RFC7230 6.3, A.1.2
- コネクションはいつでも close できる
- HTTP/1.1 以上であれば
Connection: close
が送信されるまで持続できる - HTTP/1.0 の場合、以下をすべて満たすならば持続できる
Connection: keep-alive
が指定されている- プロキシ宛のリクエストではない
- HTTP/1.0 の
keep-alive
の仕組みを望んで利用する
- HTTP/1.0 未満の場合、持続しない
- プロキシサーバーは HTTP/1.0 クライアントと持続的接続をしてはならない
Proxy-Connection
ヘッダーはうまく機能しないため送信しないことが奨励される
同時接続数
参照 RFC7230 6.4
- RFC2616 では同時接続数の具体的な上限数(サーバーあたり 2 個)が規定されていたが、RFC7230 で撤廃された
- しかし上限数の制限自体は設けるべきとされている
パイプライン化
参照 RFC7230 6.3.2
- 持続的接続をサポートするクライアントは、パイプライン化を利用することができる
- レスポンスを待たずにリクエストを送信できる
- リクエストされた順序どおりにレスポンスが返されるべきである
- 冪等メソッドに限る
- GET, HEAD, OPTIONS, TRACE, PUT, DELETE
- サーバーは安全メソッドであれば並列処理して良い
- GET, HEAD, OPTIONS, TRACE
- パイプライン化されたリクエストを受信したプロキシも、パイプライン化を利用できる
- 実際にはブラウザの既定値が無効であったりして、あまり利用されていない模様
コネクションの終了
参照 RFC7230 6.6
Connection: close
が含まれるリクエスト・レスポンスが送信された際、そのペアの処理が終了後 close されるclose
が送信されたコネクション上には、それ以上のリクエストを送信することも受信・処理することもしてはならない
TCP リセット問題
- サーバーがコネクションを終了する際、TCP を即時 close すると、クライアントが最後のレスポンスを受け取れなくなるリスクがある
- TCP リセット問題を防ぐためには、サーバー側は以下の手順で close する必要がある
- 書き込み側のみ close する
- 以下のいずれかの時点まで読み取る
- クライアントからの対応する close を受信した
- クライアントが最終レスポンスを全て受信したと確信できた
- 読み込み側も含め、コネクションを close する
Connection ヘッダーの処理
参照 RFC7230 6.1
- Connection ヘッダーは、以下の2つの機能を提供する
- 隣接ノード間向けのヘッダー (hop-by-hop ヘッダー) と、経路全体向けのヘッダー (end-to-end ヘッダー) を区別できるようにする機能
- コネクションの close を通知する機能 (
Connection: close
)
- Connection ヘッダー自体は、隣接ノード間のコミュニケーションにのみ利用される
- 中継者は Connection ヘッダーを以下の手順で処理する
- Connection ヘッダーに指定された各値 (コネクション オプション) と同じ名前のヘッダーをメッセージから除去する
- Connection ヘッダーの値を自前のものに置換するか、Connection ヘッダーを除去する
- hop-by-hop ヘッダーと定義されているヘッダーでも Connection ヘッダーに指定しなければならない [RFC7230 A.2]
- end-to-end ヘッダー (プロキシが必ずフォワードしなければならないヘッダー) は Connection ヘッダーに指定してはならない
- 例えば
Cache-Control
など
- 例えば
リクエストの再試行
参照 RFC7230 6.3.1
- コネクションが close されリクエストが中止された際、クライアントは冪等メソッドのリクエストは自動的に再試行して良い
- GET, HEAD, OPTIONS, TRACE, PUT, DELETE
- 非冪等リクエストは自動的に再試行してはならない
- POST, CONNECT
- メソッドにかかわらず、冪等である事を知っている場合は再試行して良い
- 再試行元のリクエストがターゲットリソースに適用されていない事を検出した場合も再試行して良い
- 自動的な再試行が失敗したら、更なる再試行はするべきではない