HTTP 协议历史
- HTTP 0.9(1991年)只支持get方法不支持请求头
- HTTP 1.0(1996年)基本成型,支持请求头、富文本、状态码、缓存、连接无法复用
- HTTP 1.1(1999年)支持连接复用、分块发送、断点续传
- HTTP 2.0(2015年)二进制分帧传输、多路复用、头部压缩、服务器推送等
- HTTP 3.0(2018年)QUIC 于2013年实现、2018年正式更名为HTTP3
HTTP1.0 和 HTTP1.1
- 队头阻塞:下个请求必须在前一个请求返回后才能发出,导致带宽无法被充分利用,后续请求被阻塞(HTTP 1.1 尝试使用流水线(Pipelining)技术,但先天 FIFO(先进先出)机制导致当前请求的执行依赖于上一个请求执行的完成,容易引起队头阻塞,并没有从根本上解决问题)
- 协议开销大:header里携带的内容过大,且不能压缩,增加了传输的成本
- 传输不安全:采用文本形式传输,所有传输的内容都是明文,且客户端和服务器端都无法验证对方的身份,这在一定程度上无法保证数据的安全性
- 单向请求:只能单向请求,客户端请求什么,服务器返回什么
- HTTP 1.0 和 HTTP 1.1 的区别:
- HTTP 1.0:仅支持保持短暂的TCP连接(连接无法复用);不支持断点续传;前一个请求响应到达之后下一个请求才能发送,存在队头阻塞
- HTTP 1.1:默认支持长连接(请求可复用TCP连接);支持断点续传(通过在 Header 设置参数);优化了缓存控制策略;管道化,可以一次发送多个请求,但是响应仍是顺序返回,仍然无法解决队头阻塞的问题;新增错误状态码通知;请求消息和响应消息都支持Host头域
HTTP2
解决 HTTP1 的一些问题,但是解决不了底层 TCP 协议层面上的队头阻塞问题。2015年
- 二进制传输:二进制格式传输数据解析起来比文本更高效
- 多路复用:重新定义底层 http 语义映射,允许同一个连接上使用请求和响应双向数据流。同一域名只需占用一个 TCP 连接,通过数据流(Stream)以帧为基本协议单位,避免了因频繁创建连接产生的延迟,减少了内存消耗,提升了使用性能,并行请求,且慢的请求或先发送的请求不会阻塞其他请求的返回
- Header压缩:减少请求中的冗余数据,降低开销
- 服务端可以主动推送:提前给客户端推送必要的资源,这样就可以相对减少一点延迟时间
- 流优先级:数据传输优先级可控,使网站可以实现更灵活和强大的页面控制
- 可重置:能在不中断 TCP 连接的情况下停止数据的发送
缺点:HTTP 2
中,多个请求在一个TCP管道中的,出现了丢包时,HTTP 2
的表现反倒不如HTTP 1.1
了。因为 TCP 为了保证可靠传输,有个特别的“丢包重传”机制,丢失的包必须要等待重新传输确认,HTTP 2
出现丢包时,整个 TCP 都要开始等待重传,那么就会阻塞该TCP连接中的所有请求。而对于 HTTP 1.1
来说,可以开启多个 TCP 连接,出现这种情况反到只会影响其中一个连接,剩余的 TCP 连接还可以正常传输数据
HTTP3
HTTP 是建立在 TCP 协议之上,所有 HTTP 协议的瓶颈及其优化技巧都是基于 TCP 协议本身的特性,HTTP2 虽然实现了多路复用,底层 TCP 协议层面上的问题并没有解决(HTTP 2.0 同一域名下只需要使用一个 TCP 连接。但是如果这个连接出现了丢包,会导致整个 TCP 都要开始等待重传,后面的所有数据都被阻塞了),而 HTTP3 的 QUIC 就是为解决 HTTP2 的 TCP 问题而生。
TCP 是什么?
TCP:全称为传输控制协议,是一种面向连接的、可靠的、基于字节流的传输层通信协议,由 IETF 的 RFC 793 定义。TCP 是面向连接的、可靠的流协议。
- 面向连接(存在三次握手)
- 只能进行点对点的数据传输
- 面向字节流(TCP 不像 UDP 一样那样一个个报文独立地传输,而是在不保留报文边界的情况下以字节流方式进行传输)
- 可靠传输(依靠 TCP 的段编号以及确认序号)
- 拥塞控制(网络出现拥塞的时候,TCP 能够减小向网络注入数据的速率和数量,缓解拥塞)
- 提供全双工通信(通信双方的应用程序在任何时候都能发送数据)
- 存在队头阻塞(使用序列号来标识数据的顺序,数据必须按照顺序处理)
UDP 是什么?
UDP:全称为用户数据报协议,与 TCP
协议一样用于处理数据包,是一种面向无连接不可靠的协议。关注把数据报文传输出去,不关心是否安全到达。
- 面向无连接(不需要三次握手)
- 支持一对多,多对多,多对一
- 不可靠(原因:通信都不需要建立连接、没有拥塞控制所以网络条件不好的情况下可能会导致丢包)
- 传输数据高效
QUIC 对比 TCP/UDP 的优缺点
QUIC
协议是 Google 提出的一套基于 UDP
的开源协议,它汇集了 TCP
和 UDP
的优点,传输高效并且可靠。
QUIC 的优点:
- 迭代更新快
TCP
和UDP
协议是操作系统内核实现的,部署进度慢。QUIC
直接基于客户端实现,能实现快速迭代更新 - 没有队头阻塞的多路复用
TCP
使用序列号来标识数据的顺序,数据必须按照顺序处理,可能会造成队头阻塞。HTTP2 支持多路复用,但是由于强制使用TLS
,还存在一个TLS
协议层面的队头阻塞,QUIC
最基本的传输单元是 Packet,不会超过 MTU 的大小,整个加密和认证过程都是基于 Packet 的,不会跨越多个 Packet。这样就能避免TLS
协议存在的队头阻塞。Stream 之间相互独立,比如 Stream2 丢了一个 Pakcet,不会影响 Stream3 和 Stream4,所以也不存在 TCP 队头阻塞。 - 握手更迅速
TCP
需三次握手才能建立连接,有等待时延,如果用了TLS
加密,还会进一步增加时延。QUIC
采用了类似于TCP
Fast Open的设计,在之前已经连接过的情况下可以无需握手,直接开始传送数据,连接建立时延为0 - 加密技术比
TLS
性能好,同时具有各种攻击防御策略。 - 前向纠错
QUIC
和TCP
一个主要的核心区别就是:TCP
采用 重传 机制,而QUIC
采用 纠错 机制。如果发生丢包的话,TCP
首先需要一个等待延时来判断发生了丢包,然后再启动重传机制,在此期间会对连接造成一定的阻塞(并且TCP
窗口是缓慢增大的,Web这种突发性快速连接情况下窗口会相对较小),从而影响传输时间。而QUIC
采用了一种脑洞极大的前向纠错(FEC)方案,类似于RAID5,将N个包的校验和(异或)建立一个单独的数据包发送,这样如果在这N个包中丢了一个包可以直接恢复出来,完全不需要重传,有利于保证高速性,N可以根据网络状况动态调整 - 连接保持
TCP 连接是由四元组标识的(源 IP,源端口,目的 IP,目的端口),当其中一项发生改变,都需要重新建立和服务端的 TCP 连接。QUIC 连接不再以 IP 及端口四元组标识,而是以一个 64 位的随机数作为 ID 来标识,这样就算 IP 或者端口发生变化时,只要 ID 不变,这条连接依然维持着。这就意味着:在IP地址和端口变化的情况下(比如从Wi-Fi切换到流量),可以无需重新建立连接,继续通信
- 能实现证书压缩,减少证书传输量,针对包头进行验证等。
QUIC 的不足:
QUIC
基于UDP
,目前很多网络运营商会降低UDP
包的优先级,使得UDP
丢包率特别高- 支持的浏览器少
参考资料:
下一代通信协议:QUIC
科普:QUIC协议原理分析
HTTP/3 都来了,你却还在用 HTTP/1.1?
TCP和UDP比较
一文读懂 HTTP/2 及 HTTP/3 特性
为什么 HTTP1.1 不能实现多路复用
解读HTTP/2与HTTP/3 的新特性