【计算机网络 | 第十一篇】计网之应用层(二)—— 万字解析 + 图解DNS、DHCP、HTTP2.0/3.0

⭐️在这个怀疑的年代,我们依然需要信仰。

个人主页:YYYing.

⭐️计算机网络系列专栏:

【从零开始的计算机网络】

⭐️ 其他专栏:【linux基础】【数据结构与算法】

系列上期内容:【计算机网络 | 第十篇】计网之应用层(一)一文带你搞懂HTTP

系列下期内容:暂无


目录

前言:

DNS协议

一、DNS系统协议

二、DNS系统结构

三、域名结构

四、域名服务器

4.1、根域名服务器

4.2、顶级域名服务器

4.3、权威(限)域名服务器

4.4、本地域名服务器

五、DNS的查询步骤

六、DNS查询类型

6.1、递归查询

6.2、迭代查询

6.3、缓存查询

6.4、练习题

七、DNS网络排查工具

DHCP协议

一、DHCP服务器

二、DHCP工作机制

[HTTP 2.0](#HTTP 2.0)

一、最初的HTTP

二、HTTP的瓶颈

pipelining

三、SPDY

3.1、认识SPDY

3.2、SPDY的基础功能

3.3、SPDY的高级功能

[四、初探HTTP 2.0](#四、初探HTTP 2.0)

[五、HTTP 2.0的主要变化](#五、HTTP 2.0的主要变化)

5.1、二进制格式

5.2、连接共享

5.3、头部压缩

5.4、服务端推送

[六、HTTP 2.0的缺陷](#六、HTTP 2.0的缺陷)

[HTTP 3.0](#HTTP 3.0)

[一、HTTP 3.0的诞生](#一、HTTP 3.0的诞生)

[HTTP 2.0与HTTP 3.0的不同](#HTTP 2.0与HTTP 3.0的不同)

结语

---⭐️封面自取⭐️---


前言:

在上一篇博客中,我们讲解了有关HTTP与WWW的有关内容,那么这一篇也是我们计网应用层的最后一篇了, 我们来讲解DNS、DHCP与HTTP2.0/3.0的内容。

DNS协议

试想一个问题,我们人类可以有多少种识别自己的方式?可以通过身份证来识别,可以通过社保卡号来识别,也可以通过驾驶证来识别,尽管有多种识别方式,但在特定的环境下,某种识别方法会比其他方法更为适合。因特网上的主机和人类一样,可以使用多种方式进行标识。互联网上主机的一种标识方法是使用它的主机名(hostname)比如www.baidu.comwww.google.com 等。这是我们人类习惯的记忆方式,因特网中的主机却不会这么记忆,它们喜欢定长的、有层次结构的 IP 地址

一、DNS系统协议

DNS 的全称是 Domain Name System,DNS ,它是一个由分层的 **DNS 服务器(DNS server)**实现的分布式数据库;它还是一个使得主机能够查询分布式数据库的应用层协议。DNS服务器通常是运行 **BIND(Berkeley Internet Name Domain)**软件的 UNIX 机器。DNS 协议可以运行在 UDP 之上,也可以运行在 TCP 之上,使用 53 端口。

DNS 通常不是一门独立的协议,它通常为其他应用层协议所使用,这些协议包括 HTTP、SMTP 和 FTP,将用户提供的主机名解析为 IP 地址。

二、DNS系统结构

● 因特网是否可以只使用一台DNS服务器?

**○**这种做法并不可取。因为因特网的规模很大,这样的域名服务器肯定会因为超负荷而无法正常工作,而且一旦域名服务器出现故障,整个因特网就会瘫痪。

早在1983年,因特网就开始采用层次结构的命名树作为主机的名字(即域名),并使用分布式的域名系统DNS

DNS使大多数域名都在本地解析,仅少量解析需要在因特网上通信,因此系统效率很高。

**○**由于DNS是分布式系统,即使单个计算机出了故障,也不会妨碍整个系统的正常运行。

● DNS 最早的设计是只有一台 DNS 服务器。这台服务器会包含所有的 DNS 映射。这是一种集中式的设计,这种设计并不适用于当今的互联网,因为互联网有着数量巨大并且持续增长的主机,这种集中式的设计会存在以下几个问题:

○ 单点故障(a single point of failure),如果 DNS 服务器崩溃,那么整个网络随之瘫痪。

○ 通信容量(traaffic volume),单个 DNS 服务器不得不处理所有的 DNS 查询,这种查询级别可能是上百万上千万级。

○ 远距离集中式数据库(distant centralized database) ,单个 DNS 服务器不可能 邻近 所有的用户,假设在美国的 DNS 服务器不可能临近让澳大利亚的查询使用,其中查询请求势必会经过低速和拥堵的链路,造成严重的时延

○ 维护(maintenance),维护成本巨大,而且还需要频繁更新。

三、域名结构

● 因特网采用层次树状结构的域名结构。

域名的结构由若干个分量组成,各分量之间用"点"隔开,分别代表不同级别的域名。

**○**每一级的域名都由英文字母和数字组成,不超过63个字符,不区分大小写字母。

**○**级别最低的域名写在最左边,而级别最高的顶级域名写在最右边。

**○**完整的域名不超过255个字符。

http://mirrors.ustc.edu.cn/help/ubuntu.html

**●**域名系统既不规定一个域名需要包含多少个下级域名,也不规定每一级的域名代表什么意思。

**●**各级域名由其上一级的域名管理机构管理,而最高的顶级域名则由因特网名称与数字地址分配机构 ICANN 进行管理。

顶级域名**(Top Level Domain,TLD)**分为以下三类:

|----------------------------------------|--------------------------------------------------------------------------------------------------|-------------------------|
| 国家顶级域名nTLD | 通用顶级域名gTLD | 反向域arpa |
| 采用ISO 3166的规定。如cn表示中国,us表示美国,uk表示英国、等等 | 最常见的通用顶级域名有七个,即:com(公司企业)、net(网络服务机构)、org(非营利性组织)、int(国际组织)、edu(美国教育机构)、gov(美国政府部门)、mil(美国军事部门)。 | 用于反向域名解析,即 IP地址反向解析为域名。 |

**●**在国家顶级域名下注册的二级域名均由该国家自行确定。例如,顶级域名为jp的日本,将其教育和企 业机构的二级域名定为ac和co,而不用edu和com。

我国则将二级域名划分为以下两类:

|---------------------------------------------------------------------------------------|----------------------------------------------------|
| 类别域名 | 行政区域名 |
| 共七个:ac(科研机构)、com(工、商、金融等企业)、edu(教育机构)、gov(政府部门)、net(提供网络服务的机构)、mil(军事机构)和org(非营利性组织)。 | 共34个,适用于我国的各省、⾃治区、直辖市。例如:bj为北京市、sh为上海市、js为江 苏省,等等。 |

这种按等级管理的命名方法便于维护名字的唯一性,并且也容易设计出一种高效的域名查询机制。需要注意的是,域名只是个逻辑概念,并不代表计算机所在的物理地点。

四、域名服务器

域名和IP地址的映射关系必须保存在域名服务器中,供所有其他应用查询。显然不能将所有信息都储存在一台域名服务器中。DNS使用分布在各地的域名服务器来实现域名到IP地址的转换。

就大致来说目前有三种 DNS 服务器:根 DNS 服务器、顶级域(Top-Level Domain, TLD) DNS 服务器 和 权威 DNS 服务器。这些服务器的层次模型如下图所示:

假设现在一个 DNS 客户端想要知道 www.amazon.com 的 IP 地址,那么上面的域名服务器是如何解析的呢?

首先,**客户端会先和根服务器之一进行关联,它将返回顶级域名 com 的 TLD 服务器的 IP 地址。该客户则与这些 TLD 服务器之一联系,它将为 amazon.com 返回权威服务器的 IP 地址。**最后,该客户与 amazom.com 权威服务器之一联系,它为 www.amazom.com 返回其 IP 地址。

4.1、根域名服务器

● 根域名服务器是最高层次的域名服务器

● 每个根域名服务器都知道所有的顶级域名服务器的域名及其IP地址。

● 尽管我们将这13个根域名服务器中的每一个都视为单个的服务器,但"每台服务器"实际上是由许多分布在世界各地的计算机构成的服务器群集。

**○**当本地域名服务器向根域名服务器发出查询请求时,路由器就把查询请求报文转发到离这个 DNS客户最近的一个根域名服务器。

**○**这就加快了DNS的查询过程,同时也更合理地利用了因特网的资源。根域名服务器通常并不直接对域名进行解析,而是返回该域名所属顶级域名的顶级域名服务器的IP地址。

4.2、顶级域名服务器

顶级域名服务器负责管理在该顶级域名服务器注册的所有二级域名

**●**当收到DNS查询请求时就给出相应的回答,可能是最后的结果,也可能是下一级权限域名服务器的IP地址。

4.3、权威(限)域名服务器

**●**权限域名服务器负责管理某个区的域名。

**●**每一个主机的域名都必须在某个权限域名服务器处注册登记。因此权限域名服务器知道其管辖的域名与IP地址的映射关系。

**●**另外,权限域名服务器还知道其下级域名服务器的地址。

4.4、本地域名服务器

● 本地域名服务器不属于上述的域名服务器的等级结构

当一个主机发出DNS请求报文时,这个报文就首先被送往该主机的本地域名服务器

● 本地域名服务器起着代理的作用,会将该报文转发到上述的域名服务器的等级结构中。

每一个因特网服务提供者ISP,一个大学,甚至一个大学里的学院,都可以拥有一个本地域名服务器,它有时也称为默认域名服务器

本地域名服务器离用户较近,一般不超过几个路由器的距离,也有可能就在同一个局域网中。本地域名服务器的IP地址需要直接配置在需要域名解析的主机中

五、DNS的查询步骤

不难发现,其实我们只需要知道网址后,我们就知道DNS会查询几次了,第一次是根从根那拿到com过后那么第二次是com,在com里面找microsoft拿到microsoft后那么第三次就是microsoft,在microsoft里面找example ,**但按理来说不应该中找到example后就不用再发Q5了吗,为什么这里还会发Q5再去example里找呢?**其实说到这已经很明显了,这个网址肯定不是最终的网址,可能会是www.example.microsoft.com等。

下面我们描述一下 DNS 的查询步骤,从 DNS 解析 IP 再到 DNS 返回的一系列流程。

| 注意:通常情况下 DNS 会将查找的信息缓存在浏览器或者计算机本地中,如果有相同的请求到 | 来时,就不再会进行 DNS 查找,而会直接返回结果。

整个流程如下图所示:

1、用户在浏览器中输入网址 www.example.com 并点击回车后,查询会进入网络,并且由 DNS 解析器进行接收。

2、DNS 解析器会向根域名发起查询请求,要求返回顶级域名的地址。

3、根 DNS 服务器会注意到请求地址的前缀并向 DNS 解析器返回 com 的顶级域名服务器(TLD) 的 IP 地址列表。

4、然后,DNS 解析器会向 TLD 服务器发送查询报文。

5、TLD 服务器接收请求后,会根据域名的地址把权威 DNS 服务器的 IP 地址返回给 DNS 解析器。

6、最后,DNS 解析器将查询直接发送到权威 DNS 服务器。

7、权威 DNS 服务器将 IP 地址返回给 DNS 解析器

8、DNS 解析器将会使用 IP 地址响应 Web 浏览器

一旦 DNS 查找的步骤返回了 example.com 的 IP 地址,浏览器就可以请求网页了。

六、DNS查询类型

DNS 查找中会出现三种类型的查询。通过组合使用这些查询,优化的 DNS 解析过程可缩短传输距离。在理想情况下,可以使用缓存的记录数据,从而使 DNS 域名服务器能够直接使用非递归查询。

6.1、递归查询

在递归查询中,DNS 客户端要求 DNS 服务器(一般为 DNS 递归解析器)将使用所请求的资源记录响应客户端,或者如果解析器无法找到该记录,则返回错误消息。

6.2、迭代查询

在迭代查询中,如果所查询的 DNS 服务器与查询名称不匹配,则其将返回对较低级别域名空间具有权威性的 DNS 服务器的引用。然后,DNS 客户端将对引用地址进行查询。此过程继续使用查询链中的其他 DNS 服务器,直至发生错误或超时为止。

6.3、缓存查询

为了提高 DNS 的查询效率,并减轻根域名服务器的负荷和减少因特网上的DNS查询报文数量,在域名服务器中广泛地使用了高速缓存。高速缓存用来存放最近查询过的域名以及从何处获得域名映射信息的记录。

由于域名到IP地址的映射关系并不是永久不变,为保持高速缓存中的内容正确**,****域名服务器应为每项内容设置计时器并删除超过合理时间的项(例如,每个项目只存放两天)**。

而且不但在本地域名服务器中需要高速缓存,在用户主机中也很需要。许多用户主机在启动时从本地域名服务器下载域名和 IP 地址的全部数据库,维护存放自己最近使用的域名的高速缓存,并且只在从缓存中找不到域名时才向域名服务器查询。同理,主机也需要保持高速缓存中内容的正确性。

6.4、练习题

依旧是两道题来检验检验学习成果吧。

1、因为我们是递归查询,可以看上图我们每个设备只会发一次,然后等后面回给我消息,我再回给前面,所以选A。

那如果是迭代查询呢?那根据上图就是主机只发一次,但本地只发多次了

2、首先来看我们,域名服务器201.1.1.1最少发出的DNS查询肯定是0吧,这应该毋庸置疑,如果我们本地有就不用查询了,那么我们接着看,如果本地没缓存的话会是怎么样,但其实当你看完题后就会发现,这图就是用来唬人的,根据我们刚才第五点讲的,其实仅凭我们的域名就可以解出答案了,看完刚才的内容,这道题简直easy,答案是C。

七、DNS网络排查工具

nslookup 是一款用来解决 DNS 相关问题排查的工具。

它主要分为两种模式,一种是交互模式,一种是非交互模式。交互模式就是一问一答式的直到你想关闭为止,而非交互模式就是只执行一次

比如你要使用交互式,就直接在命令行中输入nslookup。

这样就会开始一个 nslookup 的命令提示符,然后你再输入想要查询的域名即可,如下所示:

非交互式就是直接输入 nslookup 你想要查询的内容即可,比如我们还以 baidu 为例子。

可以看到,我们前面是运行完用 Ctrl + c 关闭了的,而后面是运行完直接关闭了的。而且可以看到二者内容其实是一样的。

nslookup 一般用于查询下这这些常用的场景:

|-------------------|-------------------|------------------|
| 能够查询主机的 IP 地址 | 能够查询 IP 地址的域名 | 能够查询域名的邮件服务器 |

可以通过 nslookup -querytype 查询域名的邮件服务器,如下:

会分为两种查询结果,一种是 Non-authoritative answer,这表明我们想查询的这个网址是从本地 DNS cache 也就是 DNS 缓存中查询出来的,而不是从本地 DNS 经过 DNS 查询后得到的真实域名。

还有一种就是 Authoritative answers,这种就是本地 DNS 经过 DNS 查询后得到的真实域名。

上图还显示了 netease.com 邮件服务器的一些参数, origin 表示源地址, mail addr 表示邮件服务器的地址, serial 表示序列号, refresh 表示刷新间隔, retry 表示重试间隔, expire 表示过期时间,minumum 表示最大长度。

DHCP协议

DHCP 的全称是 Dynamic Host Configuration Protocol 动态主机配置协议。使用 DHCP 就能实现自动设置 IP 地址、统一管理 IP 地址分配。也就是不管你是在开会还是在工位干活,都省去了手动配置 IP 地址这一步繁琐的操作,同时 DHCP 也大大减少了可能由于你手动分配 IP 地址导致错误的几率。

DHCP 与 IP 密切相关,它是 IP 网络上所使用的协议。如果你想要使用 DHCP 提供服务的话,那么在整条通信链路上就需要 DHCP 服务器的存在,连接到网络的设备使用 DHCP 协议从 DHCP 服务器请求 IP 地址。DHCP 服务器会为设备分配一个唯一的 IP 地址。

| 除了 IP 地址外,DHCP 服务器还会把子网掩码,默认路由,DNS 服务器告诉你。

一、DHCP服务器

现在,你不需要手动配置 IP 地址,也不再需要管理 IP 地址了,管理权已经移交给了 DHCP 服务器,DHCP 服务器会维护 IP 地址池,在网络上启动时会将地址租借给启用 DHCP 的客户端。

由于 IP 地址是动态的(临时分配)而不是静态的(永久分配),因此不再使⽤的 IP 地址会自动返回 IP 地址池中进行重新分配。

| 那么DHCP服务器由谁维护呢?

网络管理员负责建立 DHCP 服务器,并以租约的形式向启用 DHCP 的客户端提供地址配置,啊,既然不需要我管理,那就很舒服了~

其实,这也是一个 DHCP 服务器的一个功能,DHCP 服务器通常为每个客户端分配一个唯一的动态 IP 地址,当该 IP 地址的客户端租约到期时,该地址就会更改。

唯一意思说的就是,如果你手动设置了一个静态 IP,同时 DHCP 服务器分配了一个动态 IP,这个动态 IP 和静态 IP 一样,那么必然会有一个客户端无法上网。

| 比如现在我使用虚拟机配置的静态 IP 是192.168.1.8,手机使用 DHCP 也同样配置了 | 192.168.1.8 的 IP 地址,此时我的虚拟机还没有接入网络,当我接入网络时,我怎样也连不上 | 虚拟机了,其实就是 IP 地址冲突造成的。

虽然 DHCP 服务器能提供 IP 地址,但是他怎么知道哪些 IP 地址空闲,哪些 IP 地址正在使用呢?

实际上,这些信息都配置在了数据库中,下面我们就来一起看一下 DHCP 服务器维护了哪些信息。

**●**网络上所有有效的 TCP/IP 配置参数

这些参数主要包括主机名(Host name)、DHCP 客户端(DHCP client)、域名(Domain name)、IP 地址(IP address)、网关(Netmask)、广播地址(Broadcast address)、默认路由 (default rooter)

**●**有效的 IP 地址和排除的 IP 地址,保存在 IP 地址池中等待分配给客户端

**●**为某些特定的 DHCP 客户端保留的地址,这些地址是静态 IP,这样可以将单个 IP 地址一致地分配给单个DHCP 客户端

好了,现在你应该知道 DHCP 服务器都需要保存哪些信息了,并且看过上面的内容,你也应该知道一个 DHCP 的组件有哪些了,下面我们就来聊一聊 DHCP 中都有哪些组件,这些组件缺一不可。

二、DHCP工作机制

DHCP 报文共有以下几种:

● DHCP DISCOVER :客户端开始 DHCP 过程发送的包,是 DHCP 协议的开始

● DHCP OFFER :服务器接收到 DHCPDISCOVER 之后做出的响应,它包括了给予客户端的 IP 租约过期时间、服务器的识别符以及其他信息

● DHCP REQUEST :客户端对于服务器发出的 DHCPOFFER 所做出的响应。在续约租期的时候同样会使用。

● DHCP ACK:服务器在接收到客户端发来的 DHCPREQUEST 之后发出的成功确认的报文。在建立连接的时候,客户端在接收到这个报文之后才会确认分配给它的 IP 和其他信息可以被允许使用。

● DHCP NAK :DHCPACK 的相反的报文,表示服务器拒绝了客户端的请求。

● DHCP RELEASE :一般出现在客户端关机、下线等状况。这个报文将会使 DHCP 服务器释放发出此报文的客户端的 IP 地址

● DHCP INFORM :客户端发出的向服务器请求⼀些信息的报文

● DHCP DECLINE : 当客户端发现服务器分配的 IP 地址无法使用(如 IP 地址冲突时),将发出此报文,通知服务器禁止使用该 IP 地址。

我们看下图,1、 我们主机首先用DISCOVER行为广播服务器,其中我们会携带事务ID、DHCP客户端的MAC地址、源主机的MAC地址,还有IP地址也就是广播地址与自身地址目的就是为了让服务器知道我们是谁

2、 服务器收到后,就会发一个OFFER,那此处也是含有服务器的MAC与IP地址,但此处我们的主机还没得到分配到的地址,故我们此处的目的地址其实还是广播地址全1,然后刚才的事务ID就派上用场了,我们客户主机就会拿到此事务ID进行比对,如果不是刚刚的事务ID就不会管。除此之外还有各种配置信息------IP地址、子网掩码、地址租期、默认网关、DNS服务器,其中我们的IP地址其实在发之前,我们的服务器还会用ARP广播看看此IP地址有没有被占用,如果没有它才会发放。

3、 嗯?我们看到,明明刚才的OFFER已经给我们发过IP了,此处我们REQUEST的源IP地址为什么又是全0了?你不妨想想,我们其实是会选择接受这个IP地址的,再加上其实会有很多服务器给我们发IP地址而我们只能接受一个,也就是当我们回完后,服务器才会在它自己的名单上把我们的IP地址给写上,如果不行服务器也不会写。所以在这个时候其实还没真正的IP地址,所以我们网络层还是靠事务ID来区分这个连接。但此处虽然目的是广播IP,但其实这个包内会涵盖我们接受提供IP的服务器的IP地址,目的就是为了让广播的对方看清楚,是你的那你再建立,不是那就不用再回了。

4、 那么我们服务器就会再回最后一个确认包,此时我们需要再做一次ARP请求,目的就是为了避免在REQUEST 中途我们的IP又被占了,若真被占了,那我们此处的ACK确认包就是谢绝报文,并重新连接;若没占,那么我们就正式连接了。

5、建立连接后,我们如果要续租,我们会直接在0.5倍租用期的时候发起续租,那么第一种情况,就是成功续租

那么第二种情况,就是服务器会发一个NACK ,也就是不租给你了,可能就是服务器这个IP地址会想用到别的地方,那么我们的状态就会直接回到一开始,让其重新DISCOVER。

第三种情况就是我们服务器不响应,因为我们此处发的是UDP,是很容易发生丢包的现象的,那么我们双方都不知道对方在干嘛了,此时我们就设置让客户端有一个超时重传机制,这个时间就是0.875倍的租用期。

那么如果真的重传到了我们的租用期后,我们其实是不会再重传的,我们会直接断掉当前连接,然后重新发起DHCP报文。

当然如果我们不想要这个IP了,我们也是能主动断掉的,就是发我们的RELEASE包就行了

HTTP 2.0

在谈论2.0之前,我想先问下为什么要有2.0,其实也就是在问1.0/1.1有什么不足之处。

一、最初的HTTP

HTTP 刚刚诞生之初只用于 web 端的内容获取,一般就是用于页面访问,那个时候的页面内容还不如现在这样丰富,交互场景也不是很多,也没有庞大繁杂的 CSS、JS ,页面加载速度非常快。但是随着 web 2.0 的出现以及更多的内容被展示、更精美的排版、更多的用户交互场景⼀起出现,导致页面的内容越来越大,使得页面加载速度越来越慢。、

二、HTTP的瓶颈

影响一个 HTTP 网络请求的因素主要有两个:带宽和延迟。

首先来说⼀下带宽,如果我们还停留在拨号上网阶段的话,带宽很容易出现瓶颈,因为单位时间内传输的数据量很小。但是现在随着光纤等通信技术的不断发展,10Mbps、100Mbps、甚至 1000 Mbps 进入了每个家庭,我们不用再担心带宽成为网络请求的瓶颈了,那么剩下的就只剩下延迟了。

而延迟又主要有下面三个方面:

|------------------------------|-------------------------------------------------------------------------------------------------------------------------|
| 浏览器阻塞(HOL blocking) | 浏览器会因为一些原因阻塞请求。浏览器对于同一个域名,同时只能有 6 个连接(这个根据浏览器内核不同可能会有所差异),超过浏览器最大连接数限制,后续请求就会被阻塞。 |
| DNS 查询(DNS Lookup) | 浏览器需要知道目标服务器的 IP 才能建立连接。将域名解析为 IP 的这个系统就是 DNS。这个通常可以利用 DNS 缓存结果来达到减少这个时间的目的。 |
| 建立连接(Initial connection) | HTTP 是基于 TCP 协议的,浏览器最快也要在第三次握手时才能捎带 HTTP 请求报文,达到真正的建立连接,但是这些连接无法复用会导致每次请求都经历三次握手和慢启动。三次握⼿在高延迟的场景下影响较明显,慢启动则对文件类大请求影响较大。 |

HTTP 1.0 有一个被抱怨最多的是连接无法复用,即当每次有新的请求时都会重新经历一次三次握手和四次挥手过程,并且连接的建立和释放需要耗费大量的服务器资源,在请求少的页面还尚能应对,不过随着请求的不断增多,HTTP 1.0 越来越难顶。

值得一提的是,HTTP 1.0 协议头里可以设置 Connection:Keep-Alive。在 header 里设置 Keep-Alive 可以在一定时间内确实是实现了复用连接,具体复用时间的长短可以由服务器控制,一般在 15s 左右。到 HTTP 1.1 之后 Connection 的默认值就是Keep-Alive,如果要关闭连接复用需要显式的设置 Connection:Close。

HTTP 还有一个被抱怨最多的问题就是它的队头阻塞(head of blocking),队头阻塞问题会导致带宽无法充分利用,导致后续的请求被阻塞。

假如有五个请求被同时发出,如果第一个请求没有处理完成,就会导致后续的请求也无法得到处理,如下图所示:

如果第一个请求没有被处理,那么 2 3 4 5 这四个请求会直接阻塞在客户端,等到请求 1 被处理完毕后,才能逐个发出。网络通畅的时候性能影响不大,不过一旦请求 1 因为某些原因没有抵达服务器,或者请求因为网络阻塞没有及时返回,影响的就是所有后续请求,导致后续请求无限阻塞下去,问题就变得比较严重了。

pipelining

不过在 HTTP 1.1 中,也提出了**流水线(pipelining)**的设计,pipelining 就被用来解决队头阻塞的问题,如下图所示:

虽然这种流水线的设计乍一看像是能够解决阻塞问题,因为右图中这三个请求没有等到响应到达后再进行发送,而是直接依次发送,但是实际上,并不是那么回事。

pipelining 并不是救世主,它也存在不少缺陷:

**●**因为只有幂等的请求比如 GET、HEAD 才能使用 pipelining ,非幂等请求比如 POST 则不能使用, 因为请求之间可能存在先后依赖关系。

(幂等可以简单理解为:现在有1次和100次请求,这两种请求无论请求的顺序如何都没有任何的关系。)

如果你能理解这个幂等关系的话,那你会发现这个pipelining显然会出大问题,比如我们购物的时候,总不可能还没点购买就给你把费用扣了吧

**●**队头阻塞问题并没有完全解决,因为服务器返回的响应还是要依次返回,也就是返回的请求时FIFO - 先发先回。

**●**绝大多数 HTTP 代理服务器不支持 pipelining。

**●**和不支持 pipelining 的老服务器协商有问题。

正是因为有这么多的问题,各大浏览器厂商要么是根本就不支持 pipelining,要么就是默认关掉了 pipelining 机制,而且启用的条件十分苛刻。

三、SPDY

虽然 HTTP1.0 和 HTTP 1.1 存在这么多问题,而且业界也是想出了各种优化手段,但是这些手段怎么说呢,都是治标不治本,直到 2020 年 Google 提出了 SPDY 的方案,大家才开始从正面看待和解决老版本 HTTP 协议本身的问题,这也直接加速了 HTTP 2.0 的诞生。

3.1、认识SPDY

SPDY 的目标在于解决 HTTP 的缺陷,即延迟和安全性。我们上面一直在讨论延迟,至于安全性,虽然我们上面没有具体聊,不过 HTTP 的明文传输确是个问题。如果以降低延迟为目标,应用层的 HTTP 和传输层的 TCP 都是都有调整的空间,不过 TCP 作为更底层协议存在已达数十年之久,其实现已深植全球的网络基础设施当中,如果要动必然伤经动骨,业界响应度必然不⾼,所以 SPDY 的手术刀对准的是 HTTP 。

**●**降低延迟,客户端的单连接单请求,服务端的 FIFO 响应队列都是延迟的大头。

**●**HTTP 最初设计都是客户端发起请求,然后服务端进行响应,服务端无法主动发送内容到客户端。

**●**压缩 HTTP header,HTTP 1.x 的 header 越来越膨胀,cookie 和 user agent 很容易让 header 的 size 增至1kb 大小甚至更多。而且由于 HTTP 的无状态特性,header 必须每次请求都重复携带,很浪费流量。

为了增加解决这些问题的可行性,聪明的 Google 公司一开始就避开了从传输层动手,而且打算利用开源社区的力量以提高扩散的力度,对于协议使用者来说,也只需要在请求的 header 里设置 user agent,然后在服务端做好支持即可,极大的降低了部署的难度。SPDY 的设计如:

可以看到,SPDY 位于 HTTP 之下,SSL 之上,这样可以轻松的兼容老版本的 HTTP 协议,SPDY 的功能分为基础功能和高级功能两部分,基础功能是默认启用的,高级功能需要手动启用。

3.2、SPDY的基础功能

|-----------------------------------|-------------------------------------------------------------------------------------------|
| 多路复用(multiplexing) | 多路复用通过多个请求共用一个连接的方式,降低了 TCP 连接建立和释放的开销,同时提高了带宽的利用率。 |
| 请求优先级(request prioritization) | 多路复用带来的⼀个问题是,在共享连接的基础上会存在一些关键请求被阻塞,SPDY 允许给每个请求设置优先级,这样重要的请求就会优先得到响应。 |
| header 压缩 | 前面提到的 HTTP 1.x 的 header 很多时候都是重复而且多余的。选择合适的压缩算法可以减小包的大小和数量。SPDY 对 header 的压缩率可以达到 80% 以上。 |

3.3、SPDY的高级功能

服务端推送,HTTP 只能由客户端发送,服务器只能被动发送响应。不过在开启服务端推送后,服务端通过 X-Associated-Content header 会告知服务器会有新的内容被推送过来

服务端暗示,和服务端推送所不同的是,服务端暗示不会推送内容,只是告诉客户端有新的内容产生,内容的下载还是需要客户端主动发起请求。服务端暗示通过 X-Subresources header 来通知,一般应用场景是客户端需要先查询服务端状态,然后再下载资源,可以节约一次查询请求。

四、初探HTTP 2.0

HTTP 2.0 也被写作 HTTP/2 ,它是超文本传输协议的 2.0 版本,因为 SPDY 的流行让 IETF 看到了优化后的效果,以及可以通过修改协议层来优化 HTTP,所以 IETF 开始决定正式考虑制定 HTTP 2.0 的计划,而且,SPDY的部分设计人员也被邀请参与了 HTTP 2.0 的设计。

HTTP2.0 在设计之初就与 SPDY 的设计目的和出发点不同,SPDY 更像是 Google 自家的一个产品,相当于自家的一个玩具,你怎么玩儿都行,而 HTTP 2.0 在设计之初就是为了普适性的这个目的,所以,一开始任何的设计都会关系到以后的维护问题,如果有什么瑕疵或者不足的地方可能会影响巨大,所以考虑的问题角度要非常严谨和慎重。

HTTP 2.0 在设计之初就有一些重要的前提:

客户端向服务器发送请求的这种基本模型不会改变。

原有的协议头不会改变,使用 http:// 和 https:// 的服务和应用不会做任何修改,不会有http2://。

使用 HTTP 1.x 的客户端和服务器可以平滑升级到 HTTP 2.0 上。

不识别 HTTP 2.0 的代理服务器可以将请求降级到 HTTP 1.x。

值得一提的是,客户端在和服务器确定是使用 HTTP1.x 还是 HTTP 2.0 之前,需要先确定对方是否支持 HTTP 2.0,所以这里必须要先进行协商,也就是客户端询问服务器,这样一来一回就多了一个 RTT 的延迟。 我们对 HTTP 1.x 的修改就是为了降低延迟,现在又多了一个 RTT,这样显然是无法接受的。Google 制定 SPDY 协议的时候也遇到了这个问题,他们采取的做法是强制协商在 SSL 层完成,还因此制定了一个 TLS 的拓展,叫做 NPN(Next Protocol Negotiation)。虽然 HTTP 2.0 也采用了相同的方式,不过经过讨论后,最终 HTTP 2.0 没有强制要走 SSL 层,HTTP 2.0 没有使用 NPN,却制定了一个 TLS 的 拓展叫做 ALPN(Application Layer Protocol Negotiation),现在,SPDY 也打算迁移到 ALPN 了。

五、HTTP 2.0的主要变化

HTTP 2.0 自从设计到诞生以来,发生了很多变化,不过对于开发人员和厂商来说,影响比较大的就几点:

5.1、二进制格式

HTTP 1.x 的诞生使用的是明文协议,它的格式主要由三部分构成:请求行(request line) 、请求头 (header) 和报文体(body),要识别这三部分必须要做协议解析,而协议解析是基于文本的,基于文本的解析存在多样性的缺陷,而二进制格式只能识别 0 和 1 ,比较固定,基于这种考量,HTTP 2.0 决定采用二进制格式,实现方便而且健壮性强。

下面这幅图很好的诠释了 HTTP1.x 和 HTTP 2.0 使用的不同报文格式。

在 HTTP 2.0 报文中,length 定义了整个 frame 的开始到结束,type 定了 frame 的类型,一种有十种,flags 定义了一些重要的参数,stream id 用作流控制,剩下的 payload 就是 request 的正文。

虽然 HTTP 2.0 报文格式看上去和 HTTP 1.x 的完全不同,但是实际上 HTTP 2.0 并没有改变 HTTP 1.x 的语义,它只是在 HTTP 1.x 的基础上封装了一层,如下图所示:

从上图可以看到,HTTP 1.x 中的请求行、请求头被 HTTP 2.0 封装成为了 HEADERS Frame,而 HTTP 1.x 中的报文体被 HTTP 2.0 封装成为了 Data Frame。调试的时候浏览器会把 HTTP 2.0 的 frame 自动还原成 HTTP 1.x 的格式。

5.2、连接共享

我们上面聊到,HTTP 1.x 并没有真正意义上的解决连接复用问题,所以 HTTP 2.0 要解决的一大难题就是连接共享(MultiPlexing),连接共享意味着客户端与服务器之间也只需要一个连接即可,这样即使来自很多流的数据包也能够混合在一起通过同样连接传输,再根据不同帧首部的 stream id 标识符重新连接将不同的数据流进行组装

| 什么是stream流?

stream 是连接中的一个虚拟信道,可以承载双向消息传输。每个流有唯一整数标识符。为了防止两端 streaam id 冲突,客户端发起的流具有奇数 id,服务器端发起的流具有偶数 id。

我们上面提到 HTTP 1.x 没有真正解决连接共享还有一个主要的因素就是无法对不同的请求设置优先级,这样会导致关键请求被阻塞。而 HTTP 2.0 你可以对不同的 stream 设置不同的优先级,stream 之间也可以设置依赖,依赖和优先级都可以动态调整,这样就会解决关键请求被阻塞的问题。

5.3、头部压缩

上面还聊到了 HTTP1.x 中的 header 由于 cookie 和 user agent 不存在记忆性,这样导致每次都要带着这些头重新发送请求,HTTP 2.0 使用 encoder 来减少传输的 header 大小,通信双方会各自缓存一份 header 字段表,这样能够避免重复传输 header ,也能够减小传输的大小。HTTP 2.0 采用的是 HPACK 压缩算法

| 这种压缩算法的主要思想可以参考官方文档 https://httpwg.org/specs/rfc7541.html

5.4、服务端推送

服务端推送(Server Push)我们上面也已经聊过,HTTP 2.0 能够以的方式将客户端的内容预先发送出去,正因为没有发起请求,建立连接等操作,所以静态资源通过服务端推送的方式可以极大地提升速度。服务端推送还有一个更大的优势:缓存缓存也能够在不同页面之间共享缓存资源

需要注意下面几个点:

1、推送遵循同源策略;

2、这种服务端的推送是基于客户端的请求响应来确定的。

当服务端需要主动推送某个资源时,便会发送一个 Frame Type 为 PUSH_PROMISE 的 frame ,里面带了 PUSH 需要新建的 stream id。意思是告诉客户端:接下来我要用这个 id 向你发送东西,客户端准备好接着。客户端解析 frame 时,发现它是一个 PUSH_PROMISE 类型,便会准备接收服务端要推送的流。

六、HTTP 2.0的缺陷

1、 HTTP 2.0 带给我们最惊艳的莫过于多路复用了,虽然多路复用有种种好处,但是大家可以想一下, 多路复用虽然好,但是它是建立在 TCP 连接的基础上,在连接频繁的情况下,是不是会对 TCP 连接造成压力,这个角度来讲,TCP 很容易成为性能瓶颈

2、 还有一点,使用 HTTP 2.0 会增加一次 TLS 握手过程,增加 RTT,这个我们上面也说到了

3、 在 HTTP 2.0 中,多个请求是在同一个 TCP 管道中,这样当 HTTP 2.0 出现丢包时,整个 TCP 都要开始等待重传,那么就会阻塞该 TCP 连接中的所有请求

HTTP 3.0

我们大家知道,HTTP 是应用层协议,应用层产生的数据会通过传输层协议作为载体来传输到互联网上的其他主机中,而其中的载体就是 TCP 协议,这是 HTTP 2 之前的主流模式。

但是随着 TCP 协议的缺点不断暴露出来,新一代的 HTTP 协议 ------ HTTP 3.0 毅然决然切断了和 TCP 的联系,转而拥抱了 UDP 协议,这么说不太准确,其实 HTTP 3.0 其实是拥抱了 QUIC 协议,而 QUIC 协议是建立在 UDP 协议基础上的。

一、HTTP 3.0的诞生

HTTP 3.0 于 2022 年 6 月 6 日正式发布,IETF 把 HTTP 3.0 标准制定在了 RFC 9114 中,HTTP 3.0 其实相较于 HTTP 2.0 要比 HTTP 2.0 相较于 HTTP 1.1 的变化来说小很多,最大的提升就在于效率替换 TCP 协议为 UDP 协议HTTP 3.0 具有更低的延迟,它的效率甚至要比 HTTP 1.1 快 3 倍以上

其实每一代 HTTP 协议的不断发展都是建立在上一代 HTTP 的缺点上的,就比如 HTTP 1.0 最大的问题就是传输安全性和不支持持久连接上,针对此出现了 HTTP 1.1 ,引入了 Keep-Alive 机制来保持长链接和 TLS 来保证通信安全性。但此时的 HTTP 协议并发性还做的不够好。

随着网络的不断发展,每个网站所需资源(CSS、JavaScript、图像等)的数量逐年增加,浏览器发现自己在获取和呈现网页时需要越来越多的并发性。。但是由于 HTTP 1.1 只能够允许客户端/服务器进行一次 HTTP 请求交换,因此在网络层获得并发性的唯一方法是并行使用多个 TCP 连接到同一个源,不过使用多个 TCP 链接就失去了 keep-Alive 的意义

然后出现了 SPDY 协议,主要解决 HTTP 1.1 效率不⾼的问题,包括降低延迟,压缩 header 等等,这些已经被 Chrome 浏览器证明能够产生优化效果,后来 HTTP 2.0 基于 SPDY ,并且引入了流 (Stream) 的概念,它允许将不同的 HTTP 交换多路复用到同一个 TCP 连接上,从而达到让浏览器重用 TCP 链接的目的

TCP 的主要作用是以正确的顺序将整个字节流从一个端点传输到另一个端点,但是当流中的某些数据包丢失时,TCP 需要重新发送这些丢失的数据包,等到丢失的数据包到达对应端点时才能够被 HTTP 处理,这被称为 TCP 队头阻塞问题

那么可能就会有人考虑到去修改 TCP 协议,其实这已经是⼀件不可能完成的任务了。因为 TCP 存在的时间实在太长,已经充斥在各种设备中,并且这个协议是由操作系统实现的,更新起来不大现实。

基于这个原因,Google 就更起炉灶搞了一个基于 UDP 协议的 QUIC 协议,并且使用在了 HTTP/3 上,HTTP/3 之前名为 HTTP-over-QUIC,从这个名字中我们也可以发现,HTTP/3 最大的改造就是使用了 QUIC。

HTTP 2.0与HTTP 3.0的不同

HTTP/2是对现有"TCP公路"的优化改造,而HTTP/3是直接重建了一条"QUIC高速公路"。

其中最核心的区别是传输层协议 不同:HTTP/2仍基于TCPHTTP/3基于QUIC(底层是UDP)

对比维度 HTTP/2 HTTP/3
传输层协议 TCP QUIC(基于UDP)
多路复用 支持(二进制分帧,同一TCP连接上多流并行) 支持(基于QUIC流,每个流独立)
队头阻塞 存在(TCP层队头阻塞,一个包丢失阻塞所有流) 不存在(QUIC流独立,一个流丢包不影响其他流)
连接建立延迟 较高(TCP握手1RTT + TLS握手1-2RTT) 较低(首次连接1RTT,后续0RTT)
连接迁移 不支持(基于四元组,网络切换需重新连接) 支持(基于连接ID,网络切换无缝连接)
头部压缩 HPACK(基于静态/动态表,需按序更新) QPACK(类似HPACK,但适应QUIC特性)
安全性 TLS可选(但主流浏览器要求TLS) 加密强制(QUIC内置TLS 1.3)
错误恢复 慢(依赖TCP重传,可能超时) 快(QUIC有前向纠错和快速重传)
部署情况 广泛支持(所有现代浏览器和服务器) 逐步普及(浏览器和CDN已支持,服务器支持增长中)
网络兼容性 好(TCP被普遍放行) 有挑战(部分网络可能阻断UDP 443端口)
适用场景 稳定网络、内部系统、兼容性要求高 移动网络、高丢包环境、实时应用

结语

那么关于DNS、DHCP、HTTP2.0/3.0讲解就到这里了。

这也是我们计网系统讲解的最后一篇博客了,剩下更也只会更一些零碎的知识了。

我是YYYing, 后面还有更精彩的内容,希望各位能多多关注支持一下主包。

无限进步, 我们下次再见。


---⭐️ 封面自取 ⭐️---

相关推荐
小李独爱秋2 小时前
计算机网络经典问题透视:物联网和M2M通信的关系是怎样的?
运维·服务器·网络·物联网·计算机网络·m2m
czy87874752 小时前
TCP 和 IP 协议的异同
网络·网络协议·tcp/ip
zfj3212 小时前
如何用tcpdump诊断tcp数据包问题
网络·tcp/ip·tcp·tcpdump
掘根2 小时前
【jsonRpc项目】Dispatcher模块
android·网络
独行soc2 小时前
2026年渗透测试面试题总结-10(题目+回答)
android·网络·python·安全·web安全·渗透测试·安全狮
Mcband2 小时前
OpenFeign - 底层原理揭秘:动态代理 + HTTP 客户端如何工作
网络·网络协议·http
amao99882 小时前
MIT-OS2022 lab4 Traps陷阱指令和系统调用
网络
AI视觉网奇2 小时前
https 证书 生成安装笔记
笔记·网络协议·https
君鼎2 小时前
计算机网络第七章:网络安全学习总结
学习·计算机网络