【每日一题NO.78】你了解HTTP2.0的多路复用么?

共 2883字,需浏览 6分钟

 ·

2021-11-09 00:55



目录:

  • 多路复用

  • HTTP2.0的特点:

  • 帧和流

    • 帧(frame)

    • 流(stream)

  • HTTP请求 发展历程

    • 1、多个 TCP 连接

    • 2、keep-alive

    • 3、管线化

    • 4、多路复用


多路复用

多路复用就是在一个 TCP 连接中可以存在多条流,也就是可以发送多个请求,代替了原来的序列和阻塞机制,使得同一域名下的所有请求都可以在一个 TCP 链接上完成。因此,TCP的处理效率得到提高,同时也很好的解决了浏览器限制同一域名下的请求数量问题。

HTTP2.0 中,有了 二进制分帧 之后,HTTP2.0 不再依赖 TCP 链接去实现多流并行了。

HTTP2.0的特点:

  1. 同域名下所有通信都在单个连接上完成,同个域名只需要占用 一个 TCP 连接,使用一个连接并行发送多个请求和响应(多路复用)

  2. 单个连接可以承载任意数量的 双向数据流,单个连接上可以并行交错的请求和响应,之间互不干扰

  3. 数据流以 消息 的形式发送,而消息又由一个或多个 组成,多个帧之间可以 乱序 发送,因为根据帧首部的流标识可以 重新组装 。每个请求都可以带一个 31bit 的优先值,0 表示最高优先值,数值越大优先级越低


有了这些特点,HTTP2.0对比HTTP1.x具有应用速度更快、开发更简单、部署成本更低[1] 等优点

帧和流

在 HTTP2.0 中,有两个非常重要的概念:

帧(frame)

帧:是HTTP2.0 中数据传输的最小单位。因此帧不仅要细分表达 HTTP1.x 中的各个部分,也优化了 HTTP1.x 表达不好的地方,同时还增加了 HTTP1.x 表达不了的方式。

每一帧都包含几个字段:lengthtypeflagsstream identifierframe playload等等。

其中 type 代表帧的类型,在 HTTP2 的标准中定义了 10 种类型。

  1. HEADERS frame
  2. DATA frame
  3. PRIORITY (设置流的优先级)
  4. RST_STREAM (终止流)
  5. SETTINGs (设置此连接的参数)
  6. PUSH_PROMISE (服务器推送)
  7. PING (测量RTT)
  8. GOAWAY (终止连接)
  9. WINDOW_UPDATE (流量控制)
  10. CONTINUATION (继续传输头部数据)

在 HTTP2.0 中,它把数据包的两大部分分成了 header framedata frame,也就是 头部帧数据体帧

流(stream)

流:存在于连接中的一个虚拟通道。流可以承载双向消息,每个流都有一个唯一的整数 ID。

HTTP2.0 长连接中的数据是不按请求响应顺序发送的,一个完整的请求或响应可能会分成非连续多次发送,有以下几个特点:

  • 双向性:同一个流内,可以同时发送和接收数据

  • 有序性:流中被传输的数据就是二进制帧。帧在流上的被发送与被接收都是按照顺序进行的

  • 并行性:流中的二进制帧都是被并行传输的,无需按照顺序等待

  • 流的创建:流可以被客户端或服务器单方面建立、使用或共享

  • 流的关闭:流也可以被任意一方关闭

  • HEADERS 帧在 DATA 帧前面

  • 流的 ID 都是奇数,说明是由客户端发起的,这是标准规定的,那么服务端发起的就是偶数啦

HTTP请求 发展历程

HTTP0.9HTTP2.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 持久连接的升级版。

优点:

  1. 一个TCP连接并发、乱序发送多个请求,服务端则通过帧中的标识知道该帧属于哪个流(请求),通过重新排序还原请求。
  2. 允许并发的发起多个请求,每个请求及该请求的响应不需要等待其他的请求或响应,避免了线头阻塞问题。这样某个请求任务耗时严重,不会影响到其它连接的正常执行,极大的提高传输性能。

参考资料

[1]

WEB性能(5)--HTTP 2.0介绍: https://zhuanlan.zhihu.com/p/83570662


  扩展阅读


所有《每日一题》的 知识大纲索引脑图 整理在此:https://www.yuque.com/dfe_evernote/interview/everyday
你也可以点击文末的 “阅读原文” 快速跳转


END
愿你历尽千帆,归来仍是少年。


浏览 120
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报