Http / 2 知识点学习
HTTP / 1 的问题
队头阻塞
浏览器很少只从一个域名获取一份资源。大多数时候,它希望能同时获取许多资源。设想这样一个网站,它把所有图片放在单个特定域名下。HTTP/1 并未提供机制来同时请求这些资源。如果仅仅使用一个连接,它需要发起请求、等待响应,之后才能发起下一个请求。 这也是因为tcp协议是面向连接的协议
h1 有个特性叫 管道化(pipelining)
,允许一次发送一组连续的请求,而不用等待应答返回。这样可以避免连接延迟。但是该特性只能按照发送顺序依次接收响应。而且,管道化备受互操作性和部署的各种问题的困扰,基本没有实用价值。
在请求应答过程中,如果出现任何状况,剩下所有的工作都会被阻塞在那次请求应答之后。这就是 队头阻塞(Head-of-line blocking或缩写为HOL blocking),它会阻碍网络传输和 Web 页面渲染,直至失去响应。
为了防止这种问题,现代浏览器会针对单个域名开启 6 个连接,通过各个连接分别发送请求。它实现了某种程度上的并行,但是每个连接仍会受到 队头阻塞的影响。另外,这也没有高效利用有限的设备资源。
低效的TCP利用
这就涉及到tcp协议里的拥塞控制。。
如今的 Web 页面平均大小约 2MB,包括 HTML 和所有依赖的资源。在理想情况下, 这需要大约 9 次往返请求来传输完整个页面。除此之外,浏览器一般会针对同一个域名开启 6 个并发连接,每个连接都免不了拥塞窗口调节。
臃肿的消息首部
虽然 h1 提供了压缩被请求内容的机制,但是消息首部却无法压缩。消息首部可不能忽略, 尽管它比响应资源小很多,但它可能占据请求的绝大部分(有时候可能是全部)。如果算 上 cookie,有个几千字节就很正常了。
受限的优先级设置
如果浏览器针对指定域名开启了多个 socket(每个都会受队头阻塞问题的困扰),开始请求资源,这时候浏览器能指定优先级的方式是有限的:要么发起请求,要么不发起。
然而 Web 页面上某些资源会比另一些更重要,这必然会加重资源的 排队效应。这是因为浏览器为了先请求优先级高的资源,会推迟请求其他资源。
但是优先级高的资源获取之后,在处理的过程中,浏览器并不会发起新的资源请求,所以服务器无法利用这段时间发送优先级低的资源,总的页面下载时间因此延长了。还会出现这样的情况:一个高优先级资源被浏览器发现,但是受制于浏览器处理的方式,它被排在了一个正在获取的低优先级资源之后。
归结上述问题的解决方案是
- http需要在基于tcp协议的基础上,实现在一个tcp连接里处理多个http请求和响应
- 压缩头部
解决方案是提出了
- 流,消息,帧的概念来实现多路复用
- 采用类似于哈夫曼编码的思路来进行头部压缩
队头阻塞: 使用帧,将多个http拆开从而可以在一个tcp连接里处理多个http请求和响应,其次与http/1 的按照字符来截取首部相比,在处理上可以知道开多大的内存来处理一段消息
低效的TCP利用: 使用帧,将多个http拆开从而可以在一个tcp连接里处理多个http请求和响应,自然就避免了低效的tcp利用。
臃肿的消息首部:通过压缩首部来实现的
- 服务端客户端维护两张表,一是动态表,来存发过的头,这样当第二次要发相同的头部时,直接发表中该头部对应字段就ok了,其次是静态表,存储常用的键值对,比如request:get啥的
- 对发过的头部进一步使用哈夫曼压缩
推荐阅读 : HTTP/2 新特性总结