关于HTTP/3背后你所不知道的


HTTP / 3将标准化,作为一个老协议人,我想我会写一些评论。
谷歌拥有最受欢迎的网络浏览器(Chrome)和两个最受欢迎的网站(#1 Google.com#2 Youtube.com)。因此,他们可以控制未来的Web协议开发。他们的第一次升级称为SPDY(发音为“speedy”),最终标准化为HTTP的第二个版本,即HTTP/2。他们的第二次升级称为QUIC(发音为“quick”),标准化为HTTP/3。
主要网络浏览器(Chrome,Firefox,Edge,Safari)和主要网络服务器(Apache,Nginx,IIS,CloudFlare)已经支持SPDY(HTTP/2)。许多最受欢迎的网站都支持它(即使是非谷歌网站),尽管你不太可能在线上看到它(用Wireshark或tcpdump嗅探),因为它总是用SSL加密。虽然标准允许HTTP/2通过TCP运行原始,但所有实现仅通过SSL使用它。
这里有一个关于标准的好教训。在互联网之外,标准通常是法律上的由政府管理,驱动所有主要利益相关者进入一个房间并将其拟定出来,然后使用规则迫使人们采用它。在互联网上,人们首先创建实现一个新事物,然后如果其他人喜欢它,他们也会开始使用它,因此,标准通常是事实上的。
RFC是针对已经在互联网上运行良好的内容编写的,记录了人们已经在使用的内容。浏览器/服务器采用SPDY不是因为它是标准化的,而是因为主要参与者开始使用它。QUIC正在发生同样的事情:它被标准化为HTTP/3的事实反映了它已被使用,而不是处于通往标准化实施里程碑阶段。

QUIC实际上是新版本的TCP(TCP / 2 ???)而不是新版本的HTTP(HTTP / 3)。它并没有真正改变HTTP / 2的作用,而是改变了传输的工作方式。因此,我在下面的评论侧重于传输问题而不是HTTP问题。

HTTP3主要特点是更快的连接设置和延迟
TCP需要在建立连接之前来回发送多个数据包。SSL再次需要在建立加密之前来回发送许多数据包。如果有很多网络延迟,例如当人们使用具有半秒ping时间的卫星互联网时,建立连接可能需要相当长的时间。通过减少往返次数,连接可以更快地进行设置,因此当您单击链接时,链接的资源会立即弹出

带宽
网络连接的源和目标之间始终存在带宽限制,这几乎总是由于拥塞。双方都需要发现一种速度级别,以这个速度他们能够以合适的速率发送数据包。发送数据包太快也不行,会被丢弃,导致其他人拥塞更多,这样并不会提高传输速率。发送数据包太慢也不行,意味着网络使用不当。

HTTP传统上这一点实现得很糟糕,使用单个TCP连接不适用于HTTP,因为与网站的交互需要同时传输多个内容,因此浏览器会打开多个连接(通常为6个)。但是,这会打破带宽估计,因为每个TCP连接都尝试独立完成,就像其他连接不存在一样。SPDY通过其多路复用  功能解决了这个问题,该功能将浏览器/服务器之间的多个交互放入一个连接。

QUIC扩展了这种多路复用,使得处理浏览器/服务器之间的多个交互变得更加容易,而没有任何一个交互阻止另一个交互,但都具有同样的带宽。从用户的角度来看,这将使交互更加顺畅,同时减少路由器遇到的拥塞。
 
用户模式堆栈
TCP的问题,特别是在服务器上,是TCP连接由操作系统内核处理,而服务本身在usermode中运行。跨内核/用户模式边界移动会导致性能问题。跟踪大量TCP连接会导致可伸缩性问题。有些人尝试将服务放入内核,以避免转换,这是一个糟糕的,因为它破坏了操作系统的稳定性。我自己的解决方案,使用BlackICE IPS和masscan,就是使用 硬件的用户模式驱动程序,将数据包从网络芯片直接传送到用户模式进程,绕过内核(参见PoC || GTFO#15),使用我自己的自定义TCP堆栈。近年来,这已成为DPDK的流行 套件。

但是,从TCP迁移到UDP可以在没有用户模式驱动程序的情况下获得相同的性能。 您可以调用recvmmsg()  一次接收一堆UDP数据包,而不是调用众所周知的recv()函数来一次接收一个数据包。它仍然是内核/用户模式转换,但是一次性收到的一百个数据包的开销,而不是每个数据包的转换。

在我自己的测试中,使用典型的recv()  函数限制为大约500,000 UDP /秒,但使用recvmmsg()和其他一些优化(使用RSS的多核),你可以在低端四核服务器上获得5,000,000 UDP /秒。由于每个核心的扩展性很好,因此迁移到具有64个核心的强大服务器应该可以进一步改进。

BTW,“RSS”是网络硬件的一项功能,它将传入的数据包分成多个接收队列。
多核可扩展性的最大问题是两个CPU核心需要同时读取/修改同一个东西,因此共享相同的UDP队列成为最大的瓶颈。
因此,首先英特尔和其他以太网供应商添加了RSS,为每个核心提供了自己的非共享数据包队列。Linux和其他操作系统升级UDP以支持单个套接字(SO_REUSEPORT)的多个文件描述符来处理多个队列。
现在,QUIC使用这些发展成果,允许每个核心管理自己的UDP数据包流,而没有与其他CPU核心共享内容的可扩展性问题。我之所以提到这一点,是因为我亲自与英特尔硬件工程师讨论过在2000年有多个数据包队列问题。这是一个常见的问题,也是一个明显的解决方案,在过去的二十年中,它看起来很有趣,直到它出现在高端的HTTP / 3。
如果没有网络硬件中的RSS,QUIC就不太可能成为标准。


移动支持
当您将笔记本电脑移动到不同的WiFI网络或随手机移动时,您的IP地址可能会发生变化。操作系统和协议不能正常关闭旧连接并打开新连接。但是,对于QUIC,连接的标识符不是“套接字”(源/目标端口/地址协议组合)的传统概念,而是分配给连接的64位标识符。
这意味着,当您四处移动时,即使IP地址发生变化,您也可以继续从YouTube不间断地继续流式传输,或者继续进行视频电话呼叫,而不会被丢弃。几十年来,互联网工程师一直在努力解决“移动IP”问题,试图提出一个可行的解决方案。他们专注于端到端原则,以便在您移动时以某种方式保持一个恒定的IP地址,这不是一个实际的解决方案。很高兴看到QUIC / HTTP / 3最终通过现实世界中的工作解决方案来解决这个问题。

如何使用这种新的运输?几十年来,网络编程的标准一直是传输层API,  称为“套接字”。你调用recv()之类的函数的地方 在您的代码中接收数据包。使用QUIC / HTTP / 3,我们不再拥有操作系统传输层API。相反,它是一个更高层的功能,您可以在go  编程语言中使用,或者在OpenResty nginx Web服务器中使用Lua。

我之所以提到这一点,是因为您对OSI模型的教育中缺少的一点是,它最初设想每个人都在编写应用层(7)API而不是传输层(4)API。应该有像应用程序服务元素之类的 东西,它们可以以标准方式处理文件传输和消息传递等不同应用程序。我认为人们越来越多地转向这种模式,特别是谷歌用goQUIC驱动,protobufs等。

我之所以提到这一点,是因为谷歌和微软之间的对比。微软拥有一个流行的操作系统,因此它的创新是由它在该操作系统中的功能所驱动的。谷歌的创新是由它可以放在操作系统之上的。然后有Facebook和亚马逊自己必须在谷歌提供它们的堆栈之上(或之外)进行创新。按顺序排名世界排名前五的公司是Apple-Google-Microsoft-Amazon-Facebook,因此每个公司推动创新都很重要。

结论
当TCP在20世纪70年代创建时,它是崇高的。它处理的事情,如拥塞,比竞争协议要好得多。从IPv4到IPv6的升级在很大程度上保持了IP的优势;从TCP到QUIC的升级同样基于TCP的优点,但将其扩展到现代需求。实际上,令人惊讶的是,TCP已经持续了这么长时间没有升级。