John Jiang

a cup of Java, cheers!
https://github.com/johnshajiang/blog

   :: 首页 ::  :: 联系 :: 聚合  :: 管理 ::
  131 随笔 :: 1 文章 :: 530 评论 :: 0 Trackbacks
探索HTTP/2: 流的状态
探索HTTP/2系列的第四篇文章,解读了HTTP/2流的状态,以及状态之间的转化。(2016.10.09最后更新)

1. 概述
    HTTP/2的流(Stream)是有状态的。当客户端或服务器端在使用某个流去发送或接收特定帧(Frame)或包含特定标签(Flag)的帧时,会引起流的状态的转化。HTTP 2协议定义的流状态,如下所示:
                         +--------+
                 send PP |        | recv PP
                
,--------|  idle  |--------.
               /         |        |         \
              v          +--------+          v
       +----------+          |           +----------+
       |          |          | send H /  |          |
,------| reserved |          | recv H    | reserved |------.
|      | (local)  |          |           | (remote) |      |
|      +----------+          v           +----------+      |
|          |             +--------+             |          |
|          |     recv ES |        | send ES     |          |
|   send H |     ,-------|  open  |-------.     | recv H   |
|          |    /        |        |        \    |          |
|          v   v         +--------+         v   v          |
|      +----------+          |           +----------+      |
|      |   half   |          |           |   half   |      |
|      |  closed  |          | send R /  |  closed  |      |
|      | (remote) |          | recv R    | (local)  |      |
|      +----------+          |           +----------+      |
|           |                |                 |           |
|           | send ES /      |       recv ES / |           |
|           | send R /       v        send R / |           |
|           | recv R     +--------+   recv R   |           |
| send R /  `----------->|        |<-----------'  send R / |
| recv R                 | closed |               recv R   |
`----------------------->|        |<----------------------'
                         +--------+

   send:   endpoint sends this frame
   recv:   endpoint receives this frame

   H:  HEADERS frame (with implied CONTINUATIONs)
   PP: PUSH_PROMISE frame (with implied CONTINUATIONs)
   ES: END_STREAM flag
   R:  RST_STREAM frame
    总的说,HTTP/2为流的整个生命周期定义了7种状态:idle,reserved (local),reserved (remote),open,half closed (local),half closed (remote)和closed。当一端发送或接收头部块(由一个HEADERS/PUSH_PROMISE帧和紧随它的零到多个CONTINUATION帧组成的集合)或RST_STREAM帧,或包含有END_STREAM标签的帧(HEADERS和DATA)之后,将改变流的状态。
    流的状态基于各端自己的视角。由于帧的传输会有网络延迟,在同一时刻,不同端认为的流的状态可能是不同的。比如,当发送端使用一个处于idle状态的流发送一个不包含END_STREAM标签的HEADERS帧之后会立即认为该流处于open状态,但此时接收端尚未得到该HEADERS帧,所以在那一时刻,接收端依然认为该流的状态是idle。

2. idle
    所有的流在创建之初都处于idle状态。处于idle状态的流,只允许被用于发送HEADERS帧,但可以被用于接收HEADERS和PRIORITY帧。在一端使用该状态的流发送或接收HEADERS帧之后,该端会认为此流的状态转变为open。接收PRIORITY帧不会改变流的状态。
    一个idle状态的流可被另一个流通过发送/接收PUSH_PROMISE帧保留着,使其在将来被用于服务器端推送。被保留的流的状态则从idle变为reserved (local/remote)。

3. open
    处于open状态的流可被用于发送任何类型的帧。使用该状态的流去发送/接收包含有END_STREAM标签的帧(HEADERS和DATA)之后,会使该流的状态变成half closed (local/remote)。使用open状态的流发送或接收RST_STREAM帧之后,则会使它的状态转变为closed。

4. half closed (local/remote)
    状态half closed (local)与half closed (remote)中的local与remote的区别,完全是基于各端自己的视角。对于同一个流的两端,如果一端认为这个流的状态是half closed (local),那么另一端只能认为这个流的状态是half closed (remote)。
    处于half closed (local)状态的流只能被用于发送WINDOW_UPDATE,PRIORITY和RST_STREAM帧,但可以被用于接收任何类型的帧。相对应地,处于half closed (remote)状态的流只能被用于接收WINDOW_UPDATE,PRIORITY和RST_STREAM帧,但可以被用于发送任何类型的帧。

5. reserved (local/remote)
    与half closed (local/remote)状态相似,reserved (local/remote)状态中的local与remote也是基于流两端各自的视角。更具体的是,服务器端发送PUSH_PROMISE将一个idle状态的流保留着以用于未来的推送,并视这个被保留的流的状态为reserved (local),而客户端则视这个流的状态为reserved (remote)。
    服务器端使用reserved (local)状态的流向客户端发送HEADERS帧。该HEADERS帧就是服务器端推送(Server Push)中被推送的响应的头部。当发送了HEADERS帧之后,服务器端将视该流的状态为half closed (remote)。
相应地,客户端通过reserved (remote)状态的流接收到服务器端推送的响应的头部,然后会视该流的状态为half closed (local)。
    扩展一下,服务器端推送中被保留的流的状态在变为half closed(local/remote)之后才可能被用于接收/发送被推送的响应的体部,也就是DATA帧。

6. closed
    当一端使用一个流发送或接收到RST_STREAM帧,或通过状态为half closed (local/remote)的流接收/发送包含有END_STREAM标签的帧之后,都会视这个流的状态为closed。
    closed状态预示着流的终结,处于该状态的流将只能发送或接收PRIORITY帧。但有一个特例。即,如果通过使用half closed (local/remote)状态的流去接收或发送包含有END_STREAM标签的帧(HEADERS或DATA),以使该流的状态变为closed,那么在此之后的较短时间内,仍然可以接收WINDOW_UPDATE或RST_STREAM帧。
posted on 2016-10-08 21:17 John Jiang 阅读(3008) 评论(0)  编辑  收藏 所属分类: 原创HTTP/2探索HTTP/2

只有注册用户登录后才能发表评论。


网站导航: