HTTP/2相比较于HTTP1.0来说,增加了 请求/响应复用、报头压缩和服务器推送。
请求/响应复用
单一 TCP 连接的问题在于,一次只能发出一个请求,所以客户端必须等到收到响应后才能发出另一个请求。这就是 “线头阻塞” 问题。正如之前讨论的,典型的变通方案是打开多个连接;每个请求一个连接。但是,如果可以将消息分解为更小的独立部分并通过连接发送,此问题就会迎刃而解。
这正是 HTTP/2 希望达到的目标。将消息分解为帧,为每帧分配一个流标识符,然后在一个 TCP 连接上独立发送它们。此技术实现了完全双向的请求和响应消息复用。
报头压缩
HTTP/2 协议拥有配套的 HPACK。HPACK 的目的是减少客户端请求与服务器响应之间的标头信息重复所导致的开销。报头压缩的实现方式是,要求客户端和服务器都维护之前看见的标头字段的列表。未来在构建引用了已看见标头列表的消息时可以使用此列表。
服务器推送
服务器推送使服务器能预测客户端请求的资源需求。然后,在完成请求处理之前,它可以将这些资源发送到客户端。
要了解服务器推送的好处,可以考虑一个包含图像和其他依赖项(比如 CSS 和 JavaScript 文件)的网页。客户端发出一个针对该网页的请求。服务器然后分析所请求的页面,确定呈现它所需的资源,并主动将这些资源发送到客户端的缓存。在执行所有这些操作的同时,服务器仍在处理原始网页请求。客户端收到原始网页请求的响应时,它需要的资源已经位于缓存中。
那么 HTTP/2 如何管理服务器推送而不会让客户端过载?针对希望发送的每个资源,服务器会发送一个 PUSH_PROMISE
帧,但客户端可通过发送 RST_STREAM
帧作为响应来拒绝推送(例如,如果浏览器的缓存中已包含该资源)。重要的是所有PUSH_PROMISE
都在响应数据之前发送,所以客户端知道它需要请求哪些资源。