Http系列(二) Http2中的多路复用
转自:https://juejin.cn/post/6844903935648497678
简介
多路复用代替原来的序列和阻塞机制,所有就是请求的都是通过一个 TCP 连接并发完成。同时也很好的解决了浏览器限制同一个域名下的请求数量的问题。
在 HTTP/2 中,有了二进制分帧之后,HTTP/2 不再依赖 TCP 链接去实现多流并行了,在 HTTP/2 中:
- 同域名下所有通信都在单个连接上完成,同个域名只需要占用一个 TCP 连接,使用一个连接并行发送多个请求和响应。
- 单个连接可以承载任意数量的双向数据流,单个连接上可以并行交错的请求和响应,之间互不干扰。
- 数据流以消息的形式发送,而消息又由一个或多个帧组成,多个帧之间可以乱序发送,因为根据帧首部的流标识可以重新组装。每个请求都可以带一个 31bit 的优先值,0 表示最高优先级, 数值越大优先级越低。
帧(frame)和流(stream)
在 HTTP/2 中,有两个非常重要的概念:帧(frame)和流(stream)。
帧(frame)
HTTP/2 中数据传输的最小单位,因此帧不仅要细分表达 HTTP/1.x 中的各个部份,也优化了 HTTP/1.x 表达得不好的地方,同时还增加了 HTTP/1.x 表达不了的方式。 每一帧都包含几个字段,有length、type、flags、stream identifier、frame playload等,其中type 代表帧的类型,在 HTTP/2 的标准中定义了 10 种不同的类型,包括上面所说的 HEADERS frame 和 DATA frame。此外还有: PRIORITY
(设置流的优先级) RST_STREAM
(终止流)SETTINGS
(设置此连接的参数) PUSH_PROMISE
(服务器推送) PING
(测量 RTT) GOAWAY
(终止连接)WINDOW_UPDATE
(流量控制) CONTINUATION
(继续传输头部数据)
在 HTTP 2.0 中,它把数据报的两大部分分成了 header frame 和 data frame。也就是头部帧和数据体帧。
流(stream)
流: 存在于连接中的一个虚拟通道。流可以承载双向消息,每个流都有一个唯一的整数 ID。 HTTP/2 长连接中的数据包是不按请求-响应顺序发送的,一个完整的请求或响应(称一个数据流 stream,每个数据流都有一个独一无二的编号)可能会分成非连续多次发送。它具有如下几个特点:
- 双向性:同一个流内,可同时发送和接受数据。
- 有序性:流中被传输的数据就是二进制帧 。帧在流上的被发送与被接收都是按照顺序进行的。
- 并行性:流中的 二进制帧 都是被并行传输的,无需按顺序等待。
- 流的创建:流可以被客户端或服务器单方面建立, 使用或共享。
- 流的关闭:流也可以被任意一方关闭。
- HEADERS 帧在 DATA 帧前面。
- 流的 ID 都是奇数,说明是由客户端发起的,这是标准规定的,那么服务端发起的就是偶数了。
发展历程
从 Http/0.9 到 Http/2 要发送多个请求,从多个 Tcp 连接=>keep-alive=>管道化=>多路复用不断的减少多次创建 Tcp 等等带来的性能损耗。
多个 Tcp 连接
在最早的时候没有keep-alive
只能创建多个Tcp
连接来做多次请求。多次 http 请求效果如下图所示:
一次请求完成就会关闭本次的 Tcp 连接,下个请求又要从新建立 Tcp 连接传输完成数据再关闭,造成很大的性能损耗。
Keep-Alive
Keep-Alive
解决的核心问题是: 一定时间内,同一域名多次请求数据,只建立一次 HTTP 请求,其他请求可复用每一次建立的连接通道,以达到提高请求效率的问题。这里面所说的一定时间是可以配置的,不管你用的是Apache
还是nginx
。 以往,浏览器判断响应数据是否接收完毕,是看连接是否关闭。在使用持久连接后,就不能这样了,这就要求服务器对持久连接的响应头部一定要返回content-length
标识body的
长度,供浏览器判断界限。有时,content-length
的方法并不是太准确,也可以使用 Transfer-Encoding: chunked
头部发送一串一串的数据,最后由长度为 0 的chunked
标识结束。 多次 http 请求效果如下图所示:
上图:设置 Connection:Keep-Alive,保持连接在一段时间内不断开。
Keep-Alive
还是存在如下问题:
- 串行的文件传输。
- 同域并行请求限制带来的阻塞(6~8)个
管线化
HTTP 管线化可以克服同域并行请求限制带来的阻塞,它是建立在持久连接之上,是把所有请求一并发给服务器,但是服务器需要按照顺序一个一个响应,而不是等到一个响应回来才能发下一个请求,这样就节省了很多请求到服务器的时间。不过,HTTP 管线化仍旧有阻塞的问题,若上一响应迟迟不回,后面的响应都会被阻塞到。
上图:HTTPpipelining:建立多个连接
多路复用
多路复用代替原来的序列和阻塞机制。所有就是请求的都是通过一个 TCP 连接并发完成。因为在多路复用之前所有的传输是基于基础文本的,在多路复用中是基于二进制数据帧的传输、消息、流,所以可以做到乱序的传输。多路复用对同一域名下所有请求都是基于流,所以不存在同域并行的阻塞。多次请求如下图:
上图:多路复用
总结
在 HTTP/2 中,有两个非常重要的概念,分别是帧(frame)和流(stream)。
帧代表着最小的数据单位,每个帧会标识出该帧属于哪个流,流也就是多个帧组成的数据流。
HTTP2 采用二进制数据帧传输,取代了 HTTP1.x 的文本格式,二进制格式解析更高效。
多路复用代替了 HTTP1.x 的序列和阻塞机制,所有的相同域名请求都通过同一个 TCP 连接并发完成。同一 Tcp 中可以发送多个请求,对端可以通过帧中的标识知道属于哪个请求。通过这个技术,可以避免 HTTP 旧版本中的队头阻塞问题,极大的提高传输性能。
参考
作者:blackdous
链接:https://juejin.cn/post/6844903935648497678
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律