HTTP1.0
无法复用连接,HTTP1.0为每个请求单独新开一个TCP连接。
由于每个请求都是独立的连接,因此会带来下面的问题:
- 连接的建立和销毁都会占用服务器和客户端的资源,造成内存资源的浪费
- 连接的建立和销毁都会消耗时间,造成响应时间的浪费
- 无法充分利用带宽,造成带宽资源的浪费
TCP协议的特点是「慢启动」,即一开始传输的数据量少,一段时间之后达到传输的峰值。而上面这种做法,会导致大量的请求在TCP达到传输峰值前就被销毁了
HTTP1.1
为了解决HTTP1.0的问题,HTTP1.1默认开启长连接,即让同一个TCP连接服务于多个请求-响应。
在这种情况下,多次请求响应可以共享同一个TCP连接,这不仅减少了TCP的握手和挥手时间,同时可以充分利用TCP「慢启动」的特点,有效的利用带宽。
实际上,在HTTP1.0后期,虽然没有官方标准,但开发者们慢慢形成了一个共识:
只要请求头中包含Connection:keep-alive,就表示客户端希望开启长连接,希望服务器响应后不要关闭TCP连接。如果服务器认可这一行为,即可保持TCP连接
当需要的时候,任何一方都可以关闭TCP连接
扩展知识
连接关闭的情况主要有三种:
- 客户端在某一次请求中设置了
Connection:close,服务器收到此请求后,响应结束立即关闭TCP- 在没有请求时,客户端会不断对服务器进行心跳检测(一般每隔1秒)。一旦心跳检测停止,服务器立即关闭TCP
- 当客户端长时间没有新的请求到达服务器,服务器会主动关闭TCP。运维人员可以设置该时间。
由于一个TCP连接可以承载多次请求响应,并在一段时间内不会断开,因此这种连接称之为长连接。
管道化和队头阻塞
HTTP1.1允许在响应到达之前发送下一个请求,这样可以大幅缩减带宽限制时间
但这样做会存在队头阻塞的问题
由于多个请求使用的是同一个TCP连接,服务器必须按照请求到达的顺序进行响应。
于是,导致了一些后发出的请求,无法在处理完成后响应,产生了等待的时间,而这段时间的带宽可能是空闲的,这就造成了带宽的浪费
队头阻塞虽然发生在服务器,但这个问题的根源是客户端无法知晓服务器的响应是针对哪个请求的。
正是由于存在队头阻塞,我们常常使用下面的手段进行优化:
- 通过减少文件数量,从而减少队头阻塞的几率
- 通过开辟多个TCP连接,实现真正的、有缺陷的并行传输
浏览器会根据情况,为打开的页面自动开启TCP连接,对于同一个域名的连接最多6个
如果要突破这个限制,就需要把资源放到不同的域中
然而,管道化并非一个成功的模型,它带来的队头阻塞造成非常多的问题,所以现代浏览器默认是关闭这种模式的
HTTP2.0
二进制分帧
HTTP2.0可以允许以更小的单元传输数据,每个传输单元称之为帧,而每一个请求或响应的完整数据称之为流,每个流有自己的编号,每个帧会记录所属的流。
这样就真正的解决了共享TCP连接时的队头阻塞问题,实现了真正的多路复用
不仅如此,由于传输时是以帧为单元传输的,无论是响应还是请求,都可以实现并发处理,即不同的传输可以交替进行。
由于进行了分帧,还可以设置传输优先级。
头部压缩
HTTP2.0之前,所有的消息头都是以字符的形式完整传输的
可实际上,大部分头部信息都有很多的重复
为了解决这一问题,HTTP2.0使用头部压缩来减少消息头的体积

对于两张表都没有的头部,则使用Huffman编码压缩后进行传输,同时添加到动态表中
服务器推
HTTP2.0允许在客户端没有主动请求的情况下,服务器预先把资源推送给客户端
当客户端后续需要请求该资源时,则自动从之前推送的资源中寻找
http1.0、http2.0、http3.0 之间的区别
http1.0
每次请求和响应完毕后都会销毁 TCP 连接,同时规定前一个响应完成后才能发送下一个请求。这样做有两个问题:
- 无法复用连接
每次请求都要创建新的 TCP 连接,完成三次握手和四次挥手,网络利用率低
- 队头阻塞
如果前一个请求被某种原因阻塞了,会导致后续请求无法发送。
http2.0
http2.0 优化了传输效率,它主要有以下改进:
- 二进制分帧
将传输的消息分为更小的二进制帧,每帧有自己的标识序号,即便被随意打乱也能在另一端正确组装
- 多路复用
基于二进制分帧,在同一域名下所有访问都是从同一个 tcp 连接中走,并且不再有队头阻塞问题,也无须遵守响应顺序
- 头部压缩
http2.0 通过字典的形式,将头部中的常见信息替换为更少的字符,极大的减少了头部的数据量,从而实现更小的传输量
- 服务器推
http2.0 允许服务器直接推送消息给客户端,无须客户端明确的请求
http3.0
http3.0 目前还在草案阶段,它完全抛弃了 TCP 协议,转而使用 UDP 协议,是为了进一步提升性能。
虽然 http2.0 进行了大量的优化,但它无法摆脱 TCP 协议本身的问题,比如建立连接时间长、对头阻塞问题等等。
为了保证传输的可靠性,http3.0 使用了 QUIC 协议。




