更新(結果に興味がある人向け:)
chrome と node-http2 サーバーの間の次のプロトコル ネゴシエーションが失敗する理由を理解できませんでした。私の疑いは、自己署名証明書または ALPN/NPN サポートの問題でした。そこで、 golang HTTP/2 実装に移行しました。同じセットアップが完全に機能し、単一の多重化された TCP 接続が表示されます (chrome --> golang)
私は HTTP/2 について読んでいて、ホストごとに単一の多重化された TCP 接続を使用して HTTP/1.1 のレイテンシの問題を解決する方法を読んでいたので、試してみることにしました。
実験
- 1 つの css、1 つの js、およびいくつかの画像への参照を含む単純な html ファイルを作成しました。
- これらすべてのファイルを提供する Node.js の単純な http サーバー
- クロムを使用して http リクエストを作成しました
- Ubuntu で tcptrack ( tcptrack ) を使用して、http サーバーに対して行われている TCP 接続を追跡しました。
tcptrack ウィンドウには、確立された 4 つの接続が表示されます。そのため、ブラウザは画像と css/js リクエストに対して異なる接続を開いています。
tcpdump を使用して同様の出力を取得します。参考までに、使用した tcptrack コマンドは
tcptrack -d -i eth0 -r 3600 ポート 8989
および tcpdump も同様の出力を示します
tcpdump -i eth0 -nns 0 "dst ポート 8989 および tcp[tcpflags] == tcp-syn"
これらのファイルを提供する単純なオールインワン http サーバーは、以下のようなものでした (関連するコード)
(function(){
...........
var server = http.createServer(function(request, response) {
..........
fs.readFile(filetoRet, function (err,data) {
if(filePath.indexOf(".jpg") >-1){
response.writeHead(200, {"Content-Type": "image/jpg"});
}.....
response.write(data);
response.end();
});
});
server.listen(8989);
})()
この後、http/2 を使用してみました。
- http/2 リクエストを送信するための chrome フラグを有効にしました
- node-http2を使用して http/2 サーバーを作成しました
- 単純な http サーバーは、手順 2 でインストールした http2 サーバー モジュールを使用することを除いて、http/1.1 と同じコードを持っています。
- chrome を使用してリクエストを作成しました (HTTP/2 仕様に準拠した https リクエストである必要がありました)
- キャプチャされた tcptrack/tcpdump 出力
したがって、これはまだ複数の TCP 接続が行われていることを示しています。また、html 内の画像の数を増やすと、接続数が増えます。
ですから、これをどう読んでいいのかわかりません。これは HTTP/2 の動作方法ですか (またはこれはクロムのバグですか)? 単純な http/2 クライアント サーバーを使用して HTTP/2 の利益を視覚化するより良い方法はありますか?
注:私はHTTP / 2サーバーに自己署名証明書を使用しているため、クロムはページに進む前に警告をスローし、閉じられた接続がそれを表している可能性がありますが、ページとそのコンポーネントがプロトコルによって要求される方法に影響を与えるべきではないと思います
これを読んでくださった皆さんの忍耐に感謝し、何か提案があれば感謝します。
シン
PS : Wireshark の TCP キャプチャも例外ではありません。ただ、Wireshark でトラフィックを分離するのが難しいことがわかったので、tcpdump と tcptrack を使用しました。
更新: 更新: chrome://net-internals/ を見ると、HTTP/2 要求のネゴシエーションが失敗し、HTTP/1.1 の使用にフォールバックします。理由はまだわかりません。
Chrome の内部ツール イベントが表示されます
t=879052 [st= 0] +HTTP_STREAM_JOB [dt=19]
--> original_url = "https://msinghlinux.ads.com:8900/"
--> priority = "HIGHEST"
--> url = "https://msinghlinux.ads.com:8900/"
t=879052 [st= 0] +PROXY_SERVICE [dt=0]
t=879052 [st= 0] PROXY_SERVICE_RESOLVED_PROXY_LIST
--> pac_string = "DIRECT"
t=879052 [st= 0] -PROXY_SERVICE
t=879052 [st= 0] +HOST_RESOLVER_IMPL_REQUEST [dt=0]
--> address_family = 0
--> allow_cached_response = true
--> host = "msinghlinux.ads.com:8900"
--> is_speculative = false
t=879052 [st= 0] HOST_RESOLVER_IMPL_CACHE_HIT
t=879052 [st= 0] -HOST_RESOLVER_IMPL_REQUEST
t=879052 [st= 0] +SOCKET_POOL [dt=19]
t=879071 [st=19] SOCKET_POOL_BOUND_TO_CONNECT_JOB
--> source_dependency = 26961 (CONNECT_JOB)
t=879071 [st=19] SOCKET_POOL_BOUND_TO_SOCKET
--> source_dependency = 26967 (SOCKET)
t=879071 [st=19] -SOCKET_POOL
t=879071 [st=19] HTTP_STREAM_REQUEST_PROTO
--> next_proto_status = "negotiated"
--> proto = "http/1.1"
t=879071 [st=19] HTTP_STREAM_JOB_BOUND_TO_REQUEST
--> source_dependency = 26910 (URL_REQUEST)
t=879071 [st=19] -HTTP_STREAM_JOB
次のプロトコルの値は http/1.1 (next_proto_status および proto) です。しかし、このフォールバックを引き起こしたネゴシエーションで何が失敗したかはわかりませんか? 自己署名証明書が原因でしょうか?
HTTP/2 サーバー コード
var options = {
key: fs.readFileSync('./server.key'),
cert: fs.readFileSync('./server.crt')
};
options.log = bunyan.createLogger(...);
require('http2').createServer(options,function(request, response) {
.... same code as http/1.1 server
}).listen(8900);