HTTPの基礎

来週の月曜に弊社のトップエンジニアによるHTTPに関する講座が開催されるということで、
講座を有意義にするために事前にHTTPに関する知識をインプットしておこうと思います。

HTTP(Hypertext Transfer Protocol)とは?

クライアントとサーバー間の通信のプロトコル

HTTP0.9

初期のHTTPです。 例は以下のようなものです。

GET /
  • リクエスト・レスポンス
  • レスポンスはHTML
  • 接続は都度切断される

HTTP1.0

  • レスポンスはHyperTextに限定されなくなりました。
  • 現在ではよく見るものが指定できるようになりました。
  • 残念ながらリクエスト・レスポンスごとに接続が切断されてしまいます。

  • リクエストの例

GET / HTTP/1.0
User-Agent: XXXXXXXXX
Accept: */*
  • レスポンスの例
HTTP/1.0 200 OK
Content-Type: text/plain
Content-Length 123345
Expires: Fri, 1 Oct 2014 16:13:25 GMT
Last-Modified: Wed, 1 Sep 2014 16:13:25 
Server:Nginx 1.3

プレーンテキストレスポンス

HTTP1.1

  • キープアライブの追加による、複数リクエストを同一の接続で行う。 (リクエストのパイプライン化)
  • TCP前提。
  • UDPは使えない。

  • リクエストの例

GET /keiwt/keiwt.hatenablog.com/edit?editinplace=1&entry=8454420450075629009 HTTP/1.1
Host: blog.hatena.ne.jp
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36
Referer: http://keiwt.hatenablog.com/entry/2014/11/29/162903
Accept-Encoding: gzip, deflate, sdch
Accept-Language: ja,en-US;q=0.8,en;q=0.6,es;q=0.4
Cookie: b=XXXXXXXXXXX/XXXXXXXXXXXXXX; __gads=ID=XXXXXXXXXX:T=XXXXXXX:S=XXXXXX; Accept-Language=en;
  • レスポンスの例
HTTP/1.1 200 OK
Content-Encoding: gzip
Content-Type: text/html; charset=utf-8
Date: Sat, 06 Dec 2014 02:54:25 GMT
P3P: CP="OTI CUR OUR BUS STA"
Server: nginx
Set-Cookie: sk=XXXXXXXXXXXXX; path=/
Vary: Accept-Language, Cookie
X-Content-Type-Options: nosniff
X-Dispatch: Hatena::Epic::Admin::User::Blog::Edit#edit
X-Revision: XXXXXXXXXXXXXXXX
X-Runtime: 0.175711
X-XSS-Protection: 1
transfer-encoding: chunked
Connection: keep-alive

HTTP2.0

HTTP2の草案

  • 目標
リクエストとレスポンスの多重化によるレイテンシの削減
HTTPヘッダフィールドの効率的な圧縮によるプロトコルオーバーヘッドの最小化
リクエスト優先度設定とサーバープッシュの実現
  • 何が変わらずに何が変わらないのか
HTTPのコアコンセプトは変わらない(既存のアプリは特に変更しなくてもHTTP2.0を使用できる)
変更があるのはデータのフォーマット方法とクライアント・サーバー間の通信方法
  • リクエストとレスポンスの多重化(バイナリフレーミングレイヤーを使用)
リクエストヘッダーの後に空行でリクエストデータを送信するのではなく、
HEADERSフレーム、DATAフレームなどのように分割されたデータが単一のTCP接続内で
多数の並列ストリームとしてメッセージを交換する。

HTTP1.1の場合は1接続1レスポンスなので、HOLブロッキングが発生する可能性がありますね。
多重化できていると、HOLブロッキングが発生しないですね。

また、HTTP1.1でのパフォーマンス最適化策の
ファイル結合・スプライト画像・ドメインシャーディングが不要になりますね。
gruntとかは自動的にHTTP1.1の最適化策を実行するようになっているのはどうしましょうかね。。。。

さらにホストごとに6接続もしていたのが、1接続で済むようになります。
ドメインシャーディングをしてホストをたくさん分けて、6接続なんて。。。。

複数接続があると、TCPスロースタートが毎回それぞれの接続で発生してしまいます。

接続数が減ることで、ネットワーク輻輳のリスクも低減され、
ネットワーク・インフラの視点からも望ましいです。

  • インターリーブ
    HTTP2.0に関連して、よく出てきます。
    端的に説明すると同時並行で読み書きを行うことです。

  • サーバープッシュ
    クライアントのリクエスト1つに対して、
    複数のレスポンスを返す機能です。
    プッシュされたリソースはクライアントにキャッシュ可能です。(異なるページのも利用できます)
    GoogleによるGmailのパフォーマンスの最適化で
    CSSやJSのインライン(一部)をしていたのですが、
    その必要もなくなります。
    インラインは個人的にあまり好きではないですし。。
    また、インラインだとキャッシュされないですし。。。

  • ヘッダ圧縮
    HTTP1.1ではプレーンテキストで送信されていたヘッダを圧縮します。
    小さいデータの場合は圧縮・解凍のオーバーヘッドにより、
    逆にパフォーマンスが悪くなるような気もしないでもないですが。。
    圧縮よりも大きな改善だと考えているのは
    ヘッダテーブルをクライアントとサーバーに用意し、
    リクエスト・レスポンスでは同じデータを送らないようにすることです。
    ヘッダって結構重複している部分があると思うんですよね。
    User-Agentとか。Keep-Aliveとか。

  • HTTPS
    あと、HTTP2.0の忘れてはならない内容が基本HTTPS接続を前提とするということです。
    ALPN(Application Layer Protocol Negotiation)によるHTTP2.0サポートの発見は
    HTTPSネゴシエーションの一部で実行されるからです。

HTTP接続でHTTP2.0を使用したい場合は

Upgrade: HTTP/2.0

をリクエストヘッダに指定します。
対応していれば、Upgradeしてもらえます。

  • デプロイメントの注意点
    HTTP2.0はエンドツーエンドでサポートされていないといけないので、
    HTTPS and TLSが前提のようです。

  • Wiresharkでの調査
    調査した結果まだ、HTTP2.0はありませんでした。
    TLSAWSとの接続で見つかりました。
    中間装置がHTTP2.0に対応が必要であることも考えると
    HTTP2.0が世の主流になるのはもう少し時間がかかりそうですね。。

Remove all ads