http协议是互联网的基础协议,也是前端开发的必备知识,本文介绍http协议的历史演变和设计思路
http/0.9
该版本1991发布,极其简单,只有一个命令GET
GET /index.html
协议规定,服务器只能返回html格式的字符串,不能返回别的格式,服务端发送完毕就关闭TCP连接
缺点
- 只能发送html
- 命令单一
http/1.0
1996年5月发布,内容大大增加
- 任何格式的内容都可以发送(文字,视频,图片,二进制文件皆支持)
- 支持了POST和HEAD命令,丰富了浏览器和服务器的交互手段
- http请求和回应的格式也变了,除了数据部分,每次通信都必须包含头信息(header),用来描述一些元数据
缺点
- 每个TCP只能发一次请求,发送数据完毕,连接就断开,如果还想请求别的数据,就必须新建一条TCP连接
http/1.1
1997年1月,http/1.1版本发布,升级了两个功能
- 持久连接 长连接,tcp连接之后可以发送多个请求
- 管道机制 同一个TCP连接里边,客户端可以同时发送多个请求。这样就进一步改进了http的效率。 eg,客户端同时请求两个资源,以前的做法是,在同一个TCP连接里边,先发送A请求,等待服务器做出响应,在发送B请求。管道机制允许浏览器同时发出A请求和B请求,但是服务器还是按照顺序,先回应A请求,完成后再回应B请求
缺点
虽然1.1版本允许复用tcp连接,而且可以同时发送多个请求,但是服务器只能处理完一个回应,才会进行下一个回应,要是前边的回应慢,就会有许多请求排队等着,这称为“队头堵塞”
处理方案
- 减少请求数(合并js,合并css,雪碧图)
- 同时多开持久连接【资源放在多个域名下(因为一个域名最多可以有6个tcp连接)】
http/2
2009年,谷歌公开了自行研制的SPDY协议,主要解决http/1.1队头堵塞的问题,之后作为http2的基础 2015年,http2正式发布
目标: 专注于性能,最大的目标是在用户和网站间只用一个连接【之前是一个域名可以有6个tcp连接,现在只用一个tcp连接】 这样就没有握手挥手的问题,也没有慢启动的问题
核心的升级点
-
二进制协议
http/2将请求和响应数量分割为更小的帧,并且他们采用二进制编码,这样可以乱序传播,浏览器接收到所有的片段之后,按照片所带的序号,整合盛一个完整的数据包, 之前是用的文本格式,各部分之间以换行符分隔,所以不能分开传输
-
多路复用
所有的请求都,都复用一个tcp连接 之前是同一个域名可以有6个tcp连接,现在只用一个连接
-
头压缩
在同一个HTTP页面中,很多资源的Header是高度相似的,这时会在服务器和客户端,各保存一份映射表,这样就可以通过发送序号来大大压缩长度,比如序号2,用来表示:method: GET,经过头压缩的字段,前边会有一个冒号
-
服务器推送
Http2还在一定程度上改变了传统的“请求-应答”的工作模式,服务器不再是完全被动的响应请求,也可以新建“流”主动的向客户端发送消息,比如我们现在收到的很多消息推送
缺点:
-
虽然解决了应用层的队头阻塞,但是并没有解决传输层的队头阻塞
只要底层是基于tcp,就要有确认的过程,在应用层,虽然所有的数据包被切成了一片一片,而且这些片是可以乱序传输的;但是在tcp层,还是要将上一层切开的片,整合成一个数据包,依然需要按照顺序去响应,依然遵循“丢包重传”的机制,所以tcp层的队头堵塞问题是依然存在的,而且更严重,因为http/2只有一个tcp连接,一旦堵塞了,这个tcp上的所有请求都被堵塞(http/1.1可以新建tcp连接),基于这个原因http/3就诞生了
-
因为是基于tcp,所以建立连接还是会经过三次握手,四次挥手(建立连接需要花费很多时间)
http/3
2022年6月,IETF(互联网工程任务小组)正式发布了http/3
http/3的核心改变是: 传输层使用的是UDP协议,而不是tcp协议,如下图
http/3使用的是QUIC协议,它实际上是在UDP的基础上重写了TCP的功能,更高效的实现了TCP的核心功能
因为http/3是基于UDP,所以自动解决了下面两个问题
-
建立连接时的三次握手,四次挥手
那它是怎么建立连接的呢,简单来说,是客户端发送请求,服务端返回它的配置,客户端之后的请求带着服务端给的令牌请求信息
-
队头堵塞(udp是无序的,无需等待)
那它怎么保证数据的可靠性: http数据包中加了一个packet header Packet header 实现了可靠的连接,当UDP报文丢失后,通过Packet header中的Packet Number实现报文重传 Packet Number是每个报文独一🈚无二的序号,基于它可以实现报文的精准重发