HTTPS、HTTP2、HTTP3介绍

695 阅读6分钟

HTTPS

1.客户端发送一个消息,以明文传输 TLS 版本信息、加密套件候选列表、压缩算法候选列表等信息,重点还有一个随机数

2.服务端也会发送一个消息,告诉客户端选择使用的协议版本、加密套件、压缩算法等,也有一个随机数

3.随后服务端有一个非对称密钥,将证书发送给客户端,证书里有非对称密钥的公钥

4.客户端从信任的CA中拿到公钥解密这个证书,成功说明网站可信.并计算Pre-Master随机数,以非对称密钥的公钥加密

5.服务端用非对称加秘的私钥解密拿出Pre-Master随机数

6客户端与服务端同时计算数据传输时的对称公钥;对称密钥=客户端的随机数+服务端的随机数+Pre-Master随机数

HTTP2

HTTP 1.1 在应用层以纯文本的形式进行通信。每次通信都要带完整的 HTTP 头,这样在实时性、并发性上都存在问题。所以HTTP 2.0 会对 HTTP 的头进行一定的压缩,开发了专门的“HPACK”算法,在客户端和服务器两端建立“字典”,用索引号表示重复的字符串,还釆用哈夫曼编码来压缩整数和字符串。

HTTP 2.0 协议将一个 TCP 的连接中,分成多个流,每个流都有自己的 ID,是一串有先后顺序的数据流,这些数据流按照次序组装起来.流同时发送多个“碎片化”的消息,这就是常说的“多路复用”多个往返通信都复用一个连接来处理。

HTTP/2 还在一定程度上改变了传统的“请求 - 应答”工作模式,服务器不再是完全被动地响应请求,也可以新建“流”主动向客户端发送消息。比如,在浏览器刚请求 HTML 的时候就提前把可能会用到的 JS、CSS 文件发给客户端,减少等待的延迟,这被称为“服务器推送”

HTTP 2.0 还将所有的传输信息分割为更小的帧,并对它们采用二进制格式编码。常见的帧有 Header 帧,用于传输 Header 内容,并且会开启一个新的流。再就是 Data 帧,用来传输正文实体。多个 Data 帧属于同一个流。在“流”的层面上看,消息是一些有序的“帧”序列,而在“连接”的层面上看,消息却是乱序收发的“帧”。多个请求 / 响应之间没有了顺序关系,不需要排队等待,在应用层上也就不会再出现“队头阻塞”问题,降低了延迟,大幅度提高了连接的利用率。

通过这两种机制,HTTP 2.0 的客户端可以将多个请求分到不同的流中,然后将请求内容拆成帧,进行二进制传输。这些帧可以打散乱序发送, 然后根据每个帧首部的流标识符重新组装,并且可以根据优先级,决定优先处理哪个流的数据。

HTTP3.0

HTTP 2.0 虽然大大增加了并发性,但还是有问题的。因为 HTTP 2.0 也是基于 TCP 协议的,TCP 协议在处理包时是有严格顺序的。

假如客户端用 TCP 发送了三个包,但服务器所在的操作系统只收到了后两个包,第一个包丢了。那么内核里的 TCP 协议栈就只能把已经收到的包暂存起来,“停下”等着客户端重传那个丢失的包,这样就又出现了“队头阻塞”

这种“队头阻塞”是 TCP 协议固有的,所以Google 的 QUIC 协议基于UDP

QUIC 的基本数据传输单位是包(packet)和帧(frame),一个包由多个帧组成,包面向的是“连接”,帧面向的是“流”。

连接机制

QUIC 基于 UDP,根本没有握手和挥手,所以QUIC 也基于 UDP 实现了可靠传输.在 QUIC 自己的逻辑里面维护连接的机制,是以一个 64 位的随机数作为 ID 来标识,而且 UDP 是无连接的,所以当 IP 或者端口变化的时候,只要 ID 不变,就不需要重新建立连接。

假如手机由 4G 切换到 WiFi。这时 IP 地址会发生变化,TCP 就必须重新建立连接。而 QUIC 连接里的两端连接 ID 不会变,所以连接在“逻辑上”没有中断,它就可以在新的 IP 地址上继续使用之前的连接,消除重连的成本,实现连接的无缝迁移。

重传机制

在 TCP 里面超时的采样存在不准确的问题。例如,发送一个包,序号为 100,发现没有返回,于是再发送一个 100,过一阵返回一个 ACK101。这个时候客户端知道这个包肯定收到了,但是往返时间是多少呢?是 ACK 到达的时间减去后一个 100 发送的时间,还是减去前一个 100 发送的时间呢?事实是,第一种算法把时间算短了,第二种算法把时间算长了。

QUIC 也有个序列号,是递增的。QUIC 还定义了一个 offset 来记录数据流。任何一个序列号的包只发送一次,下次就要加一了。例如,发送一个包,序号是 100,发现没有返回;再次发送的时候,序号就是 101 了;如果返回的 ACK 100,就是对第一个包的响应。如果返回 ACK 101 就是对第二个包的响应,RTT 计算相对准确。

无阻塞的多路复用

同 HTTP 2.0 一样,同一条 QUIC 连接上可以创建多个 stream,来发送多个 HTTP 请求。但是,QUIC 是基于 UDP 的,一个连接上的多个 stream 之间没有依赖。这样,假如 stream2 丢了一个 UDP 包,后面跟着 stream3 的一个 UDP 包,虽然 stream2 的那个包需要重传,但是 stream3 的包无需等待,就可以发给用户。

流量控制

QUIC 的流量控制也是通过滑动窗口.在一个连接上控制窗口,而且还在一个连接中的每个 stream 控制窗口。

QUIC 的 ACK 是基于 offset 的,每个 offset 的包来了,进了缓存,就可以应答,应答后就不会重发,中间的空挡会等待到来或者重发即可,而窗口的起始位置为当前收到的最大 offset,从这个 offset 到当前的 stream 所能容纳的最大缓存,是真正的窗口大小。显然,这样更加准确。

参考资料:

<极客时间>-趣谈网络协议