HTTP/3就要来了,先看看我的解读
QUIC中虽然也有连接(Connection),也基于IP和port建立,但它并不能直接与TCP的连接对应,也不同于HTTP/2中的连接。原因在于QUIC建立连接时既完成了经典的传输握手,又完成了加密握手——你可以认为这样分层责任不清晰,但它确实提升了效率。QUIC的连接与HTTP/2类似,一个物理连接也可以承载多个逻辑连接(也就是数据流)。但与HTTP/2不同的是,QUIC中的逻辑连接是彼此独立的,所以避免了TCP上出现的“逻辑连接甲丢包导致逻辑连接乙、丙、丁都需要重传”的情况。 QUIC连接的另一个特点是,每个连接都有一组连接ID。连接各端可以设定自己的连接ID,同时认可对方的连接ID。连接ID的作用在于从逻辑上标识当前连接。所以,如果用户的IP发生变化而连接ID没有变化,因为packet包含了网络ID标识符,所以只需要继续发送数据包就可以重新建立连接。而目前,如果用户的设备发生了网络切换,比如从Wi-Fi切换到4G,则所有连接都要断掉再重连。 如果你详细研究过HTTP/2,应当知道它的header压缩采用的HPACK,因为gzip做header压缩有安全性隐患。HTTP/3同样提供了header压缩,但不能直接沿用HPACK。原因在于,HPACK粗略来说就是一张动态表(dynamic table),由request-response共同维护它,后续header中不会完整重复之前的条目,而是引用之前的条目,TCP的有序性保证了它一定是先修改再读取,也就是先编码再解码。 然而如果使用HPACK,多个流的顺序是无法保证的,这样会导致解析错误。QUIC的解决方案是QPACK,其原理很简单:所有的header必须通过同一数据流来传输,而且必须严格有序。但是这样一来,从HTTP 1.1开始就困扰HTTP已久的队头阻塞又出现了。因此,QUIC的长期目标之一就是解决header的队头阻塞问题。 做过在线升级的朋友都知道,在线升级中的一个必须成分是提供降级方案,以保证“退化”兼容。无论HTTP/2还是HTTP/3,都不能逃避这部分的工作量。HTTP/2虽然可以通过upgrade这个header来升级,但也有更简单的办法,就是在TLS握手时协商HTTP的版本,比如Nginx就有NPN(Nginx Protocol Negotiation)扩展,自动协商协议,并已经被IETF采纳,成为ALPN(Application Layer Protocol Negotiation)。 如果web server有这样的特性,应用服务代码就不必为兼容HTTP 1.1和HTTP/2做太多工作。但是,如果应用程序中使用了Push等新特性,还是免不了要做很多事情。在业界,Google、Youtube、Wikipedia等大厂早已经提供了完整服务,HTTP/2和HTTP 1.1无缝切换,客户端完全无感知,它们的经验值得参考。 与HTTP/2不同的是,HTTP/3中新定义了一个header,可以用来指示客户端“在另一个端口提供了专用的HTTP/3服务”。 Alt-Svc: h3=":20003" 这个header说明,在本主机的20003端口开启了HTTP/3的服务。所以,客户端之后可以尝试和这个端口建立纯粹的HTTP/3连接。 聊了这么多QUIC的好处之后,再谈谈它的问题,有些观点来自我个人,未必足够准确客观,欢迎讨论。 虽然QUIC有这么多好处,但可以看到,相比HTTP/2,它的改动相当大,所以问题也不会少。 第一个问题是与遗留的网络设备的兼容问题。 基于目前的应用情况,许多网络设备对TCP和UDP的策略相当固定,TCP限制在常用端口,而UDP大概只开放了53端口(DNS)。所以如果HTTP/3使用UDP,兼容性方面可能会有不少问题需要解决。 不过如果这个问题可以解决,未来大概不会再出现这种问题,因为HTTP/3的设计思想中已经为未来做了考虑,应用层和传输层职责严格隔离,避免再出现“传输层一看端口就知道应用层在干什么”的情况。 第二个问题是QUIC的性能问题。 TCP虽然也是很老的协议,但应用广泛,操作系统内核中有对应的处理代码,BBR之类的新特性也可以大幅提升TCP的性能。但是QUIC放弃了TCP,据Google的文档,恰恰是因为TCP太稳定了,内核里的代码更新特别麻烦。此外,因为Linux内核设计之初并没有考虑多核的扩展问题,在多核(core)情况下反而会产生反复的陷核,造成进程阻塞,严重影响性能。 针对上面的问题,不少新的方案都把网络协议栈放到用户态处理,QUIC也顺应了这种大潮流。唯一的问题是,UDP的协议栈似乎还没有现成的让人满意的方案,或许我们还得再等待一段时间,才能用上可靠高效的方案。 第三个问题是服务端推送。 虽然很多人很想要这个特性,而且HTTP/2也确实加入了它,但关于它的应用仍然存在许多争议。简单说,HTTP/2的推送打破了HTTP传统的“一问一答”的通讯模式,在客户端没有请求的时候,服务端就可以给客户端发送数据,这难免被滥用(想想随处可见的那些最喜欢“在商言商”,最不喜欢谈“道德”的留言吧),尽管Chrome的开发人员说它们会检查推送并阻止恶意内容,那也是要在收到推送数据之后进行,这个方案并不完善。 同时,服务端也可能不顾客户端的缓存,执意重复推送,造成带宽浪费。HTTP/3保留了推送,但机制有所不同。客户端需要先同意,服务端才可以推送。而且,客户端可以设置服务端推送上限,超过上限的推送会出错。尽管如此,推送如何能妥善利用,目前还没有公认明确的答案。 最后一个问题来自调试和支持的工具。 任何技术要想大规模工程应用,靠“标准实现”单打一肯定是不行的,因为无法切片,无法细粒度调试。在经典的HTTP技术栈中,各层都有对应的工具,比如IP层有ping和traceroute,传输层有telnet,应用层有curl,正是有这些工具簇拥着,开发人员才可以很方便地定位问题所处的层次和细节。HTTP/2虽然有改动,但调试工具也不少,curl可以支持,还有nghttp2、h2c等工具,初步形成了完整的体系。HTTP/3的改动很大,如果没有对应的调试支持工具,可以想象部署和迁移都不会容易。
(编辑:南平站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |