不得不了解的http2/3

280 阅读7分钟

什么是http2

HTTP2是HTTP协议自1999年HTTP 1.1发布后的首个更新,主要基于SPDY协议。

当 HTTP 到 HTTPS 后,在安全上已经有保障了,但本来性能一般般的 HTTP 又加上一层处理,变得更加重,在性能上有所损耗,那么成熟后的 HTTPS 已经在性能暴露了问题,那么只能对其性能方面下手,所以就出现后续的 HTTP2。

保持功能上的兼容,完全兼容 HTTP1,基于 HTTP 的上层应用也不需要做任何修改,可以无缝转换到 HTTP2。

特别要说的是,与 HTTPS 不同,HTTP2 没有在 URI 里引入新的协议名,仍然用“http”表示明文协议,用“https”表示加密协议。

可以让浏览器或者服务器去自动升级或降级协议,免去了选择的麻烦,让用户在上网的时候都意识不到协议的切换,实现平滑过渡。 但 HTTP2 的内容对于 HTTP1 有着“天翻地覆”的改造.

开启http2

开启http2一般使用nginx只要listen配置http2与ssl即可,然后ssl需要配置证书。

截屏2022-02-18 下午11.07.35.png

开启后效果 截屏2022-02-18 下午11.09.52.png

为什么HTTP后续没有出现过小版本

以前的“1.0”“1.1”造成了很多的混乱和误解,让人在实际的使用中难以区分差异,所以就决定 HTTP 协议不再使用小版本号,只使用大版本号,从今往后 HTTP 协议不会出现 HTTP/2.0、2.1,只会有“HTTP/2”“HTTP/3”。

这样就可以明确无误地辨别出协议版本的“跃进程度”,让协议在一段较长的时期内保持稳定,每当发布新版本的 HTTP 协议都会有本质的不同,绝不会有“零敲碎打”的小改良。

http2带来的改变

二进制分帧

帧: HTTP/2 数据通信的最小单位消息:指 HTTP/2 中逻辑上的 HTTP 消息。例如请求和响应等,消息由一个或多个帧组成。

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

相对于 HTTP/1 里纯文本形式的报文,HTTP/2 采用二进制格式

二进制里只有“0”和“1”,可以严格规定字段大小、顺序、标志位等格式,“对就是对,错就是错”,解析起来没有歧义,实现简单,而且体积小、速度快,做到“内部提效”。

HTTP/2 为此定义了一个“流”的概念,它是二进制帧的双向传输序列,同一个消息往返的帧会分配一个唯一的流 ID。你可以把它想象成是一个虚拟的“数据流”,在里面流动的是一串有先后顺序的数据帧,这些数据帧按照次序组装起来就是 HTTP/1 里的请求报文和响应报文。

因为“流”是虚拟的,实际上并不存在,所以 HTTP/2 就可以在一个 TCP 连接上用“流”同时发送多个“碎片化”的消息,这就是常说的“多路复用”——多个往返通信都复用一个连接来处理。

在“流”的层面上看,消息是一些有序的“帧”序列,而在“连接”的层面上看,消息却是乱序收发的“帧”。多个请求 / 响应之间没有了顺序关系,不需要排队等待,也就不会再出现“队头阻塞”问题,降低了延迟,大幅度提高了连接的利用率。

多路复用

多路复用多个请求没有顺序,而长连接多个请求必须排队,就会队头阻塞。

http 协议要求请求-响应必须一来一回,上一个请求没有处理完,下一个请求是不能发出去的。一个 tcp 连接上的 http 请求必然是串行。

管道模式可以顺序发出多个请求,但响应也必须顺序响应。这些都是 http/1.1 里规定的。

再对比 http/2,一个 tcp 连接里有多个流,每个流就是一个请求,所以多个请求可以并发,“复用”在了一个连接里。

服务器推送

服务端可以在发送页面HTML时主动推送其它资源,而不用等到浏览器解析到相应位置,发起请求再响应。例如服务端可以主动把JS和CSS文件推送给客户端,而不需要客户端解析HTML时再发送这些请求。

服务端可以主动推送,客户端也有权利选择是否接收。如果服务端推送的资源已经被浏览器缓存过,浏览器可以通过发送RST_STREAM帧来拒收。主动推送也遵守同源策略,服务器不会随便推送第三方资源给客户端。

下面是配置的方式,还可以使用Link的预加载方式,具体可以自行查找资料 截屏2022-02-18 下午11.22.48.png

截屏2022-02-18 下午11.20.31.png

头部压缩

HTTP每一次通信都会携带一组头部,用于描述这次通信的的资源、浏览器属性、cookie等。

由于 HTTP1 没有针对头部的优化手段,头部还有优化的空间,不过 HTTP/2 并没有使用传统的压缩算法,而是开发了专门的“HPACK”算法,在客户端和服务器两端建立“字典”,用索引号表示重复的字符串,那么下一次请求则只需要发送差异数据,这样可以减少冗余数据,降低开销。还釆用哈夫曼编码来压缩整数和字符串,可以达到 50%~90% 的高压缩率。

http/3

HTTP/2 虽然使用“帧”“流”“多路复用”,没有了“队头阻塞”,但这些手段都是在应用层里,而在下层,也就是 TCP 协议里,还是会发生“队头阻塞”。

由于这种“队头阻塞”是 TCP 协议固有的,所以 HTTP/2 即使设计出再多的“花样”也无法解决。

Google 在推 SPDY 的时候就已经意识到了这个问题,于是就又发明了一个新的“QUIC”协议,让 HTTP 跑在 QUIC 上而不是 TCP 上。

QUIC 选择使用 UDP 为基础,因为 UDP 是无序的,包之间没有依赖关系,所以就从根本上解决了“队头阻塞”。

QUIC 在 UDP 上把 TCP 的那一套连接管理、拥塞窗口、流量控制等“搬”了过来,“去其糟粕,取其精华”,打造出了一个全新的可靠传输协议,可以认为是“新时代的 TCP”。

QUIC 基于 UDP,而 UDP 是“无连接”的,根本就不需要“握手”和“挥手”,所以天生就要比 TCP 快。

总结

http/1 请求-应答都是有序并且每次都需要建立连接,而后 http/1.1 出现长连接与管道模式可以让连接维持不断并且多个请求有序的同时发送等待响应,但响应部分还是需要排队等待一个一个返回,而 HTTP/2 出现就是主要是压缩头部信息与数据格式从文本改为二进制,让数据的体积变小,而且让应用层上连接的有序变为无序,解决了连接层上队头阻塞,而 HTTP/3 的出现主要解决了 TCP 的传输层上队头阻塞问题,把 TCP 换为 UDP 无序的、包之间没有依赖更快传输协议,并改造为可靠的传输协议。

而使用 HTTP2/3 就没有必要使用精灵图、多个请求合并的操作,因为这些技术出现都是为了解决对头阻塞导致的请求响应慢的问题,而且还不能很好的使用 HTTP 的缓存机制,在 HTTP2/3 中这些技术反而会拖慢请求响应的速度。