Dawn's Blogs

分享技术 记录成长

0%

软件架构设计读书笔记 (2) HTTP HTTPS QUIC

HTTP

HTTP 协议主要有三个版本,分别是 1996 年发布的 HTTP 1.0、1999 年发布的 HTTP 1.1 以及 2015 年发布的 HTTP 2。

HTTP 1.0

在 HTTP 1.0 中,默认发出一个请求就建立一个 TCP 连接。但是可以使用 Keep-Alive 和 Content-Length 来实现持久连接

  • Keep-Alive:用于声明这个字段是持久连接,多个 HTTP 请求都在同一个 TCP 连接上。
  • Content-Length:之前服务器响应完成就会关闭连接,而在持久连接中客户端不知道服务器的数据是否发送完成,所以需要 Content-Length 字段来告知数据长度

但是 Content-Length 字段有一个缺点,如果服务器使用了压缩,那么在生成 Header 时并不知道压缩之后的长度,所以无法生成 Content-Length。

所以在 HTTP 1.0 中,压缩和持久连接是冲突的。

HTTP 1.1

分块传输编码 chunk

在 HTTP 1.1 中,Keep-Alive 变成了默认选项,也可以利用 Content-Length 字段,让客户端判断服务器响应是否结束。但是因为 Content-Length 的缺点,所以引入了 Chunk 机制(分块传输编码)

在响应 Header 中添加 Transfer-Encoding: chunked,Body 中可以采用分块传输。分块包含十六进制的长度值和对应长度的数据内容,长度值独占一行,数据从下一行开始。最后以一个长度值为 0 的分块来表示资源结束

pipeline

尽管 HTTP 1.0 中的已经引入了长连接模式,但是 HTTP 1.0 中在收到上一次请求之后才能发出下一次请求。

在 HTTP 1.1 中改进了这个问题,引入了 Pipeline 机制。在没有收到响应之前,就可以发出之后的请求。

image-20230619204542901

但是不管是 HTTP 1.0 还是 Pipeline,都有个问题就是队头阻塞。因为服务器的响应顺序必须是请求发出的顺序,所以如果前面的响应处理流程缓慢,则会延缓后面请求响应的处理。

由于队头阻塞的问题,Pipeline 的推广并不是很成功。

HTTP 2

HTTP 2.0 中,帧(Frame)是传输的最小单位,每一个帧都附带一个 ID 用于标识这个帧属于哪个流,从而可以通过不同流重组出 HTTP 请求和响应,被称为 HTTP 2 多路复用技术。HTTP 与同一个服务器只维护一个连接

这样就缓解了队头阻塞问题。

Header 压缩

HTTP 2 的另一个提高效率的方法就是使用头部压缩,HTTP 2 专门设计了针对于 Header 压缩的算法。

HTTP 2 使用的头部压缩算法是 hpack 算法,其基本思想就是缓存头部的数据,如果头部键值已经存在直接使用索引进行传输。未缓存的数据,可以采用哈夫曼编码进行传输。

img

HTTPS

HTTPS = HTTP + TLS,HTTPS 可以保证 HTTP 协议的内容的机密性和完整性。

TLS 握手

TLS 在传输数据之前会进行握手,TLS 握手的作用就是交换证书(公钥)、对称密钥等信息。

  1. 客户端请求:会给服务器提供以下信息,支持 TLS 的版本、客户端生成的随机数、支持的加密算法等。
  2. 服务器响应:如果服务器接受客户端的请求,则向客户端回复响应。服务器同样会给客户端提供以下信息:确认使用的 TLS 版本、服务器生成的随机数、服务器选定的加密算法等。如果协商出的加密算法需要证书,则也会发送自己的证书。
  3. 客户端确认:此时通信采用协商出的加密方式进行,客户端向服务器发送的信息包括:客户端的证书(可选)、以服务器公钥加密的对称密钥(对称密钥通过两个随机数计算出)。
  4. 服务器确认:服务器通过私钥解密得到对称密钥,此后所有的通信通过对称密钥以对称加密的形式传输。

TLS 握手完成后,安全连接已经建立,之后的通信采用协商出的对称加密算法进行传输。因为 TLS 位于 TCP 和 HTTP 之间所以上层协议 HTTP 是对其无感知的。

CA 证书

至于如何验证服务器的证书,就引入了 CA。CA 就是一个可以信任的机构,用于颁发证书和验证证书

但是又回到了原来的问题,如何验证 CA 的证书?答案就是给 CA 颁发证书,CA 的证书由 CA 的上一级 CA 颁发。而根 CA 是有限可数的,已经内置进了浏览器和操作系统中,我们无条件的信任根 CA。

image-20230619212844398

QUIC

HTTP 3 的涉及重点在于用 UDP 替换 TCP,HTTP 3 使用 QUIC(Quick UDP Internet Connections)作为底层协议

QUIC 取代了 TCP 的部分功能,实现了 SSL/TLS 的所有功能,最后它还取代了 HTTP 2 的部分功能(帧,HTTP 2 多路复用)。

image-20230619213913179

下面介绍 QUIC 的几个特性。

不丢包

TCP 通过 ACK 和重传来保证不丢包的问题,而在 QUIC 中采用 Raid 算法来解决。

Raid 5 算法就是每发送 n 个数据包,就发送一个冗余包,冗余包是通过 n 个数据包异或得到的。这样如果其中有一个包丢失了,就可以通过冗余包和其他包计算得到。如果丢失的数据包超过一个,则还是需要重传(不过已经大大降低了重传的几率)。

Raid 6 算法更进一步提高可靠性,生成两个冗余包,这就允许丢失两个数据包。数据恢复的过程就相当于解一个二元一次方程组。

对于 QUIC 来说,采用了 Raid5 算法,每发送 10 个数据包构建一个冗余包。

更少的 RTT

在 HTTPS 中,需要实现 TCP 3次握手和 TLS 4 次握手,共需要 3.5 RTT。

QUIC 实现了 TLS1.3 协议,首次握手 1RTT,PSK 过期前再握手 0RTT

在这里插入图片描述

连接迁移

在移动端上可能客户端的 IP 会一直变化,意味着需要频繁的建立和关闭连接。

QUIC 不再使用 IP 和端口号标识连接,而是让客户端生成一个 64 位的数字标识连接。虽然客户端 IP 和端口号一直在漂移,但是 64 位的连接标识符没有发生变化。对于上层应用来说,就感觉这条连接一直存在没有中断过。