HTTP系列-HTTP/2篇

2022-12-20·5min
type
Post
summary
status
Published
category
tags
slug
date
Dec 20, 2022
password
icon
📌
HTTP有两个主要的缺点,分别是安全性不足和性能不佳。
安全性不足的缺点通过引入SSL/TLS得到了修补,但在性能的提升上却乏善可陈。于是在HTTPS逐渐成熟之后,HTTP就朝着性能方面开始走向了进化之路。

HTTP/2

由于不堪忍受HTTP/1.1的性能问题,Google率先打响了协议“革命”的第一枪,发明了SPDY协议,并应用于自家的浏览器Chrome。随后标准化组织以SPDY为基础推出了HTTP/2,在性能改善方面有了一个大的飞跃。

兼容性

由于HTTP/1.1已经推出很久了,有无数互联网设备正在使用。所以HTTP/2的协议修改必须要小心谨慎,兼容性是首要考虑的目标,否则就会影响到现有的互联网资产。
为了保持功能上的兼容,HTTP/1.1中的请求方法、状态码、URI和头部字段等都保留不变,这就意味着基于HTTP/1.1的应用不用做任何修改就可以无缝切换到HTTP/2。
并且,与HTTPS不同,HTTP/2没有在URI里引入新的协议名,仍然用“HTTP“表示明文协议,”HTTPS“表示密文协议。这就意味着浏览器或服务器可以自动的升级或降级协议,这个过程对于用户是无感的,实现平滑过渡。

头部压缩

HTTP/1.1可以在头部字段中使用“Content-Encoding”来指定Body的编码方式,通过压缩来减少数据传输量,节约带宽。
但对于Header部分,却没有相应的优化手段。报文Header一般会有一些固定的头字段,多达几百字节甚至上千字节,但Body部分却经常只有几十字节(比如GET请求、204/301/304 响应),并且很多请求响应报文里有不少字段值都是重复的,大量带宽浪费在了这些冗余的数据上。
HTTP/2针对这个问题推出了“头部压缩”,开发了专门的“HPACK”算法来压缩头部数据。
“HPACK”与gzip等压缩算法不同,它是一个“有状态”的算法,需要客户端和服务端各自维护一份“索引表”,压缩和解压就是查表和更新表的操作。
为了方便管理和压缩,HTTP/2取消了起始行的概念,去掉了没什么用的协议版本号和状态短语。将起始行里的状态码、URI、请求方法统一转换为了头字段的形式,并在它们的名字前加一个“:”,用来区分其他“真头字段”。
将报文头全都变成“key-value”形式的字段之后,HTTP/2为一些最常用的头字段定义了一个只读的“静态表”,只要通过下标查询就能知道字段名和对应的值。例如数字“2”代表“GET”,数字“8”代表状态码 200。
对于一些只有key没有value,或者自定义头字段,HTTP/2定义了一个“动态表”,它添加在静态表后面,结构相同,但会在编码解码的时候随时更新。
随着客户端和服务端互相发送的报文越来越多,两边的”索引表“也会越来越丰富,发送时只需要发送一两个字节的索引即可,大大节约了带宽和冗余的数据。

二进制帧与流

HTTP/2报文废弃了纯文本格式,全面采用二进制格式。二进制格式虽然对人不友好,调试起来困难,但是却大大方便了计算机的解析,做到了内部提效。
HTTP/2吸收了部分TCP协议的特性,把原来“Header”+“Body”的消息“打散”为数个小片的二进制帧(Frame),用“HEADERS”帧存放头数据、“DATA”帧存放实体数据。
HTTP/2 的帧结构类似TCP的段或者TLS里的记录,也是在实际传输的数据前加上自己的头数据。
这个二进制头分为四个部分:帧长度、帧类型、帧标志和流标识符。
  1. 帧长度:3个字节,HTTP/2的帧通常不超过16K,最大是16M。
  1. 帧类型:分成数据帧和控制帧两类,HEADERS帧和DATA帧属于数据帧,存放的是HTTP报文,而SETTINGS、PING、PRIORITY等则是用来管理流的控制帧。
  1. 帧标志:可以保存8个标志位,携带简单的控制信息。常用的标志位有END_HEADERS表示头数据结束。END_STREAM表示单方向数据发送结束。
  1. 流标识符:标识帧所属的“流”,接收方使用它就可以从乱序的帧里识别出具有相同流ID的帧序列,按顺序组装起来就实现了虚拟的“流”。
与二进制帧相关的还有一个“流”的概念,可以理解为:一个流就等同于一个HTTP/1.1里的”请求-应答“。具有相同流ID的二进制帧会在被接受后按顺序组装成为请求报文和响应报文。
HTTP/2可以在一个TCP连接上发送很多具有不同流ID的二进制帧,也就是搭建多个流。在流的层面上看,消息都是一些有序的“帧”序列,但在TCP连接层面来看,只是一堆无序的二进制帧,这就是常说的多路复用,多个往返通信都复用一个连接来处理。
这样多个请求/响应之间没有了顺序关系,不需要排队等待,基本上解决了“队头阻塞”的问题,降低了延迟,大幅度提高了连接的利用率。
并且为了能够更好利用连接,HTTP/2还能通过控制帧来管理“流”,实现优先级管理和流量控制。

服务器推送Server Push

HTTP/2在一定程度上改变了传统的“请求 - 应答”工作模式,服务器不再是完全被动地响应请求,也可以新建“流”主动向客户端发送消息。比如,在浏览器刚请求HTML的时候就提前把可能会用到的JS、CSS文件发给客户端,减少等待的延迟。

强化安全

出于兼容的考虑,HTTP/2延续了明文的特点,不强制使用加密通信。
但由于HTTPS已经是大势所趋,并且主流的浏览器公开宣布只支持加密的HTTP/2,所以事实上的HTTP/2是加密的,也就是说互联网上所能见到的HTTP/2都是使用https协议名,跑在TLS上面。
HTTP/2对于TLS的版本也有要求,只支持TLS1.2及以上的版本。
 
> cd ..