为什么在发送 HEADERS 帧之前从 HTTP2 客户端发送 5 个 PRIORITY 帧?它们是成功的 HTTP2 连接所必需的吗?
Why 5 PRIORITY frames are sent from HTTP2 client before it sends a HEADERS frame ? Are they necessary for a successful HTTP2 connection?
我注意到一些 HTTP2 客户端(Firefox 和 nghttp)在同意 http2 协议之后和发送 HEADERS 帧之前为流 3、5、7、9、11 发送 5 个优先级帧。我很好奇为什么?我知道PRIORITY frames的意思,但我不明白发送它的意义,但是Firefox和nghttp都这样做,所以一定有一些原因。
最重要的是,根据日志,那些流(流 3、5、7、9、11)在 PRIORITY 帧之后未使用。
Firefox 服务器的输出信息如下所示。
$ nghttpd -d ~/Proxy 8080 key.pem cert.pem -v
Enter PEM pass phrase:
IPv4: listen 0.0.0.0:8080
IPv6: listen :::8080
[ALPN] client offers:
* h2
* spdy/3.1
* http/1.1
SSL/TLS handshake completed
The negotiated protocol: h2
[id=1] [ 18.917] send SETTINGS frame <length=6, flags=0x00, stream_id=0>
(niv=1)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[id=1] [ 18.920] recv SETTINGS frame <length=12, flags=0x00, stream_id=0>
(niv=2)
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):131072]
[SETTINGS_MAX_FRAME_SIZE(0x05):16384]
[id=1] [ 18.920] recv WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=0>
(window_size_increment=12517377)
[id=1] [ 18.920] recv PRIORITY frame <length=5, flags=0x00, stream_id=3>
(dep_stream_id=0, weight=201, exclusive=0)
[id=1] [ 18.920] recv PRIORITY frame <length=5, flags=0x00, stream_id=5>
(dep_stream_id=0, weight=101, exclusive=0)
[id=1] [ 18.920] recv PRIORITY frame <length=5, flags=0x00, stream_id=7>
(dep_stream_id=0, weight=1, exclusive=0)
[id=1] [ 18.920] recv PRIORITY frame <length=5, flags=0x00, stream_id=9>
(dep_stream_id=7, weight=1, exclusive=0)
[id=1] [ 18.920] recv PRIORITY frame <length=5, flags=0x00, stream_id=11>
(dep_stream_id=3, weight=1, exclusive=0)
[id=1] [ 18.920] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
; ACK
(niv=0)
[id=1] [ 18.926] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
; ACK
(niv=0)
[id=1] [ 25.773] recv (stream_id=13) :method: GET
[id=1] [ 25.773] recv (stream_id=13) :path: /plaintext.txt
[id=1] [ 25.773] recv (stream_id=13) :authority: 127.0.0.1:8080
[id=1] [ 25.773] recv (stream_id=13) :scheme: https
[id=1] [ 25.773] recv (stream_id=13) user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:45.0) Gecko/20100101 Firefox/45.0
[id=1] [ 25.773] recv (stream_id=13) accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
[id=1] [ 25.773] recv (stream_id=13) accept-language: en-US,en;q=0.5
[id=1] [ 25.773] recv (stream_id=13) accept-encoding: gzip, deflate, br
[id=1] [ 25.773] recv (stream_id=13) if-modified-since: Wed, 27 Apr 2016 13:10:07 GMT
[id=1] [ 25.773] recv HEADERS frame <length=196, flags=0x25, stream_id=13>
; END_STREAM | END_HEADERS | PRIORITY
(padlen=0, dep_stream_id=11, weight=32, exclusive=0)
; Open new stream
[id=1] [ 25.774] recv WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=13>
(window_size_increment=12451840)
[id=1] [ 25.774] send HEADERS frame <length=42, flags=0x05, stream_id=13>
; END_STREAM | END_HEADERS
(padlen=0)
; First response header
:status: 304
server: nghttpd nghttp2/1.8.0
date: Fri, 29 Apr 2016 08:07:25 GMT
[id=1] [ 25.774] stream_id=13 closed
但是Chrome不发送它们,如下所示。所以它们不是成功连接所必需的?
$ nghttpd -d ~/Proxy 8080 key.pem cert.pem -v
Enter PEM pass phrase:
IPv4: listen 0.0.0.0:8080
IPv6: listen :::8080
[ALPN] client offers:
* h2
* spdy/3.1
* http/1.1
SSL/TLS handshake completed
The negotiated protocol: h2
[id=1] [ 16.069] send SETTINGS frame <length=6, flags=0x00, stream_id=0>
(niv=1)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[id=1] [ 16.083] closed
[ALPN] client offers:
* h2
* spdy/3.1
* http/1.1
SSL/TLS handshake completed
The negotiated protocol: h2
[id=2] [ 16.298] send SETTINGS frame <length=6, flags=0x00, stream_id=0>
(niv=1)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[id=2] [ 16.299] closed
[ALPN] client offers:
* h2
* spdy/3.1
* http/1.1
SSL/TLS handshake completed
The negotiated protocol: h2
[id=3] [ 16.303] send SETTINGS frame <length=6, flags=0x00, stream_id=0>
(niv=1)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[id=3] [ 16.303] recv SETTINGS frame <length=12, flags=0x00, stream_id=0>
(niv=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):1000]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):6291456]
[id=3] [ 16.303] recv WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=0>
(window_size_increment=15663105)
[id=3] [ 16.303] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
; ACK
(niv=0)
[id=3] [ 16.303] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
; ACK
(niv=0)
[id=3] [ 16.311] recv (stream_id=1) :method: GET
[id=3] [ 16.311] recv (stream_id=1) :authority: 127.0.0.1:8080
[id=3] [ 16.311] recv (stream_id=1) :scheme: https
[id=3] [ 16.311] recv (stream_id=1) :path: /plaintext.txt
[id=3] [ 16.311] recv (stream_id=1) accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
[id=3] [ 16.311] recv (stream_id=1) upgrade-insecure-requests: 1
[id=3] [ 16.311] recv (stream_id=1) user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.86 Safari/537.36
[id=3] [ 16.311] recv (stream_id=1) accept-encoding: gzip, deflate, sdch
[id=3] [ 16.311] recv (stream_id=1) accept-language: en-US,en;q=0.8
[id=3] [ 16.311] recv HEADERS frame <length=238, flags=0x25, stream_id=1
....
它们不是成功连接所必需的。
其余的,我只是在这里猜测。 Firefox 将这些流用作 "virtual streams"。然后它使更多的真实流依赖于那些虚拟流。效果应该是创建不同的优先级组,而不需要为每个(实际)流指定优先级。
我注意到一些 HTTP2 客户端(Firefox 和 nghttp)在同意 http2 协议之后和发送 HEADERS 帧之前为流 3、5、7、9、11 发送 5 个优先级帧。我很好奇为什么?我知道PRIORITY frames的意思,但我不明白发送它的意义,但是Firefox和nghttp都这样做,所以一定有一些原因。
最重要的是,根据日志,那些流(流 3、5、7、9、11)在 PRIORITY 帧之后未使用。
Firefox 服务器的输出信息如下所示。
$ nghttpd -d ~/Proxy 8080 key.pem cert.pem -v
Enter PEM pass phrase:
IPv4: listen 0.0.0.0:8080
IPv6: listen :::8080
[ALPN] client offers:
* h2
* spdy/3.1
* http/1.1
SSL/TLS handshake completed
The negotiated protocol: h2
[id=1] [ 18.917] send SETTINGS frame <length=6, flags=0x00, stream_id=0>
(niv=1)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[id=1] [ 18.920] recv SETTINGS frame <length=12, flags=0x00, stream_id=0>
(niv=2)
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):131072]
[SETTINGS_MAX_FRAME_SIZE(0x05):16384]
[id=1] [ 18.920] recv WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=0>
(window_size_increment=12517377)
[id=1] [ 18.920] recv PRIORITY frame <length=5, flags=0x00, stream_id=3>
(dep_stream_id=0, weight=201, exclusive=0)
[id=1] [ 18.920] recv PRIORITY frame <length=5, flags=0x00, stream_id=5>
(dep_stream_id=0, weight=101, exclusive=0)
[id=1] [ 18.920] recv PRIORITY frame <length=5, flags=0x00, stream_id=7>
(dep_stream_id=0, weight=1, exclusive=0)
[id=1] [ 18.920] recv PRIORITY frame <length=5, flags=0x00, stream_id=9>
(dep_stream_id=7, weight=1, exclusive=0)
[id=1] [ 18.920] recv PRIORITY frame <length=5, flags=0x00, stream_id=11>
(dep_stream_id=3, weight=1, exclusive=0)
[id=1] [ 18.920] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
; ACK
(niv=0)
[id=1] [ 18.926] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
; ACK
(niv=0)
[id=1] [ 25.773] recv (stream_id=13) :method: GET
[id=1] [ 25.773] recv (stream_id=13) :path: /plaintext.txt
[id=1] [ 25.773] recv (stream_id=13) :authority: 127.0.0.1:8080
[id=1] [ 25.773] recv (stream_id=13) :scheme: https
[id=1] [ 25.773] recv (stream_id=13) user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:45.0) Gecko/20100101 Firefox/45.0
[id=1] [ 25.773] recv (stream_id=13) accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
[id=1] [ 25.773] recv (stream_id=13) accept-language: en-US,en;q=0.5
[id=1] [ 25.773] recv (stream_id=13) accept-encoding: gzip, deflate, br
[id=1] [ 25.773] recv (stream_id=13) if-modified-since: Wed, 27 Apr 2016 13:10:07 GMT
[id=1] [ 25.773] recv HEADERS frame <length=196, flags=0x25, stream_id=13>
; END_STREAM | END_HEADERS | PRIORITY
(padlen=0, dep_stream_id=11, weight=32, exclusive=0)
; Open new stream
[id=1] [ 25.774] recv WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=13>
(window_size_increment=12451840)
[id=1] [ 25.774] send HEADERS frame <length=42, flags=0x05, stream_id=13>
; END_STREAM | END_HEADERS
(padlen=0)
; First response header
:status: 304
server: nghttpd nghttp2/1.8.0
date: Fri, 29 Apr 2016 08:07:25 GMT
[id=1] [ 25.774] stream_id=13 closed
但是Chrome不发送它们,如下所示。所以它们不是成功连接所必需的?
$ nghttpd -d ~/Proxy 8080 key.pem cert.pem -v
Enter PEM pass phrase:
IPv4: listen 0.0.0.0:8080
IPv6: listen :::8080
[ALPN] client offers:
* h2
* spdy/3.1
* http/1.1
SSL/TLS handshake completed
The negotiated protocol: h2
[id=1] [ 16.069] send SETTINGS frame <length=6, flags=0x00, stream_id=0>
(niv=1)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[id=1] [ 16.083] closed
[ALPN] client offers:
* h2
* spdy/3.1
* http/1.1
SSL/TLS handshake completed
The negotiated protocol: h2
[id=2] [ 16.298] send SETTINGS frame <length=6, flags=0x00, stream_id=0>
(niv=1)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[id=2] [ 16.299] closed
[ALPN] client offers:
* h2
* spdy/3.1
* http/1.1
SSL/TLS handshake completed
The negotiated protocol: h2
[id=3] [ 16.303] send SETTINGS frame <length=6, flags=0x00, stream_id=0>
(niv=1)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[id=3] [ 16.303] recv SETTINGS frame <length=12, flags=0x00, stream_id=0>
(niv=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):1000]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):6291456]
[id=3] [ 16.303] recv WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=0>
(window_size_increment=15663105)
[id=3] [ 16.303] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
; ACK
(niv=0)
[id=3] [ 16.303] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
; ACK
(niv=0)
[id=3] [ 16.311] recv (stream_id=1) :method: GET
[id=3] [ 16.311] recv (stream_id=1) :authority: 127.0.0.1:8080
[id=3] [ 16.311] recv (stream_id=1) :scheme: https
[id=3] [ 16.311] recv (stream_id=1) :path: /plaintext.txt
[id=3] [ 16.311] recv (stream_id=1) accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
[id=3] [ 16.311] recv (stream_id=1) upgrade-insecure-requests: 1
[id=3] [ 16.311] recv (stream_id=1) user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.86 Safari/537.36
[id=3] [ 16.311] recv (stream_id=1) accept-encoding: gzip, deflate, sdch
[id=3] [ 16.311] recv (stream_id=1) accept-language: en-US,en;q=0.8
[id=3] [ 16.311] recv HEADERS frame <length=238, flags=0x25, stream_id=1
....
它们不是成功连接所必需的。
其余的,我只是在这里猜测。 Firefox 将这些流用作 "virtual streams"。然后它使更多的真实流依赖于那些虚拟流。效果应该是创建不同的优先级组,而不需要为每个(实际)流指定优先级。