为什么在发送HEADERS帧之前从HTTP2客户端发送5个PRIORITY帧?它们是成功连接HTTP2所必需的吗?

时间:2016-04-29 09:17:52

标签: http2 nghttp2

我注意到一些HTTP2客户端(Firefox和nghttp)在同意http2协议之后和发送HEADERS帧之前为流3,5,7,9,13发送了5个PRIORITY帧。我很好奇为什么?我知道PRIORITY帧的含义,但我没有明确发送它,但Firefox和nghttp都这样做,所以必须有一些原因。

最重要的是,根据日志,PRIORITY帧之后不会使用这些流(流3,5,7,9,11)。

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
....

1 个答案:

答案 0 :(得分:1)

成功连接需要

其余的,我只是在这里猜测。 Firefox正在将这些流用作“虚拟流”。然后它进一步依赖于那些虚拟流的实际流。效果应该是创建不同的优先级组,而不需要指定每(实际)流的优先级。