从HTTP0.9到HTTP3.0发展历程的万字回首与展望

作者:小牛呼噜噜 | https://xiaoniuhululu.com
计算机内功、源码解析、科技故事、项目实战、面试八股等更多硬核文章,首发于公众号「小牛呼噜噜

哈喽,大家好呀,我是呼噜噜,好久没更新了,今天我们来开一个新的专题计算机网络,网络在我们如今的世界中无处不在,无论是电脑,手机还是其他物联网设备的远程访问,都离不开网络

计算机网络的作用

计算机网络的功能主要是:

  1. 数据通信,数据通信主要完成资源子网中各个独立的计算机系统之间的信息数据的传递,比如社交软件、远程传输文件软件等都利用了计算机网络
  2. 资源共享,资源共享是计算机网络提供的最基本功能,也是早期建网的的初衷,所谓的资源主要是软件资源,数据信息资源等
  3. 提高可靠性,在计算机网络中,设备是彼此相连的。如果一个设备出现故障,可以通过网络寻找其他机器来代替本机工作或者资源可以多设备存放,用户可以通过多种途径来访问网络中的资源
  4. 提高系统处理能力,单机设备的处理能力是有限的,同一网络内的多台计算机协同操作和并行处理可以提升整个系统的处理能力
  5. 分布式处理,利用网络技术多个独立的计算机系统连接组合成一个高性能的计算机系统,计算机群集,分布式系统

什么是HTTP协议

我们先来讲讲和我们离得最近的一种协议:HTTP协议,比如我们平时在电脑上使用浏览器浏览网页,在手机上在app里刷视频打游戏,它们背后都离不开HTTP协议

计算机网络中的”协议”,就是protocol,即允许计算机设备相互之间,通信(交流)的一系列标准的规则rules,规定了双方及其以上参与者的行为约定和规范

HTTP协议:超文本无状态协议,英文HyperText Transfer Protocol,简称HTTP,是一个基于请求与响应,无状态的,应用层的协议,是互联网上应用最为广泛的一种网络协议

如果你先前不太了解这个协议,看上面的定义是不是很懵?下面我们来详细解释一下:

  1. HTTP协议可以传输超文本,所谓的超文本来源于英文HyperText直译

其不局限文本文字还包含图片、视频等,特指含有指向其他资源链接(超链接HyperLink)内容的文本

最常见的超文本就是网页HTML,支持图文混排的同时将各种不同空间的文字信息组织在一起的网状文本,html本身也就是普遍的文本,当然它还包含许多图片、视频等的超链接

但它拥有超越于文本的表达能力,只需通过浏览器内核等设备或者其他技术的识别处理,就能展示文字、图片、音频、视频等混合内容,这也就是如今我们熟悉的丰富多彩的网页

  1. HTTP 是一种无状态stateless协议,为了能够快速处理大量的事务, 提高效率,所以对于发送过的请求或响应都不做持久化处理

HTTP协议的发展历程

上面我们介绍http协议最基本的2个特点:超文本传输、无状态,它还有许多特性,这些特性不是一蹴而就的,是通过很多年的使用和迭代不断发展而来的,我们一起来回顾一下HTTP协议的发展历程:

版本 推出年份 当前状态
HTTP/0.9 1991年 已过时
HTTP/1.0 1996年 已过时
HTTP/1.1 1997年 标准
HTTP/2.0 2015年 标准
HTTP/3.0 2022年 标准

如果时间回退到1989年,那时候互联网还只属于少数人的自娱自乐,当时在欧洲核子研究组织 (CERN)工作的 Tim Berners-Lee博士,写了一份关于建立一个可以通过网络传输超文本全新系统的提案,阐述了新系统的几个组成:

  1. 一个用来表示超文本文档的文本格式,超文本标记语言(HTML)
  2. 一个用来交换超文本文档的简单协议,超文本传输协议(HTTP)
  3. 一个显示超文本文档的客户端,即网络浏览器。第一个网络浏览器被称为World Wide Web
  4. 一个服务器用于提供可访问的文档,即httpd的前身

早期网络只是满足世界各地大学和研究所的科学家之间,互相分享文档、资料或者信息的需求,但是Berners-Lee(蒂姆·伯纳斯·李)野望不仅仅如此,他更希望建立一个全球化的信息交互系统,秉持着开放、平等、协作、快速、共享的信念

在随后的1990年该项目实施期间被更名为万维网(World Wide Web,WWW),取自第一个网络浏览器的名称,如今大名鼎鼎!

info.cern.ch是世界上第一个网站和网络服务器的地址,运行在 CERN 的 NeXT 计算机上。第一个网页地址是http://info.cern.ch/hypertext/WWW/TheProject.html,大家可以去浏览看看

HTTP/0.9

我们接着讲HTTP协议,其实http在应用的早期阶段非常简单,基于现有的TCP/IP协议之上建立的,并没有版本号,后来被统称为HTTP/0.9,1991年

HTTP/0.9非常简单,并不涉及数据包传输,通过请求和响应的交换达成通信,请求由单行指令构成,所以它也被称为单行协议,而且请求方法支持有限,只能GET请求,其后跟目标资源的路径;所以它并没有作为正式的标准

请求:

1
GET /index.html   

响应:

1
2
3
<html>
Hello World
</html>

但此时HTTP/0.9最大的问题是,是只能传输简单的HTML格式的字符串,无法传输其他类型的文件

也没有状态码或错误代码,一旦出现问题,会返回包含问题描述信息的HTML网页;当服务端相响应之后,会立即关闭TCP连接

几年后,在互联网工程任务组(IETF) 和万维网联盟(W3C) 的协调努力下,开始开发早期的HTTP征求意见(RFC ),随后工作移交给了 IETF,未来可期~

HTTP/1.0

由于HTTP/0.9协议的应用十分有限,只能传输简单的HTML文件

所以在1996年HTTP/1.0发布,http正式作为标准协议,新增请求头(request header)和响应头(response header)的概念,都以Key-Value键值对形式保存,无论是请求还是响应,都需要先返回头信息

内容格式不再受限

请求头中新增了Content-Type标头,来表示请求所提交内容的类型,使协议变得非常灵活,更具扩展性,从此让http协议传输的内容格式不再受限;即相较于HTTP/0.9只能传输html文件,它能传输图片、音频、视频、二进制等其他类型的文件

增加POST、PUT、PATCH、HEAD、 OPTIONS、DELETE命令,丰富了请求的方法;还可以在通信中指定了HTTP协议版本号,在请求行后追加,比如GET / HTTP/1.0

为了减轻服务器的压力,在 HTTP/1.0 中提供了缓存Cache机制,用来缓存已经下载过的数据,当客户端在规定时间内访问相同的网页,网页数据直接从cache取出。看来缓存在计算机的时间中真是无处不在呀,感兴趣地可以去看看笔者的 CPU_Cache系列

还增加了多字符集支持,多部分发送,权限等,我们下面来看下HTTP/1.0的请求和响应示例

请求:

1
2
3
4
5
GET / HTTP/1.0

User-Agent: NCSA_Mosaic/2.0 (Windows 3.1)

Accept: */*

响应:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
HTTP/1.0 200 OK

Content-Type: text/plain

Content-Length: 137582

Expires: Thu, 05 Dec 1997 16:00:00 GMT

Last-Modified: Wed, 5 August 1996 15:55:28 GMT

Server: Apache 0.84



<html>

<body>Hello World</body>

</html>

由于某些请求服务器可能无法处理,或者处理异常,这个情况下,我们需要告诉浏览器,服务器最终处理该请求的具体情况

所以HTTP/1.0还新增响应状态码,响应状态码会在响应开始时发送,使浏览器能了解服务器执行请求具体情况(成功or失败),并及时根据返回状态码,来相应调整行为(如更新或使用本地缓存);状态码追加在响应行后面HTTP/1.0 200 OK,所以状态码是通过响应行的方式来通知浏览器的

我们这边暂不展开,1.0的http状态码还不是很全,后面的协议会不断新增状态码;响应状态码常见的有1xx,2xx,3xx,4xx,5xx:

1xx 信息,服务器收到请求,需要请求者继续执行操作
2xx 成功,操作被成功接收并处理
3xx 重定向,需要进一步的操作以完成请求
4xx 客户端错误,请求包含语法错误或无法完成请求
5xx 服务器错误,服务器在处理请求的过程中发生了错误

无状态且无连接特性

我们需要注意的是,此时HTTP/1.0无状态且无连接的应用层协议!

为了能够快速处理大量的事务, 提高效率,所以HTTP/1.0规定浏览器(客户端)和服务器(服务端)保持短暂的连接(短连接),对于发送过的请求或响应都不做持久化处理,浏览器每次请求都需要建立tcp连接,服务器处理完成后立即断开TCP连接(无连接的表现),服务器不跟踪也不记录每个客户端过去的请求(无状态的表现

HTTP/1.0的无连接特性也会导致一些性能缺陷:

  1. 客户端与服务端之间的连接无法复用,HTTP/1.0中每个TCP连接只能发送一个请求,数据发送完毕连接就关闭,如果还要请求其他资源,就必须重新建立连接。TCP每次建立连接时,都需要进行三次握手和四次挥手,所以频繁地建立新连接的成本很高,网络的利用率较低
  2. 队头堵塞问题,由于HTTP/1.0规定下一个请求必须在前一个请求响应到达之前才能发送。假设一个请求因为网络的波动,产生的丢包和乱序问题,导致响应一直不到达,那么下一个请求就不发送,就到导致阻塞后面的请求;而且每次建立连接高成本,会更加重性能缺陷

为了解决这些问题,缝缝补补的HTTP/1.1第二年就出现了~~

HTTP/1.1

随着浏览器的普及,网页上的图片视频等文件越来越多,一个页面甚至能包含成千上万个超链接资源文件,HTTP/1.0每下载一个文件,都需要重新建立连接、传输数据和断开连接这3个操作,HTTP/1.0无连接特性导致连接无法复用以及队头堵塞性能的问题,越来越严重

支持长连接

1997年HTTP/1.1正式发布,HTTP/1.1正式支持长连接,它在请求头上新增Connection字段,将其设置为Connection: keep-alive,当然你不用去设置,因为这是默认开启的,来保持连接不断开,这样也就可以被多个请求复用

如果你不想开启长连接,也可以在 HTTP 请求头中加上Connection: close。谷歌浏览器中对于同一个域名,默认允许同时建立6个TCP长连接

管道机制

HTTP/1.1还加入管道机制pipelining(多个请求可以”并行”,无需等待上一个请求返回),试图解决”队头阻塞”的问题;当然它的前提是HTTP/1.1支持长连接

但管道仅在理想情况下,能够提高网络的收发效率,主要由于它响应的顺序还是必须按照请求的顺序返回的,只有这样才能保证客户端能够区分出每次请求的响应内容(浏览器获取html一定要在获取css前面,不然就没有意义);也就是说某个先发请求阻塞,则后继报文即使处理也不能发出,所以仍然存在队头阻塞问题;FireFox、Chrome都做过管线化的试验,但是由于各种原因,它们最终都放弃了管线化处理


所以HTTP/1.1无法解决”队头阻塞”,只能缓解,主要采取一下2种方式来处理:

  1. 浏览器厂商允许我们打开多个TCP的会话。RFC2616里明确限制每个客户端最多并发2个连接。不过实践中证明这个数字实在是太小了,众多浏览器都“无视”标准,把这个上限提高到了 4~6;后来RFC7230取消”最多并发2个连接”这个限制
  2. 域名分片,多个域名可以同时指向同一台服务器(这个前提是HTTP新增请求头Host字段)

新增请求头Host字段

另外HTTP/1.0不支持Web服务器在同一个IP地址和端口号上配置多个虚拟web站点,因此一个服务器只能支持一个域名

HTTP/1.1中增加请求头Host字段,用来表示当前的域名地址,这样浏览器可以使用host来明确表示要访问服务器上的哪个Web站点,服务器同时也可以根据不同的Host值做不同的处理,这就实现了多个请求发往同一台服务器上的不同网站;也就是说如果每个虚拟web站点都有自己的单独的域名,那么这些单独的域名可以公用同一个 IP 地址

HTTP 1.1还提供了与身份认证、状态管理和Cache缓存等机制相关的请求头和响应头,新增了PUT、PATCH、OPTIONS、DELETE 等请求方式

我们来看下HTTP/1.1的请求和响应示例
请求:

1
2
3
4
5
6
7
GET /static/img/header-background.png HTTP/1.1
Host: developer.mozilla.org
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:50.0) Gecko/20100101 Firefox/50.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: https://developer.mozilla.org/zh-CN/docs/Glossary/Simple_header

响应:

1
2
3
4
5
6
7
8
9
10
11
200 OK
Age: 9578461
Cache-Control: public, max-age=315360000
Connection: keep-alive
Content-Length: 3077
Content-Type: image/png
Date: Thu, 31 Mar 2016 13:34:46 GMT
Last-Modified: Wed, 21 Oct 2015 18:27:50 GMT
Server: Apache

(image content of 3077 bytes)

断点续传和分块传输

HTTP/1.1还支持文件的断点续传,所谓的断点续传,就是文件在网络传输过程中时常面对网络中断的情况,上传到中途时,网突然断了,由于文件比较大,若重新开始上传的话,非常浪费时间,这个时候就需要有一种机制可以从上次网络中断的地方继续开始上传

那么HTTP/1.1是如何支持文件的断点续传?HTTP/1.1通过新增Header里两个参数,客户端发请求时对应的是Range,服务器端响应时对应的是Content-Range;再配合新引入的分块传输Chunk transfer机制,服务器会将数据分割成若干个任意大小的数据块,每个数据块发送时会附上上个数据块的长度(无论内容多大服务端都可以动态知晓),最后使用一个零长度的块作为发送数据完成的标志

可能还会出现,当客户端再次发起续传请求时,此时URL对应服务器上的资源文件已经发生变化这种情况,HTTP/1.1还新增Last-Modified来标识文件的最后修改时间,如此就能够判断出续传文件时是否已经发生过改动;同时还是定义了一个ETag的头,可以使用 ETag头来放置文件的唯一标识

我们下面看一下,Range、Content-Range及其响应的格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Range: bytes=0-499 //表示第 0-499 字节范围的内容 
Range: bytes=500-999 //表示第 500-999 字节范围的内容
Range: bytes=-500 //表示最后 500 字节的内容
Range: bytes=500- //表示从第 500 字节开始到文件结束部分的内容
Range: bytes=0-0,-1 //表示第一个和最后一个字节
Range: bytes=500-600,601-999 //同时指定几个范围

Content-Range: bytes 0-499/22400 //0-499 是指当前发送的数据的范围,而 22400 则是文件的总大小

在响应完成后,返回的响应头内容也不同:

1. HTTP/1.1 200 Ok(不使用断点续传方式)

2. HTTP/1.1 206 Partial Content(使用断点续传方式)

无状态的缺点以及cookies带来的希望

HTTP/1.1协议自发布以来,是2015年前使用最广泛的http版本,到如今(2023)还有大量的设备仍然在使用,由于 HTTP 协议的可扩展性使得创建新的头部和方法是很容易的,到2014年为止,HTTP/1.1协议不断地扩展其自身的功能

HTTP/1.1无状态协议,好处是不需要额外的资源来记录状态信息,减少服务器的压力,能够快速处理大量事务,确保协议的可伸缩性

但凡事有利有弊,随着网络的应用场景越来越丰富,http没有记忆功能,导致业务处理变得棘手情况越来越多,比如用户登录购物,租房,打车,支付网站等等,跳转对应网站的其他页面,也需要能继续保持登录状态以及一下个人信息,总不能一直去服务端获取相关信息吧

所以HTTP/1.1引入了Cookie技术,在请求头新增Cookie字段,响应头新增Set-Cookie字段。Cookie使基于无状态的HTTP协议能够记录稳定的状态信息成为了可能

Cookie是服务器发送到用户浏览器并保存到本地的一小块数据,浏览器下次向同一服务器再发起请求时携带(会带来额外的性能开销)并一起发送到服务器上。一般,它用于告知服务端两个请求是否来自同一浏览器——如保持用户的登录状态或者相关信息

cookie的使用场景一般有:会话状态管理(如用户登录状态、购物车、游戏分数或其它需要记录的信息),个性化设置(如用户自定义设置、主题等),浏览器行为跟踪(如跟踪分析用户行为等)

但由于各个平台滥用cookie来存储数据,会带来了性能问题和安全问题,再加上现代浏览器陆续支持各种各样的存储方式,如今份额也在慢慢变少

SSL与HTTPS

HTTP/1.1最大的安全问题,就是它是明文传输的,早期web和网络主要用于学术资料的传输与共享,但随着web流行于整个地球,使用者也越来越鱼龙混杂,所有经过http传输的信息都可以被抓包等其他手段看的清清楚楚,存在很大的安全隐患

于是在1994年,网景公司(Netscape Communication)在http协议依赖的TCP/IP协议栈的基础上,创建了一个额外的加密传输层:SSL协议,后来发展为TLS,一般被称为SSL/TLS协议。HTTP+SSL/TLS = HTTPS(超文本传输安全协议),所以HTTPS并不是一个新协议

HTTP 默认端口号是 80,HTTPS 默认端口号是 443

HTTPS连接建立,需要TCP三次握手之后,还需进行SSL/TLS的握手过程,才能够进入加密报文传输通道

那么SSL/TLS协议是如何保证传输通道的安全性的?

主要是采用以下措施:

  1. 混合加密: 所有请求内容加密后再传播,防止被第三方窃听。混合加密,就是使用非对称密钥加密对称密钥,用于保证传输对称密钥的安全性;之后的通信都是用对称密钥进行加解密,来保证通信效率
  2. 认证:由于公钥是暴露在外的,需要配备CA证书,保证公钥是服务器的公钥,而不是第三方冒充的
  3. 完整性保证: 提供报文摘要功能(通过哈希算法生成哈希值),报文一旦被篡改,通信双方会立刻发现(即使被篡改也很难通过哈希值反推出报文摘要)

HTTP/2.0

HTTP/2.0在2015年正式发布,相较于HTTP/1.1不仅仅是更新发展,更是里程碑式的突破,我们一起来看看它的新特性

抓的https://www.h2check.org的包,HTTP/2.0的请求和响应示例:

二进制分帧

HTTP1.x头信息是文本(ASCII编码),数据体可以是文本,也可以是二进制;而HTTP/2.0则彻底是二进制协议,它在
应用层和传输层之间增加一个二进制分帧层,来解决HTTP1.1 的性能限制,改进传输性能,实现低延迟和高吞吐量

那肯定有人疑惑,为什么采用二进制呢,文本不是挺好的嘛?

与文本相比,HTTP/2.0采用二进制,占用更少的空间,也就代表传输的数据量更少,从而减少了带宽的使用;虽然二进制人类看不懂,但计算机天生就能看懂啊,这样服务器和客户端解析数据时就不需要再额外进行文本到二进制的转换,提高了处理数据的速度;也更利用后面的多路复用,二进制的结构更容易支持同时传输多个数据流;另外二进制相比文本也更适合算法去压缩大小

引入二进制分帧层,在不改动 HTTP/1.x 的语义、方法、状态码、URI 以及首部字段的情况下,重新设计了编码机制,它将所有传输信息分割为更小的帧frame,并进行二进制编码将其封装;帧就是基本单位

其中帧可以分为:头信息帧(Headers Frame)和数据帧(Data Frame),htt1.x中的头信息header封装到Headers帧中,而数据体body将被封装到Data帧中

多路复用

哪怕HTTP/1.1引入管道机制pipelining,但服务器必须进行按顺序逐个响应的送回,导致响应端还是存在”队头阻塞”问题,HTTP/2.0采用多路复用,来代替原来的序列和阻塞机制(就是HTTP1.x所依赖最基本的”请求与应答”模型)

多路复用就是在单一的HTTP/2.0连接中,允许同时发起多重的请求,每个请求及该请求的响应不需要等待其他的请求,某个请求任务耗时严重,不会影响到其它连接的正常执行

二进制分帧前提下,此时HTTP/2.0不再依赖建立多个TCP连接去实现多流并行。每个数据流都拆分成很多相互独立的帧,而这些帧可以无序传输,也可以按优先级,最后在另一端再通过根据不同帧首部的流标识符把它们重新组装成完整的消息。

要想更直观地理解,多路复用,二进制分帧除了上面帧的,还需要知道连接、数据流、消息的概念

  1. 连接 Connection: 1 个 TCP 连接,包含一个或者多个 Stream。
  2. 数据流 Stream:一个双向通讯数据流,包含 1 条或者多条 Message。
  3. 消息 Message:对应 HTTP/1 中的请求或者响应,包含一条或者多条 Frame。
  4. 数据帧 Frame:最小单位,以二进制压缩格式存放 HTTP/1.1中的内容,包含类型Type, 长度Length, 标记Flags, 流标识Stream和frame payload有效载荷。

其实他们四者,是分层级和一对多的关系:

每个请求/响应构成一个数据流.,每个数据流都可以被拆分成许多个二进制的帧中。这些二进制数据帧通过stream id来区分自己属于哪一个数据流,这样就可以把不同数据流的帧混在同一个连接里双向传输;也就是说只需要通过单个TCP连接就可以高速传输所有的请求数据,避免了”队头堵塞”,这才是真正地实现TCP连接的并行,其实就是基于数据流来实现会话的串行传输。这样能够绕过浏览器限制同一个域名下的请求数量的限制,充分利用 TCP 带宽

HTTP/2.0版本的基于帧的消息通信过程:

头部压缩

头部压缩Header Compression,由于HTTP协议是无状态协议,所以每次请求都必须附上所有信息;这就导致同时发出多个请求,往往他们的头信息是相似的,许多字段都是重复的,比如Cookie和User Agent等字段,会浪费很多带宽

HTTP/2.0采用HPACK算法,客户端和服务器同时维护一张头信息表,所有字段都会存入这个静态表,生成一个索引号,以后就不发送同样字段了,只发送索引号,减少传输重复数据的成本;另一方面头信息继续使用gzip或compress压缩后再发送

服务端推送

HTTP/2.0允许服务器未经请求,主动向客户端发送资源,也就是在客户端请求之前发送,这叫做服务器推送(server push)

当一个网页有许多静态资源,HTTP/1.x时代,客户端收到网页后,解析html源码,发现静态资源的同时发起获取静态资源请求;而HTTP/2.0的出现,服务端如果提前预知客户端需要哪些资源,可以提前把这些静态资源和网页一起,主动推给客户端缓存中

HTTP/2.0在一定程度上改变了传统的“请求-应答”模型,服务器不再是完全被动地响应请求,也可以新建“流”主动向客户端发送消息;

与基于HTTP/1.1实现的Websocket协议类似,服务端都可以主动给客户端发消息,但是不同的是HTTP/2.0允许让服务器能够主动地推送资源到客户端缓存,并没有允许推送数据到客户端应用本身。服务器的推送只是由浏览器来处理,并不会让应用代码介入,所以客户端也有权利选择是否接收

Websocket本文就不展开讲解了,因为本文的主题是http,感兴趣地自行去了解这个有意思的协议

如果服务端推送的资源已经被浏览器缓存过,客户端可以通过发送RST_STREAM帧来拒收。服务器不能随便将第三方资源推送给客户端,而必须是经过双方确认才行,即遵守同源策略

HTTP3.0

虽然HTTP/2.0相较于HTTP1.x有了巨大的技术革新,自发布以后逐渐占据市场主流,足以证明其优秀;但是俗话说,世界上没有完美的东西,HTTP/2.0也有其不足

启用HTTP/2.0后性能会有较大地提升,解决了HTTP这一层面的队头阻塞问题,但是因为所有传输数据的压力并没有消失,而是转移到底层依赖的一个TCP连接之上,而TCP又是个面向连接、可靠的传输层协议,TCP建立连接时的三次握手还是耗时还是长的,其次TCP依旧存在”队头阻塞”问题

以谷歌为首的大型科技公司并不能满足HTTP/2.0的性能,HTTP/3.0于2022年正式发布!要想进一步提升HTTP的性能,必须要优化其依赖的底层协议。TCP很成熟意味着改造难度很大。谷歌相较于改进TCP协议,更倾向于基于UDP来开发全新一代HTTP协议,HTTP/3.0也叫QUIC协议(Quick UDP Internet Connections)

  1. TCP面向连接,可靠,保证数据正确性,保证数据顺序,有队头阻塞问题,成本较高
  2. UDP无连接,不可靠,不保证数据正确性(可能丢包),不保证数据顺序,无队头阻塞问题,成本较低

抓的https://quic.nginx.org的包,HTTP/3.0的请求和响应示例:

解决队头阻塞问题

上面我们提到了,HTTP/2.0只解决HTTP这一层面的队头阻塞问题,但是TCP层依旧存在”队头阻塞”问题,这其实并不能怪TCP,它是无辜的,一切都是为了保证传输的可靠性;比如在传输过程中,一旦丢包,会触发TCP重传机制,这个时候一个TCP连接中的其他所有的请求都必须等待,直到丢的包被重传回来;这就会出现因为丢包而阻塞整个连接的请求

QUIC使用UDP来替换TCP,基本上算是重写了HTTP协议,而UDP没有”队头阻塞”问题,QUIC也实现了可靠传输,保证数据一定能够抵达目的地,还引入了类似HTTP/2.0的数据流和多路复用

QUIC协议可以同时运行多个数据流,每个数据流独立互不影响,并为每个流独立实现数据包丢失检测和重传,来保证数据的正确和有序性;当某个数据流丢包时,只会阻塞这个数据流,其他的数据流不会受到影响

缩短建立连接的时间

我们一般用来衡量网络建立连接性能的,常用指标是 RTT(Round-Trip Time),往返时延,表示从发送端发送数据开始,到发送端收到来自接收端的确认,所经历的时延;通俗点讲就是数据包一来一回的消耗了多少时间

我们知道HTTPS要建立一个连接,需要进行TCP握手和TLS握手,需要3个RTT;如果把第一次握手计算出来的对称密钥缓存起来,那也需要2个RTT。但是QUIC协议,可以做到首次连接只需要1RTT, 后面的连接只需要0RTT

因为QUIC可以让客户端发送给服务端的第一个包就可以包含有效的业务数据,这里使用DH密钥交换算法,重新定义了TLS协议加密QUIC头部的方式,既提高了网络攻击成本,又降低了建立连接的速度

图片来自:一文搞懂Diffie-Hellman密钥交换协议;大家数学不错的话,可以自行去了解一下

HTTP/3.0重新定义了TLS协议加密QUIC头部的方式,既提高了网络攻击成本,又降低了建立连接的速度

连接迁移

在我们现实生活中,网络的切换是很常见的情况,TCP连接基于四元组(源IP, 源端口, 目的IP, 目的端口), 切换网络时至少会有一个因素(一般是IP)发生变化,就会导致原本的连接异常,这时需要重新创建TCP连接,才能正常传输数据

QUIC不受四元组的影响, 当这四个元素发生变化时, 原来的连接依旧能够维持稳定;因为使用64位的随机数作为连接的Connection ID,并使用该ID表示连接;举个例子,当我们用手机看视频,这个时候需要出门拿快递,手机的网络会从WIFI自动地切换到4G,全程都不会感觉到视频卡顿,体验感直接拉满

前向纠错

前向纠错FEC是一种在单向通信系统中控制传输错误的技术,通过连同数据发送额外的信息进行错误恢复,以降低比特误码率

因为UDP并不是个可靠协议,QUIC使用前向纠错来增加协议的容错性,一段数据会被拆成多个数据包,传输途中某个包丢失,接收方收到数据包后,可以”校验”发现有丢包情况并通过其他包和FEC,推算出丢失的那个包的数据来”纠错”

HTTP3还有许多有意思的特点,篇幅有限就不展开了,详情见Hypertext Transfer Protocol Version 3 (HTTP/3)

小结

本文主要是介绍计算机网络中的http协议,并没有展开里面的各个属性参数,而是带着大家从web、http协议的诞生之初,回顾各个阶段的发展历程,从HTTP/0.9、HTTP/1.0、HTTP/1.1、HTTP/2.0再到如今最新的HTTP/3.0,聊聊他们的主要特性以及聚焦于改进的缘由(前代的不足),有许多细节由于篇幅有限只能做取舍,我们下期再见,带着大家走入网络的世界~

最后再汇总一下各个版本的特点:


参考资料:

https://www.w3.org/Protocols
https://codestory.de/12429/einfuehrung-in-html
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Basics_of_HTTP/Evolution_of_HTTP
https://www.cnblogs.com/findumars/p/5745345.html
https://home.cern/science/computing/birth-web/short-history-web
https://zhuanlan.zhihu.com/p/599518034
https://zh.wikipedia.org/wiki/%E8%B6%85%E6%96%87%E6%9C%AC%E4%BC%A0%E8%BE%93%E5%8D%8F%E8%AE%AE
https://www.w3.org/Protocols/HTTP/AsImplemented.html
https://link.zhihu.com/?target=https%3A//datatracker.ietf.org/doc/html/rfc1945
https://datatracker.ietf.org/doc/html/rfc7540
https://datatracker.ietf.org/doc/html/draft-ietf-quic-http-33


作者:小牛呼噜噜 ,首发于公众号「小牛呼噜噜

感谢阅读,原创不易,如果有收获的话,就点个免费的[]or[转发],你的支持会激励我输出更高质量的文章,感谢!