HTTP 3

HTTP/1.1的缺陷

1.高延迟–带来页面加载速度的降低

网络延迟问题:由于队头阻塞(Head-Of-Line Blocking),导致带宽无法被充分利用。队头阻塞是指当顺序发送的请求序列中的一个请求因为某种原因被阻塞时,在后面排队的所有请求也一并被阻塞,会导致客户端迟迟收不到数据。

2.无状态特性–带来的巨大HTTP头部

由于报文Header一般会携带"User Agent"“Cookie”“Accept”"Server"等许多固定的头字段,多达几百字节甚至上千字节,但Body却经常只有几十字节(比如GET请求、204/301/304响应),成了不折不扣的“大头儿子”。Header里携带的内容过大,在一定程度上增加了传输的成本。更要命的是,成千上万的请求响应报文里有很多字段值都是重复的,非常浪费。

3.明文传输–带来的不安全性

HTTP/1.1在传输数据时,所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份,这在一定程度上无法保证数据的安全性。

4.不支持服务器推送消息

HTTP/2 新特性

HTTP/2基于SPDY,专注于性能,最大的一个目标是在用户和网站间只用一个连接。

1.二进制传输

HTTP/2传输数据量的大幅减少,主要有两个原因:以二进制方式传输和Header 压缩。

2.Header 压缩

  • 在客户端和服务器端使用“首部表”来跟踪和存储之前发送的键-值对,对于相同的数据,不再通过每次请求和响应发送;
  • 首部表在HTTP/2的连接存续期内始终存在,由客户端和服务器共同渐进地更新;
  • 每个新的首部键-值对要么被追加到当前表的末尾,要么替换表中之前的值

例如下图中的两个请求, 请求一发送了所有的头部字段,第二个请求则只需要发送差异数据,这样可以减少冗余数据,降低开销
在这里插入图片描述

3.多路复用

多路复用很好的解决了浏览器限制同一个域名下的请求数量的问题,同时也更容易实现全速传输,毕竟新开一个 TCP 连接都需要慢慢提升传输速度。

  • 同域名下所有通信都在单个连接上完成。
  • 单个连接可以承载任意数量的双向数据流。
  • 数据流以消息的形式发送,而消息又由一个或多个帧组成,多个帧之间可以乱序发送,因为根据帧首部的流标识可以重新组装。

这一特性,使性能有了极大提升:

  • 同个域名只需要占用一个 TCP 连接,使用一个连接并行发送多个请求和响应,这样整个页面资源的下载过程只需要一次慢启动,同时也避免了多个TCP连接竞争带宽所带来的问题。
  • 并行交错地发送多个请求/响应,请求/响应之间互不影响。
  • 在HTTP/2中,每个请求都可以带一个31bit的优先值,0表示最高优先级, 数值越大优先级越低。有了这个优先值,客户端和服务器就可以在处理不同的流时采取不同的策略,以最优的方式发送流、消息和帧。
    在这里插入图片描述
    如上图所示,多路复用的技术可以只通过一个 TCP 连接就可以传输所有的请求数据。

4.Server Push

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

另外需要补充的是,服务端可以主动推送,客户端也有权利选择是否接收。如果服务端推送的资源已经被浏览器缓存过,浏览器可以通过发送RST_STREAM帧来拒收。主动推送也遵守同源策略,换句话说,服务器不能随便将第三方资源推送给客户端,而必须是经过双方确认才行。

5.提高安全性

HTTP/2 的缺点

HTTP/2的缺点主要有以下几点:

  • TCP 以及 TCP+TLS建立连接的延时
    ①在建立TCP连接时,需要和服务器进行三次握手来确认连接成功,需要在消耗完1.5个RTT之后才能进行数据传输。
    ②进行TLS连接,大致是需要1~2个RTT。
  • TCP的队头阻塞并没有彻底解决
    当出现了丢包时,HTTP/2 的表现反倒不如 HTTP/1。TCP为了保证可靠传输,有个特别的“丢包重传”机制,丢失的包必须要等待重新传输确认,HTTP/2出现丢包时,整个 TCP 都要开始等待重传,那么就会阻塞该TCP连接中的所有请求。而对于 HTTP/1.1 来说,可以开启多个 TCP 连接,出现这种情况反到只会影响其中一个连接,剩余的 TCP 连接还可以正常传输数据。
  • TCP不支持流级复用
    TCP允许在应用层之间建立多个逻辑连接,但不允许在一个TCP流中复用数据包。使用HTTP/2时,浏览器只能与服务器打开一个TCP连接,并使用同一个连接来请求多个对象,如CSS、JavaScript等文件。在接收这些对象的同时,TCP会将所有对象序列化在同一个流中。因此,它不知道TCP段的对象级分区。

HTTP/3 新特性

在这里插入图片描述
QUIC基于UDP,而UDP是“无连接”的,不需要“握手”和“挥手”,所以比TCP来得快。此外QUIC也实现了可靠传输,保证数据一定能够抵达目的地。
还引入了类似HTTP/2的“流”和“多路复用”,单个“流"是有序的,可能会因为丢包而阻塞,但其他“流”不会受到影响。具体来说QUIC协议有以下特点:

  • 实现了类似TCP的流量控制、传输可靠性的功能。
    虽然UDP不提供可靠性的传输,但QUIC在UDP的基础之上增加了一层来保证数据可靠性传输。它提供了数据包重传、拥塞控制、调整传输节奏以及其他一些TCP中存在的特性。可以更有效地利用可用的网络带宽,从而获得更好的吞吐量。
    QUIC协议不依赖于特定的拥塞控制算法,并提供了一个可插拔的接口,允许用户实验。默认使用了 TCP 协议的 Cubic 拥塞控制算法。
    流量控制,QUIC提供了基于stream和connection两种级别的流量控制,既需要对单个 Stream 进行控制,又需要针对所有 Stream 进行总体控制。
    QUIC连接级流控,用以限制 QUIC 接收端分配给连接的总缓冲区,避免服务器为某个客户端分配任意大的缓存。连接级流控与流级流控的过程基本相同,但转发数据和接收数据的偏移限制是所有流中的总和。

  • 实现了快速握手功能。
    TCP可靠传输协议需要进行三次握手,正是因为三次握手,所以需要额外消耗1.5 RTT。QUIC基于UDP,可以实现使用0-RTT或者1-RTT来建立连接,这意味着QUIC可以用最快的速度来发送和接收数据,这样可以大大提升首次打开页面的速度。0RTT 建连可以说是 QUIC 相比 HTTP2 最大的性能优势。
    在这里插入图片描述

  • 集成了TLS加密功能。
    目前QUIC使用的是TLS1.3,其中最重要的一点是减少了握手所花费的RTT个数。

  • 多路复用,彻底解决TCP中队头阻塞的问题
    和TCP不同,QUIC实现了在同一物理连接上可以有多个独立的逻辑数据流。这些数据流并行在同一个连接上传输,且多个数据流之间间的传输没有时序性要求,也不会互相影响。实现了数据流的单独传输,就解决了TCP中队头阻塞的问题。

TCP传输过程中会把数据拆分为一个个按照顺序排列的数据包,这些数据包通过网络传输到了接收端,接收端再按照顺序将这些数据包组合成原始数据,这样就完成了数据传输。

但是如果其中的某一个数据包没有按照顺序到达,接收端会一直保持连接等待数据包返回,这时就会阻塞后续请求。这就发生了TCP队头阻塞。
在这里插入图片描述
QUIC的单个数据流可以保证有序交付,但多个数据流之间可能乱序。这意味着单个数据流的传输是按序的,但是多个数据流中接收方收到的顺序可能与发送方的发送顺序不同!

也就是说同一个连接上面的多个数据流之间没有任何依赖(不要求按照顺序到达),即使某一个数据包没有达到,也只会影响自己这个数据流,并不会影响到到其他的数据流。
在这里插入图片描述

  • 更好的错误处理能力:QUIC使用增强的丢失恢复机制和转发纠错功能,以更好地处理错误数据包。
  • 连接迁移
    对于TCP连接的识别,基于四元组(源 IP、源端口、目的 IP、目的端口)。在网络切换的场景中,比如手机切换网络,那么自身的ip就会发生变化。这就导致之前的TCP连接就会失效,就需要重新建立。
    这一点上,QUIC进行了优化。
    QUIC协议使用特有的UUID来标记每一次连接,在网络环境发生变化时,只要UUID不变,就能继续传输数据。QUIC 连接使用一个 64 位的随机数,这个随机数被称为 Connection ID,只要 Connection ID 没有变化,那么连接依然可以维持。

在QUIC中,数据流由传输层本身提供,而在HTTP/2中,流由HTTP层完成。
由于数据流互相独立,HTTP/2中使用的头部压缩算法如果不做改动,会造成队头阻塞。

QUIC 连接的建立流程

QUIC在握手过程中使用Diffie-Hellman算法协商初始密钥,初始密钥依赖于服务器存储的一组配置参数,该参数会周期性的更新。初始密钥协商成功后,服务器会提供一个临时随机数,双方根据这个数再生成会话密钥。客户端和服务器会使用新生的的密钥进行数据加解密。

以上过程主要分为两个步骤:初始握手(Initial handshake)、最终(与重复)握手(Final (and repeat) handshake)

Diffie–Hellman (以下简称DH)密钥交换是一个特殊的交换密钥的方法。它是密码学领域内最早付诸实践的密钥交换方法之一。 DH可以让双方在完全缺乏对方(私有)信息的前提条件下通过不安全的信道达成一个共享的密钥。此密钥用于对后续信息交换进行对称加密。

初始握手(Initial handshake)

连接开始建立时,客户端会向服务端发送一个打招呼信息,(inchoate client hello (CHLO)),因为是初次建立,所以,服务端会返回一个拒绝消息(REJ),表明握手未建立或者密钥已过期。
在这里插入图片描述
但,这个拒绝消息中还会包含更多的信息(配置参数),主要有:

  • Server Config:一个服务器配置,包括服务器端的Diffie-Hellman算法的长期公钥(long term Diffie-Hellman public value)
  • Certificate Chain:用来对服务器进行认证的信任链
  • Signature of the Server Config:将Server Config使用信任链的叶子证书的public key加密后的签名
  • Source-Address Token:一个经过身份验证的加密块,包含客户端公开可见的IP地址和服务器的时间戳。

在客户端接收到拒绝消息(REJ)之后,客户端会进行数据解析,签名验证等操作,之后会将必要的配置缓存下来。

同时,在接收到REJ之后,客户端会为这次连接随机产生一对自己的短期密钥(ephemeral Diffie-Hellman private value) 和 短期公钥(ephemeral Diffie-Hellman public value)。

之后,客户端会将自己刚刚产生的短期公钥打包一个Complete CHLO的消息包中,发送给服务端。这个请求的目的是将自己的短期密钥传输给服务端,方便做前向保密。
在这里插入图片描述
发送Complete CHLO消息给到服务器之后,为了减少RTT,客户端并不会等到服务器的响应,而是立刻会进行数据传输。

为了保证数据的安全性,客户端会自己的短期密钥和服务器返回的长期公钥进行运算,得到一个初始密钥(initial keys)。

有了这个初识密钥之后,客户端就可以用这个密钥,将想要传输的信息进行加密,然后把他们安全的传输给服务端了。
在这里插入图片描述
另外一面,接收到Complete CHLO请求的服务器,解析请求之后,就同时拥有了客户端的短期公钥和自己保存的长期密钥。这样通过运算,服务端就能得到一份和客户端一模一样的初始密钥(initial keys)。

接下来他接收到客户端使用初始密钥加密的数据之后,就可以使用这个初识密钥进行解密了,并且可以将自己的响应再通过这个初始密钥进行加密后返回给客户端。

所以,从开始建立连接一直到数据传送,只消耗了初始连接连接建立的 1 RTT

最终(与重复)握手

之后的数据传输就可以使用初始密钥(initial keys)加密了吗?

其实并不完全是,因为初始密钥毕竟是基于服务器的长期公钥产生的,而在公钥失效前,几乎多有的连接使用的都是同一把公钥,所以,这其实存在着一定的危险性。

所以,为了达到前向保密 (Forward Secrecy) 的安全性,客户端和服务端需要使用彼此的短期公钥和自己的短期密钥来进行运算。

在密码学中,前向保密(英语:Forward Secrecy,FS)是密码学中通讯协议的安全属性,指的是长期使用的主密钥泄漏不会导致过去的会话密钥泄漏。

那么现在问题是,客户端的短期密钥已经发送给服务端,而服务端只把自己的长期公钥给了客户端,并没有给到自己的短期密钥。

所以,服务端收到Complete CHLO后,会给到客户端一个server hello(SHLO)消息,这个消息会使用初始密钥(initial keys)进行加密。
在这里插入图片描述
这个CHLO(SHLO)消息包中,会包含一个服务端重新生成的短期公钥。这样客户端和服务端就都有了对方的短期公钥(ephemeral Diffie-Hellman public value)。

这样,客户端和服务端都可以基于自己的短期密钥和对方的短期公钥做运算,产生一个仅限于本次连接使用的前向保密密钥 (Forward-Secure Key),后续的请求发送,都基于这个密钥进行加解密就可以了。

这样,双方就完成了最终的密钥交换、连接的握手并且建立了QUIC连接。

当下一次要重新创建连接时,客户端会从缓存中取出自己之前缓存下来的服务器的长期公钥,并重新创建一个短期密钥,重新生成一个初识密钥,再使用这个初始密钥对想要传输的数据进行加密,向服务器发送一个Complete CHLO 请求即可。这样就达到了0 RTT的数据传输。
在这里插入图片描述
所以,如果是有缓存的长期公钥,那么数据传输就会直接进行,准备时间是0 RTT

以上,通过使用Diffie-Hellman算法协商密钥,并且对加密和握手过程进行合并,大大减小连接过程的RTT ,使得基于QUIC的连接建立可以少到1 RTT甚至0 RTT。

以下,是Google官网上面的一张关于QUIC连接建立的流程图,可以帮助大家理解这个过程。
在这里插入图片描述
另外,通过以上关于握手建立的过程,我们也可以知道,QUIC在整个过程中通过加解密的方式很好的保证了安全性。

HTTP/3的最佳用例

  • 物联网(IoT)
  • 大数据
  • Web VR

弊端

很多企业、运营商和组织对53端口(DNS)以外的UDP流量会进行拦截或者限流,因为这些流量近来常被滥用于攻击。

特别是一些现有的UDP协议和实现易受放大攻击(amplification attack)威胁,攻击者可以控制无辜的主机向受害者投放发送大量的流量。

所以,基于UDP的QUIC协议的传输可能会受到屏蔽。

因为UDP一直以来定位都是不可靠连接,所以有很多中间设备对于他的支持和优化程度并不高,所以,出现丢包的可能性还是比较高的。
在这里插入图片描述

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值