【每日一题NO.78】你了解HTTP2.0的多路复用么?
目录:
多路复用
HTTP2.0的特点:
帧和流
帧(frame)
流(stream)
HTTP请求 发展历程
1、多个 TCP 连接
2、keep-alive
3、管线化
4、多路复用
多路复用
多路复用
就是在一个 TCP 连接中可以存在多条流,也就是可以发送多个请求,代替了原来的序列和阻塞机制,使得同一域名下的所有请求都可以在一个 TCP 链接上完成。因此,TCP的处理效率得到提高,同时也很好的解决了浏览器限制同一域名下的请求数量问题。
在 HTTP2.0
中,有了 二进制分帧 之后,HTTP2.0
不再依赖 TCP 链接去实现多流并行了。
HTTP2.0的特点:
同域名下所有通信都在单个连接上完成,同个域名只需要占用 一个 TCP 连接,使用一个连接并行发送多个请求和响应(多路复用)
单个连接可以承载任意数量的 双向数据流,单个连接上可以并行交错的请求和响应,之间互不干扰
数据流以 消息 的形式发送,而消息又由一个或多个 帧 组成,多个帧之间可以 乱序 发送,因为根据帧首部的流标识可以 重新组装 。每个请求都可以带一个 31bit 的优先值,0 表示最高优先值,数值越大优先级越低
有了这些特点,HTTP2.0对比HTTP1.x具有应用速度更快、开发更简单、部署成本更低[1] 等优点
帧和流
在 HTTP2.0 中,有两个非常重要的概念:帧 和 流
帧(frame)
帧:是HTTP2.0
中数据传输的最小单位。因此帧不仅要细分表达 HTTP1.x
中的各个部分,也优化了 HTTP1.x
表达不好的地方,同时还增加了 HTTP1.x
表达不了的方式。
每一帧都包含几个字段:length
、type
、flags
、stream identifier
、frame playload
等等。
其中 type 代表帧的类型,在 HTTP2 的标准中定义了 10 种类型。
HEADERS frame DATA frame PRIORITY (设置流的优先级) RST_STREAM (终止流) SETTINGs (设置此连接的参数) PUSH_PROMISE (服务器推送) PING (测量RTT) GOAWAY (终止连接) WINDOW_UPDATE (流量控制) CONTINUATION (继续传输头部数据)
在 HTTP2.0 中,它把数据包的两大部分分成了 header frame
和 data frame
,也就是 头部帧 和 数据体帧。
流(stream)
流:存在于连接中的一个虚拟通道。流可以承载双向消息,每个流都有一个唯一的整数 ID。
HTTP2.0
长连接中的数据是不按请求响应顺序发送的,一个完整的请求或响应可能会分成非连续多次发送,有以下几个特点:
双向性:同一个流内,可以同时发送和接收数据
有序性:流中被传输的数据就是二进制帧。帧在流上的被发送与被接收都是按照顺序进行的
并行性:流中的二进制帧都是被并行传输的,无需按照顺序等待
流的创建:流可以被客户端或服务器单方面建立、使用或共享
流的关闭:流也可以被任意一方关闭
HEADERS 帧在 DATA 帧前面
流的 ID 都是奇数,说明是由客户端发起的,这是标准规定的,那么服务端发起的就是偶数啦
HTTP请求 发展历程
从 HTTP0.9
到 HTTP2.0
要发送多个请求,技术上经历了几次发展:多个 TCP 连接
---> keep-alive
---> 管线化
---> 多路复用
,每一次的发展都是为了不断地减少多次创建 TCP 等带来的性能损耗。
1、多个 TCP 连接
在HTTP1.1
之前 没有 keep-alive
的时候, 只能创建多个 TCP 连接来做多次请求。
一次请求完成就会关闭本次的 TCP 连接,下个请求又要重新建立 TCP 连接传输、等完成数据再关闭。
这样反复创建TCP连接都要经过三次握手、四次挥手等,给我们的系统造成了很大的性能损耗。
2、keep-alive
keep-alive
解决问题是:在一定时间内,同一域名多次请求数据,只建立一次 HTTP 请求,其他请求可复用每一次建立的连接通道,来达到提高请求效率的问题。
这里面所说的时间是可以配置的,不管你用的是 Apache
还是 nginx
。
以往,浏览器判断响应数据是否接收完毕,需要看连接是否关闭。
在使用持久连接后就不能这样了,这就要求服务器对持久连接的响应头部一定要返回 content-length
字段,来标识 body
的长度,以供浏览器判断界限。
有时,content-length
的方法并不是很准确,也可以根据 Transfer-Encoding:chunked
头部发送一串一串的数据,最后由长度为 0 的 chunked 标识结束。
keep-alive
存在的问题:
串行的文件传输,文本内容需要一个一个按顺序传输; 同域并行请求限制带来的阻塞。(针对这一点、可以通过资源分别放置到不同域名下来曲线救国)
3、管线化
HTTP 管线化
可以克服同域并行请求限制带来的阻塞:它是建立在持久连接之上,是把所有请求一并发给服务器。
但是服务器需要按照顺序一个一个去响应,而不是等到一个响应回来才能发下一个请求,这样就节省了很多请求到服务器的时间。
不过,HTTP 管线化仍旧有阻塞的问题,若上一响应迟迟不回,后面的响应都会被阻塞到。
4、多路复用
多路复用
代替原来的序列和阻塞机制。所有请求都是通过一个 TCP 连接并发完成。
在这之前所有的传输是基于基础文本的,而多路复用中是基于二进制数据帧的传输、消息、流,所以可以做到乱序的传输。
多路复用对同一域名下所有请求都是基于流,所以不存在同域并行的阻塞。
HTTP1.3
默认开启持久连接,在一个 TCP 连接可以传送多个 HTTP 请求和响应,减少了建立和关闭连接的消耗和延迟。
HTTP/2.0
支持多路复用,这是 HTTP1.x
持久连接的升级版。
优点:
一个TCP连接并发、乱序发送多个请求,服务端则通过帧中的标识知道该帧属于哪个流(请求),通过重新排序还原请求。 允许并发的发起多个请求,每个请求及该请求的响应不需要等待其他的请求或响应,避免了线头阻塞问题。这样某个请求任务耗时严重,不会影响到其它连接的正常执行,极大的提高传输性能。
参考资料
WEB性能(5)--HTTP 2.0介绍: https://zhuanlan.zhihu.com/p/83570662
扩展阅读
所有《每日一题》的 知识大纲索引脑图 整理在此:https://www.yuque.com/dfe_evernote/interview/everyday
你也可以点击文末的 “阅读原文” 快速跳转