type
status
date
slug
summary
tags
category
icon
password
AI 摘要
http1 的缺点
http1.1 提出支持长链接和管道化。
长链接:即可以在一个 http 连接上传输多个请求&响应(http1.1 之前每个 http 链接只可以传输一对请求&响应然后就断开链接)。 在没有管道化的情况下,一个连接上的下一个请求需要在前一个响应返回后再发出。(并发请求只能通过同时建立多个连接实现)
问题:
- 串行传输
- http同域并发连接限制带来的阻塞(6~8)个
管道化:可以在一个 http 链接上同时发送多个请求 (可以克服同域并行连接限制带来的阻塞)
- 服务器可以同时处理多个请求,但是必须按照请求的顺序返回结果(即使后面的请求先处理完成也还是需要缓存起来,等前面的请求处理完返回之后再返回)(对头阻塞:如果前一个请求处理的时间过长或者被无线挂起,那么后面的请求就会排队等待)
问题:
- HTTP 请求无法很好地利用多路复用,不允许一个连接上的多个响应数据交错返回(多路复用)。因而一个响应必须完全返回后,下一个响应才会开始传输。
- 对头阻塞
线头阻塞
HTTP 管线化要求服务器按照接收到的请求顺序进行响应,如果管线化中的单个请求执行得很慢,客户端的后续
响应
也会相应的延迟下去
解决办法
客户端在主机上建立多个 TCP 连接
- 连接的开销并没有消失
再加上 ssl/tls 的加密通信使用,大多数浏览器设置了
最大可能同时连接数
来寻求平衡为什么限制并发连接数?
- 每个连接都需要占用一些服务器的资源,服务器需要维持每一个连接请求的信息,因此过多的连接数意味着服务器的负担很大。
- Dos 攻击:DOS(A Denial of Service) 攻击意味着让服务器忙于跟你打交道,以至于他无法跟其他客户端打交道。当其他客户端无法连接,这就是 DOS。
http2
多路复用
在 HTTP/1.X 中数据是基于文本的有序传输,不能并行传输而且接收端也不知道数据包的顺序。但 HTTP/2 中新的二进制分帧层突破了这些限制,实现了完整的请求和响应复用: 客户端和服务器可以将 HTTP 消息分解为互不依赖的帧,然后交错发送,最后再在另一端把它们重新组装起来。
- 并行交错地发送多个请求,请求之间互不影响。
- 并行交错地发送多个响应,响应之间互不干扰。
- 使用一个连接并行发送多个请求和响应。
- 消除不必要的延迟和提高现有网络容量的利用率,从而减少页面加载时间
针对队头阻塞
谷歌在 2008 年发布了 Chrome 浏览器,这种浏览器因其快速和创新而迅速流行。它使谷歌在互联网技术问题上获得了强大的话语权。在 2010 年代初期,谷歌在 Chrome 中增加了对其 Web 协议 SPDY 的支持。 HTTP/2 标准基于 SPDY,并进行了一些改进
HTTP/2 通过在单个打开的 TCP 连接上多路复用 HTTP 请求,解决了线头阻塞问题
这允许服务器以任何顺序响应请求,然后客户端可以在接收到响应时重新组合响应,从而在单个连接中加快整个交换的速度。

实际上,使用 HTTP/2 服务器甚至可以在请求之前就将资源提供给客户端!举个例子,如果服务器知道客户端很可能需要样式表来显示 HTML 页面,它可以将 CSS“推”到客户端,而无需等待相应的请求。虽然这从理论上讲是有益的,但此功能在实践中很少见,因为它需要服务器了解其服务的 HTML 结构,但这种情况很少发生。
TCP 队头阻塞
TCP 的队头阻塞并没有彻底解决: TCP 为了保证可靠传输,有一个“超时重传”机制,丢失的包必须等待重传确认
http2 虽然很好的解决了 HTTP 队头阻塞的问题。但是 http2 仍然会存在 TCP 队头阻塞的问题,因为 http2 还是基于
TCP 协议
实现的。TCP 传输过程中会把数据拆分成一个一个小的有序的数据包,然后经过路由器、集线器、交换机等中间设备转发,最终到达目的地。如果其中某一个数据包没有按序到达,接收端就会保持连接等待数据包返回。这时就会阻塞后续的请求,就造成了 TCP 队头阻塞。
HTTP/1.1 管道化持久连接也是使得同一个 TCP 连接可以被多个 HTTP 使用,但是 HTTP/1.1 中规定一个域名可以有 6 个 TCP 连接
而 HTTP/2 中,同一个域名只使用一个 TCP 连接,一旦 HTTP/2 中 TCP 队头阻塞所造成的影响会更大,因为 HTTP/2 的多路复用技术使得多个请求其实是基于同一个 TCP 连接的,如果某一个请求造成了 TCP 队头阻塞,那么多个请求都会受到影响。
建立连接时间长
多路复用容易 Timeout: 大批量的请求同时发送,由于 HTTP2 连接内存在多个并行的流,而网络带宽和服务器资源有限,每个流的资源会被稀释,虽然它们开始时间相差更短,但却都可能超时
http3
针对tcp队头阻塞
TCP协议在收到数据包之后,这部分数据可能是乱序到达的,但是TCP必须将所有数据收集排序整合后给上层使用,如果其中某个包丢失了,就必须等待重传,从而出现某个丢包数据阻塞整个连接的数据使用。
QUIC协议是基于UDP协议实现的,在一条链接上可以有多个流,流与流之间是互不影响的,当一个流出现丢包影响范围非常小,从而解决队头阻塞问题。
针对http2的tcp连接时间长
前面说到 HTTP2 连接基本上要花到2~3个RTT才能完成连接,但QUIC基本上可以实现1或0RTT去完成连接的。
如果是首次需要花1RTT去完成连接,但如果非首次连接0RTT就可以完成了,这是因为首次连接时会缓存配置文件,后续再连接时就可以直接使用,从而跳过1RTT,实现0RTT的业务数据交互
自身特点
- 实现了类似 TCP 的流量控制、传输可靠性的功能。虽然 UDP 不提供可靠性的传输,但 QUIC 在 UDP 的基础之上增加了一层来保证数据可靠性传输。它提供了数据包重传、拥塞控制以及其他一些 TCP 中存在的特性。
- 集成了 TLS 加密功能。目前 QUIC 使用的是 TLS1.3,相较于早期版本 TLS1.3 有更多的优点,其中最重要的一点是减少了握手所花费的 RTT 个数。
- 实现了 HTTP/2 中的多路复用功能。和 TCP 不同,QUIC 实现了在同一物理连接上可以有多个独立的逻辑数据流。实现了数据流的单独传输,就解决了 TCP 中队头阻塞的问题。
落地的一些困难
动了底层协议,所以 HTTP/3 的增长会比较缓慢,这和 HTTP/2 有着本质的区别
第一,从目前的情况来看,服务器和浏览器端都没有对 HTTP/3 提供比较完整的支持。Chrome 虽然在数年前就开始支持 Google 版本的 QUIC,但是这个版本的 QUIC 和官方的 QUIC 存在着非常大的差异。
第二,部署 HTTP/3 也存在着非常大的问题。因为系统内核对 UDP 的优化远远没有达到 TCP 的优化程度,这也是阻碍 QUIC 的一个重要原因。
第三,中间设备僵化的问题。这些设备对 UDP 的优化程度远远低于 TCP,据统计使用 QUIC 协议时,大约有 3%~7% 的丢包率。
三个版本在数据传输上的体现
HTTP/1.1

HTTP/2

QUIC

RTT和RTO
- RTT(Round Trip Time):一个连接的往返时间,即数据发送时刻到接收到确认的时刻的差值;
- RTO(Retransmission Time Out):重传超时时间,即从数据发送时刻算起,超过这个时间便执行重传, RTO协议实现值最小1s
RTT 和 RTO 的关系是:由于网络波动的不确定性,每个RTT都是动态变化的,所以 RTO 也应随着 RTT 动态变化。
当 RTO < RTT 时, 将会触发大量的重传, 当 RTO > RTT 时候, 如果频繁出现丢包, 重传不及时, 又会造成网络的反应慢, 最好的结果是 RTO 略大于 RTT.