HTTP\1.1 为提高网络效率做了大量的优化,比较核心的有:
- 增加了持久连接
- 浏览器为每个域名最多同时维护 6 个 TCP 连接
- 使用 CDN 的实现域名分片机制
HTTP\1.1 做的这些优化取得了一定的效果,但是 HTTP\1.1 对带宽的利用率却不是很理想,这也是 HTTP\1.1 的一个核心问题
带宽是指每秒最大能发送或者接收的字节数。我们把每秒能发送的最大字节数成为 上行带宽,每秒能够接收的最大字节数称为 下行带宽
之所以会出现这个问题,是由以下原因导致的:
(一)TCP 启动慢
慢启动是 TCP 为了减少网络拥塞的一个策略
一但一个 TCP 连接建立之后,就进入了发送数据的状态,刚开始 TCP 协议会采用一个非常慢的速度去发送数据,然后慢慢加快发送数据的速度。直到发送的速度达到一个理想的状态
在页面中本来有一些关键资源,这些资源本来在 TCP 连接建立好之后就要请求的,但是由于慢启动,请求这些资源的时间就会多很多,这样就推迟了宝贵的首次渲染的时间
(二)竞争带宽
如果系统建立多条 TCP,当带宽充足,每条连接发送或者接收的速度会慢慢增加,一旦带宽不足,这些 TCP 的连接又会减慢发送或者接收的速度
而速度一旦减慢,一些关键资源的下载速度也会减慢,进而影响页面的渲染
(三)HTTP/1.1 的队头阻塞问题
详见另一篇博客 HTTP\1.1
可以看出,这些问题大部分都是 TCP 的问题,但是又不能换掉 HTTP,所以,只能规避这些问题
HTTP\2 的多路复用
关于慢启动和 TCP 之间连接竞争的关系,HTTP\2 的解决办法是一个域名只使用一个 TCP 长连接,这样整个页面只需要经过一次慢启动,同时也避免了多个 TCP 连接竞争带宽的问题
关于队头阻塞,HTTP\2 实现了资源的并行请求,也就是,任何时候都可以将请求发送给服务器,而不需要等待掐面的请求完成
HTTP\2 的解决方案,可参考下图:
HTTP\2 的多路复用
多路复用是如何实现的
HTTP\2 通过添加了一个 二进制分帧层 来实现 多路复用技术
HTTP\2 的请求和接收过程
- 浏览器请求数据
- 数据经过二进制分帧层处理之后,会被转换为一个个带有请求 ID 编号的帧 通过协议栈发送给服务器
- 服务器接收所有的帧,将相同的 ID 合并为一条完整的请求信息
- 服务器处理请求,将处理的 响应行,响应头,响应体分别发送至二进制分帧层
- 同样的,二进制分帧层将这些响应转换为一个个带有 ID 编号的帧,经过协议栈发送给浏览器
- 浏览器接收到响应帧后,会根据 ID 编号将帧的数据提交给对应的请求
HTTP\2 的其他特性
可以设置请求的优先级
在发送请求时,可以标上该请求的优先级,这样服务器收到请求后,会优先处理优先级高的数据
服务器推送
当用户请求一个 HTML 页面之后,服务器知道该 HTML 页面会引用哪几个 JS 文件 CSS 文件,那么在接收到 HTML 请求之后,附带将要使用的 CSS 文件和 JS 文件一并发送给浏览器
头部压缩
可以对请求头和响应头进行压缩
网友评论