HTTP2

HTTP 明确划分了语义和语法。语义描述了请求和响应交换的概念,包括:方法、状态码、标头(元数据)和正文(有效载荷),语法则描述了如何将语义映射到在网络上传输的字节。SPDY 采用了 HTTP/1.1 语义,并将语法从字符串改为二进制形式。


注意使用的加密套件:
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xC0,0x2F)

头部压缩技术需要在支持 HTTP/2 的浏览器和服务端之间:
  • 维护一份相同的静态字典(Static Table),包含常见的头部名称,以及特别常见的头部名称与值的组合;
  • 维护一份相同的动态字典(Dynamic Table),可以动态的添加内容;
  • 支持基于静态哈夫曼码表的哈夫曼编码(Huffman Coding);
使用字典可以极大地提升压缩效果,其中静态字典在首次请求中就可以使用。对于静态、动态字典中不存在的内容,还可以使用哈夫曼编码来减小体积。HTTP/2 使用了一份静态哈夫曼码表(详见),也需要内置在客户端和服务端之中。

HTTP/1 的状态行信息(Method、Path、Status 等),在 HTTP/2 中被拆成键值对放入头部(冒号开头的那些),同样可以享受到字典和哈夫曼压缩。


默认情况下,浏览器会针对这些情况使用同一个连接:

  • 同一域名下的资源;
  • 不同域名下的资源,但是满足两个条件:
    1. 解析到同一个 IP;
    2. 使用同一个证书;

使用多域名加上相同的 IP 和证书部署 Web 服务有特殊的意义:让支持 HTTP/2 的终端只建立一个连接,用上 HTTP/2 协议带来的各种好处;而只支持 HTTP/1.1 的终端则会建立多个连接,达到同时更多并发请求的目的。

虽然 HTTP1.1 版允许复用 TCP 连接(管道机制),但是同一个TCP 连接里面,所有的数据通信是按次序进行的。服务器只有处理完一个回应,才会进行下一个回应。要是前面的回应特别慢,后面就会有许多请求排队等着。这称为"队头堵塞"(Head-of-line blocking)。
HTTP/2 通过请求复用解决了这个问题,它消除了应用程序层的HOL阻塞,但HOL仍然存在于传输(TCP)层。HTTP/2 多请求复用一个TCP连接,一旦发生丢包,就会block住所有的HTTP请求

HTTP/2 的多路复用特性,使得可以在一个连接上同时打开多个,双向传输数据,响应多个请求(多工)。 // 解决了线头阻塞的问题

Server Push,意味着服务端可以在发送页面 HTML 时主动推送其它资源,而不用等到浏览器解析到相应位置,发起请求再响应,通过 PUSH_PROMISE 帧推送给浏览器(服务器自己判断需要主动发送哪些),有缓存时客户端会发送 RST_STREAM 帧来终止流。(相关技术:link 的一些 html 属性——预加载 // 浏览器主动请求)。


对于请求:所有头部名都需要小写。不能发送某些头部(keep-alive等)。客户端必须支持 gzip 压缩。如果服务端收到数据帧长度和不等于 content-length 的请求,必须返回 400(Bad Request)。同时,对于 POST 请求,也需要包含 content-length 头部。

HTTP/1 的请求和响应报文,都是由起始行、首部和实体正文(可选)组成,各部分之间以文本换行符分隔。而 HTTP/2 将请求和响应数据分割为更小的,并对它们采用二进制编码
  • 帧(Frame):HTTP/2 数据通信的最小单位。帧用来承载特定类型的数据,如 HTTP 首部、负荷(数据帧),或者用来实现特定功能(控制帧),例如打开、关闭流。每个帧都包含帧首部,其中会标识出当前帧所属的流,一些新的字段(有些类似以前的头字段如 ':host');
  • 消息(Message):指 HTTP/2 中逻辑上的 HTTP 消息。例如请求和响应等,消息由一个或多个帧组成;
  • 流(Stream):存在于连接中的一个虚拟通道。流可以承载双向消息,每个流都有一个唯一的整数 ID;客户端发出的数据流,ID一律为奇数,服务器发出的,ID为偶数。
  • 连接(Connection):与 HTTP/1 相同,都是指对应的 TCP 连接;
客户端还可以指定数据流的优先级。优先级越高,服务器就会越早回应。

HTTP/2 doesn't support HTTP 1.1's chunked transfer encoding mechanism

多种控制,其中有三种用来管理流(stream):

  • SYN_STREAM:打开流;
  • SYN_REPLY:远程确认新打开的流;
  • RST_STREAM:关闭流;1.1 唯一的办法是关闭tcp链接

在 HTTP/2 中,同域名下所有通信都在单个连接(wireshark: tcp.stream)上完成,这个连接可以承载任意数量的双向数据流(多路复用)。每个数据流都以消息的形式发送,而消息又由一个或多个帧组成。多个帧之间可以乱序发送,因为根据帧首部的流标识可以重新组装