网页为什么越来越快?一文看懂 HTTP 的三次进化 _

📅 2026/6/30 6:30:53
网页为什么越来越快?一文看懂 HTTP 的三次进化 _
HTTP/1.1的改进和不足HTTP/1.1 相比 HTTP/1.0 性能上的改进使用长连接的方式改善了 HTTP/1.0 短连接造成的性能开销。支持管道pipeline网络传输只要第一个请求发出去了不必等其回来就可以发第二个请求出去可以减少整体的响应时间HTTP/1.1的不足请求 / 响应头部Header纯文本格式占用较大首部信息越多延迟越大。每次互相发送相同的首部造成的浪费较多服务器是按请求的顺序响应的如果服务器响应慢会招致客户端一直请求不到数据也就是队头阻塞没有请求优先级控制请求只能从客户端开始服务器只能被动响应。HTTP/2的优化HTTP/2 协议是基于 HTTPS 的所以 HTTP/2 的安全性也是有保障的HTTP/2 相比 HTTP/1.1 性能上的改进头部压缩二进制格式并发传输解决HTTP对头阻塞问题服务器主动推送资源头部压缩HTTP/2 会压缩头Header如果同时发出多个请求他们的头是一样的或是相似的那么协议会帮你消除重复的部分。这是所谓的 HPACK 算法在客户端和服务器同时维护一张头信息表所有字段都会存入这个表生成一个索引号以后就不发送同样字段了只发送索引号这样就提高速度了。二进制格式HTTP/2 不再像 HTTP/1.1 里的纯文本形式的报文而是全面采用了二进制格式头信息和数据体都是二进制并且统称为帧frame头信息帧Headers Frame和数据帧Data Frame。比如状态码 200 在 HTTP/1.1 是用 200 三个字符来表示共用了 3 个字节。HTTP2只需要用1个字节就能表示计算机只懂二进制那么收到报文后无需再将明文的报文转成二进制而是直接解析二进制报文这增加了数据传输的效率。比如状态码 200 在 HTTP/1.1 是用 200 三个字符来表示二进制00110010 00110000 00110000共用了 3 个字节。在 HTTP/2 对于状态码 200 的二进制编码是 10001000只用了 1 字节就能表示相比于 HTTP/1.1 节省了 2 个字节如下图如上图Header: :status: 200 OK 的编码内容为1000 1000最前面的 1 标识该 Header 是静态表中已经存在的 KV。在静态表里“:status: 200 ok” 静态表编码是 8二进制即是 1000。并发传输同一个连接中HTTP 完成一个事务就是一次请求与响应才能处理下一个事务也就是说在发出请求等待响应的过程中是没办法做其他事情的如果响应迟迟不来那么后续的请求是无法发送的也造成了队头阻塞的问题。所以HTTP/2 引出了 Stream 概念多个 Stream 复用在一条 TCP 连接。从上图可以看到1 个 TCP 连接包含多个 StreamStream 里可以包含 1 个或多个 MessageMessage 对应 HTTP/1 中的请求或响应由 HTTP 头部和包体构成。Message 里包含一条或者多个 FrameFrame 是 HTTP/2 最小单位以二进制压缩格式存放 HTTP/1 中的内容头部和包体)。针对不同的 HTTP 请求用独一无二的 Stream ID 来区分接收端可以通过 Stream ID 有序组装成 HTTP 消息不同 Stream 的帧是可以乱序发送的因此可以并发不同的 Stream 也就是 HTTP/2 可以并行交错地发送请求和响应。比如下图服务端并行交错地发送了两个响应 Stream 1 和 Stream 3这两个 Stream 都是跑在一个 TCP 连接上客户端收到后会根据相同的 Stream ID 有序组装成 HTTP 消息。服务器推送HTTP/2服务端可以主动向客户端发送消息。客户端和服务器双方都可以建立 Stream Stream ID 也是有区别的客户端建立的 Stream 必须是奇数号而服务器建立的 Stream 必须是偶数号。比如下图Stream 1 是客户端向服务端请求的资源属于客户端建立的 Stream所以该 Stream 的 ID 是奇数数字 1Stream 2 和 4 都是服务端主动向客户端推送的资源属于服务端建立的 Stream所以这两个 Stream 的 ID 是偶数数字 2 和 4。比如客户端通过 HTTP/1.1 请求从服务器那获取到了 HTML 文件而 HTML 可能还需要依赖 CSS 来渲染页面这时客户端还要再发起获取 CSS 文件的请求需要两次消息往返如下图左边部分如上图右边部分在 HTTP/2 中客户端在访问 HTML 时服务器可以直接主动推送 CSS 文件减少了消息传递的次数。HTTP2的不足HTTP/2 通过 Stream 的并发能力解决了 HTTP/1 队头阻塞的问题但是 HTTP/2 还是存在“队头阻塞”的问题只不过问题不是在 HTTP 这一层面而是在 TCP 这一层。HTTP/2 是基于 TCP 协议来传输数据的TCP 是字节流协议TCP 层必须保证收到的字节数据是完整且连续的这样内核才会将缓冲区里的数据返回给 HTTP 应用那么当「前 1 个字节数据」没有到达时后收到的字节数据只能存放在内核缓冲区里只有等到这 1 个字节数据到达时HTTP/2 应用层才能从内核中拿到数据这就是 HTTP/2 队头阻塞问题。HTTP3为了解决HTTP2中由于TCP造成的队头阻塞问题HTTP/3 把 HTTP 下层的 TCP 协议改成了 UDP