HTTP
Go ならわかるシステムプログラミングを読んで、Go 言語で HTTP サーバ/クライアントを実装したりした。ブラウザ経由でサーバにアクセスすると、ちゃんと HTTP 通信ができていることがわかり面白い。サーバ側を変えるだけで Keep alive もきいている (ようにみえる)し、タイムアウトの設定もちゃんと動く (それはそう)。
それと、以下も合わせて読んだ。もともと以下の記事を最初に読んで、そういえば家に Go のシステムプログラミングの本があったなと思い実践してみた。
ただ、本に書かれていることを実装しただけではいまいち理解が深まった感じがしないので、実際に Keep-Alive を有効にしたことでパフォーマンスがどれくらい変わるのか?などは実験してみたい。それと、HTTP/2 もどのような場合に早くなったり遅くなったりするのかも少し気になる。
余談
2. Capture filter は Loopback: lo0 を選択する
3. Display filter は ip.addr == 127.0.0.1 and tcp.port == 8080 を設定する
HTTP/1.0
TCP は、接続時に 3-way handshake を行う。3-way handshake はクライアント/サーバ間で 3 回のやり取りを行うので、これにかかる時間は 3 * RTT となる。HTTP/1.0 の場合、1度の HTTP リクエスト/レスポンスのたびに TCP 接続が切れるので、これは効率が悪い。 下記は、ブラウザ経由でアクセスして、3 回更新した場合。毎回 TCP コネクションが貼りなおされていることがわかる。
code:shell
$ ./server
Accept: 127.0.0.1:56918
GET / HTTP/1.1
Host: localhost:8080
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-us
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.3 Safari/605.1.15
Accept: 127.0.0.1:56920
GET / HTTP/1.1
Host: localhost:8080
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-us
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.3 Safari/605.1.15
Accept: 127.0.0.1:56922
GET / HTTP/1.1
Host: localhost:8080
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-us
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.3 Safari/605.1.15
https://gyazo.com/3c3d34b2bc5ab4b26f79bc0c0bf02b16
HTTP/1.1
HTTP/1.1 からは Keep-Alive が仕様に入った。 TCP コネクションの回数を減らすことができる。下記は、上記と同様にブラウザ経由での接続を試した場合。ただし、3回更新した後、タイムアウトを挟んでもう一度更新している。タイムアウトするまでは TCP コネクションが使い回されていることがわかる。
code:shell
$ ./server
Accept: 127.0.0.1:56928
GET / HTTP/1.1
Host: localhost:8080
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-us
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.3 Safari/605.1.15
GET / HTTP/1.1
Host: localhost:8080
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-us
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.3 Safari/605.1.15
GET / HTTP/1.1
Host: localhost:8080
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-us
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.3 Safari/605.1.15
Timeout
Accept: 127.0.0.1:56930
GET / HTTP/1.1
Host: localhost:8080
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-us
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.3 Safari/605.1.15
Timeout
https://gyazo.com/aeaaf94295f09985ed004bb82b5fdf87
HTTP/2
HTTP/2 によって何が改善されたのか?それによってどういう時に早くなるのか?については、色々まとめてみたい気持ちがある。Rebuild で話が出ていたので聞いてみたが、興味深かった (古いエピソードだが)。
気持ちが沸いたら詳しくまとめるつもりだけど、一旦変更点をあげると以下のようなものがあるようだ。
バイナリフレームベース
元はテキストベースだったものが変わった
テキスト解析部分のオーバーヘッドがなくなる
テキストベースの場合、結局パーサーの実装に依存して速度が変わってくるようだ
rebuild 内だと、oku さんが速い HTTP パーサについてのお話に少し触れていた (1h5min くらいのとこ)
ヘッダ仕様
HEADERS フレーム
HPACK という規格による圧縮がデフォルトで有効 SSL
HTTPS が強制されるとかされないとかみたいな話を小耳に挟んでいるがどうなのか、まだソースにあたれていない
HTTP/2 がどのような場合に有効で、どのような場合に有効でないか?は、ちゃんと検証したりして仕組みを理解しておく必要はありそう。ただ、rebuild.fm でも聞いたが、
初回ダウンロードが早くなる
jQuery があり、css があり、画像がいくつもあるようなサイト
ページレンダリングが開始されるまでの時間が早くなる
一番速度に聞いてくるのは、リクエスト間の優先順位付けが HTTP/2 だと可能だから
html をダウンロードしたら、ヘッダにある css や js をダウンロードしにいく
HTTP 1.1 では、全部一度に落とそうとするから遅くなる
HTTP 2 では css や js のみ優先的に落とせる
接続開始時の速さと、リソース取得の優先順位付けがキモらしい
TCP のバッファの話とか
ドメインあたりの同時アクセス数制限があって、それを避けるためにドメインを変えるみたいなことがあったようだ
でも、これをやってしまうと HTTP/2 では優先順位の制御ができなくなるので帰って遅くなってしまう
ダウンロード速度自体にはそこまで差はないというのはどうしてだろう