龙空技术网

一文看懂WebTransport

LiveVideoStack 424

前言:

眼前你们对“pythonwebrtc”大约比较关心,大家都想要知道一些“pythonwebrtc”的相关内容。那么小编也在网上网罗了一些关于“pythonwebrtc””的相关文章,希望各位老铁们能喜欢,大家快快来学习一下吧!

文 / Will Law

整理 / LiveVideoStack

大家好,我是Will Law,目前在旧金山的Akamai Technologies办公室工作。我生活和工作的地方距离金门大桥非常近,也就是图片上的地方。能与美国和中国的工程师交流一直是我的荣幸,尤其是讨论在全球范围内具有重要意义的下一代Web协议问题。而我今天要介绍的主题就是关于WebTransport(网络传输)。

话不多说,让我们开始吧。我们首先要考虑下为什么需要一个新的协议?为什么HTTP1、HTTP2、HTTP3或WebSocket协议不能满足我们的需求?我将介绍当前这些协议存在的问题,并引出什么是WebTransport;它包括哪些部分;以及什么是网络堆栈;此外,我还会介绍W3C(国际网络联盟)提出的Web浏览器应用程序接口草案。最后,我们还将讨论如何参与该协议的开发。

在开始之前,我想先感谢Jeff Posnick、Victor Vasilief、Peter Thatcher、Yutaka Hirano和Bernard Aboba为本次演示提供的数据和内容素材。他们一直是WebTransport发展中不可或缺的一部分,尤其是在社区草案形成过程中做出了很多贡献,因此我想对他们提供的信息表示感谢。

让我们正式开始今天的介绍,假设我们要设计一款游戏,您是架构师,我们希望您想出尽可能多的使用场景,而我们要考虑的第一个场景是基于Web或者主机的多人游戏,在这些游戏中,指令会从客户端发送到基于云的服务器,其中有些指令对时间属性十分敏感,例如您在游戏中的位置和角色等。而有些指令则与状态的关联程度更高,例如您的形象或武器。

所以,我们不介意状态性指令的丢失,但那些对时间十分敏感的指令必须及时发送。这两种情况下的数据流都是双向的,因为您需要把位置发送到游戏中,游戏也需要将游戏目前的状态和所有其他玩家的位置信息传给您。因此,我们可以使用RESTful API(事实上大多数情况都是这么做的),也可以用HTTPS来保证安全,还可以使用WebSockets协议或WebRTC(网页实时通信)数据通道,再或者我们还可以用自己的UDP(用户数据报协议)传输。

这四种方式在不同的游戏和场景中都有运用。但是,仔细研究这些协议,我们会发现每种方式都存在一些问题,那么我们要如何来改善呢?

第二个例子是低延迟实时直播,典型的场景包括体育赛事、新闻和娱乐竞猜节目的一对多单向直播流,我们希望视频画面能够支持高清、高帧率、高动态范围、宽色域以及DRM(数字版权管理),但现实是其中很多都无法实现。WebRTC(网页即时通信)如今不支持这些功能。有时我们可能还想进行多对多视频聊天,比如使用Zoom、Apple Facetime或Google Meet会议程序进行网络会议。这种情况我们可以使用单向广播,通过H1或H2使用Chunked的编码功能,目前这也是大部分人所使用的;我们还可以用WebSockets协议、WebRTC数据通道来传送我们的媒体片段;同样,我们还可以使用自己的UDP私有协议传输。

以上是两个详细的例子,我们还可以继续找到类似的例子,比如如果我们想做同声传译的话,我们可能会用到AI技术,我认为这是在线会议未来的方向。再比如如果您让我们做即时翻译,那么我们需要将音频快速上传到云。此前我已经详细介绍了安全摄像头分析、大型多人网络在线游戏和主机游戏,而云游戏模式的原理是在边缘编码器中实时渲染实际游戏,并发送游戏内容,使得低端配置的客户端获得等同高端主机的视觉效果。Google Stadia云游戏平台就是一个很好的例子,当然这也需要双向的游戏指令。我们已经有了基于服务器的视频会议系统,但是我们希望简化会议,而且WebRTC在会话建立期间会暴露大量的隐私信息,我们也希望能够避免这种情况。再来说说远程桌面管理,这是一个企业使用场景,有用户使用物联网传感器和数据分析传输,我们能够使用小型功耗敏感物联网设备,非常有效地向云端发送少量的数据。这是怎么做到的呢?对于他们来说,RESTful API是最好的选择吗?最后一个选项是PubSub(发布/订阅)模型。我们今天也许可以在很多应用程序中避免使用长轮询代码。

因此,综合这些案例,我们看到了一些核心需求。首先我们希望继承现代Web的安全保护技术。换句话说,我们需要TLS(安全传输层协议)加密,我们想要某种类型的拥塞控制和CORS(跨域资源共享),我们仍想要客户端-服务器体系结构,我们不希望它建立在p2p的模型上,因为p2p连接体系结构会话的启动难度不小。我们在大多数应用程序中也想使用双向通信,我们需要发送可靠和有序的数据,我们将这种数据称为“流”。流遵循先进先出的模式,因此在此过程中不会丢失任何内容。

我们还希望以最小的延迟来实现流,但同时我们还需要发送非可靠和无序的数据报文,这和UDP报文非常相似,它们都是小数据包,关键在于传输的速度,如果速度太慢,其中一些数据可能会丢失,但只要我们能够实现高速传输,就能解决这个问题。我们还需要持续地给发送端提供反馈,您也可以将其视为反压力,我们不能漫无目的地发射接收无法处理的数据。并且它们应该使用URI进行资源定位,因为Web中的URI和URL是我们定位Internet内容的核心中枢,所以我们不想改变这种机制,我们想要一些符合URI机制的东西。

现在,让我们回顾一下现有Web技术存在哪些问题?比如RESTful API(表现层状态转移应用程序接口)建立连接的速度相对较慢,尤其是在使用H1或H2的情况下,速度会更慢。使用TLS(安全传输层协议)时,Http/1速度最慢,Http/2次之,Http/3无疑性能最佳,它们始终能提供可靠的无损传输,这在许多领域中都是很重要的,不然就需要重新传输,增加延迟。即使使用HPACK和QPACK压缩,HTTP包头信息也会增加额外的负担,当我们的数据有效载荷很小时,包头所占的比重仍然很大。正如我们提到的那样,在很多情况下我们并不需要它,我们能接受牺牲一些可靠性来换取速度。

WebSocket的主要问题是队首阻塞,我在稍后将详细说明什么是队首堵塞,这是推广WebSocket协议使用的一个主要障碍,不过WebSocket能随时提供可靠的传送服务。WebRTC数据通道的问题是建立连接的负担很高,稍后我们将详细阐述。

您可以开发自己的UDP协议来解决这些问题,但是这会带来一个新的问题,即必须在每个客户端和每台服务器中安装SDK,才能与协议通信。但这会使您丧失控制权,因为Web标准的优势在于您的Web服务器和客户端能够使用您的语言。

此外,我们不能使用Chunked编码的媒体片段,因为这会造成吞吐延迟(延迟目前将增加一到两秒),究其原因在于HTTPS的连接速度较慢。另外每个片段都有一个RTT(往返时间)延迟,所以现有的网络技术并不是我们所需要的。

让我们再看一下队首阻塞的一些细节,因为WebSocket可能是我们的首选方案。因此通常情况下,我们会在队首阻塞中看到由多个流共享的单个数据队列,所以我可以把它比作红车和蓝车在一条马路上行驶,假设现在我的红色汽车要在这个十字路口左转,蓝色的车要继续行驶,只要这条路没有拥堵,一切都会按照我们所期望的那样。

但是如果有一个等待传输的数据包队列,并且队首的数据包无法向前移动那就会发生队首阻塞。在这里可以把它想象成红色汽车想左转,但汽车因为某种原因无法继续行驶,现在我的单通道流中的所有其他流都将堆积在阻塞数据的后面,因此我的蓝车和红车都无法行驶,通道也被堵住了。

有多种解决方案可以解决队首阻塞,其中之一是实现每个输出转发队列并行独立。因此在道路的类比中,这意味着我们要加宽道路以引入另一条车道。假设现在我们的红车挡住了他们的车道,蓝色的车还有另一条车道可以继续行驶,但是由于第一个包堵在那里,红色队列仍然被阻塞,蓝色流保持独立并且不会被阻塞。

那么为什么不使用现有的Web协议WebRTC呢?这张图表就能解释其中的原因,因为这是一个非常复杂的协议。它最初被构建为p2p通信协议,并且在建立连接之前会要求会话描述协议来进行SDP消息传递。在客户端服务器通信模型中我们不需要这样做,因为服务器端也需要通过客户端进行寻址。

WebRTC也要求的ICE、DTL、SCTP协议也通常不会再CDN中大规模部署。因此在某些情况下我们可以使用WebRTC,但WebRTC不是为服务器-客户端模型的应用程序而专门设计的。

为什么不直接使用UDP呢?因为UDP并不安全,它没有继承Web安全模型,缺少加密和拥塞控制,也缺少CORS和发送确认。

如果看一下QUIC协议,您就会发现,它实际上可以满足我们的许多要求。事实上,我们现在知道它可能是最好的选择,因此如果现实中客户端和服务器之前已成功握手,则它具有快速的连接设置1-round trip或者0-round trip。

同时QUIC也十分安全,它一直使用TLS1.3,具有低延时的拥塞控制和可靠的流,并且能实现标识1和2的无序数据报文。如果需要的话,它可以使用在p2p场景,作为H3的基础。因此它在整个互联网中被大量部署,尤其是CDM之中。现在IETF即将推出标准版本,我们将以HTTP/3的形式获得出色的全球QUIC支持。

所以,我们希望QUIC符合我们的多数准则,因为其他的协议或多或少都有些小问题。因此,开发人员应该为网络开发新的传输选项,解决我刚刚谈到的这些特殊问题。WebTransport由工程师创建,为工程师所用,并且被工程师命名,因此,我们就直接沿用WebTransport这个名字。

WebTransport是一个被称为框架的协议,该协议使客户端与远程服务器端在安全模型下通信,并且采用安全多路复用传输技术。注意WebTransport是一个框架,在它下面是实际的协议,框架提供了一个一致的接口,因此它由一组可以安全地暴露给不受信任的应用程序的协议,以及一个允许它们互换使用的模型组成。它还提供了一组灵活的功能,为我们提供了可靠的单向和双向流以及非可靠的数据报文传输。

那么WebTransport有哪些功能呢?我之前提到了单向流,这其实是一个方向上无限长的字节流。当接收端无法足够快地读取它们时,它会对发送端施加反压力,这类似于我现在正在给大家演讲的这个直播视频。

正常序列消息传递中遵循先入先出FIFO原则,先进入的也从另一端先出,而对于乱序的消息传递则可以通过每个流中加入消息从而使得其有多个并发的流。双向流只是一对单向流,每个方向相反,因此,这对于在我希望得到响应的情况下发送信息很有用。正如我们在许多使用过的案例中所讨论的那样,这种需求非常普遍,因此数据报文是小规模、无序、非可靠的消息,数据报文通常保存小于1MTU的数据(约1500字节),这主要取决于网络配置。这对于发送小的更新非常有用,因为这些更新可能会丢失,但是我的应用程序可以处理这些丢失,传输可以专注于将数据包从服务器尽快地发送到客户端。

所以请记住WebTransport是一个传输框架,那么WebTransport中包含哪些推荐的传输协议呢?正如我提到的,QUIC似乎是一个不错的候选,首先是专用的QUIC传输,另外还有HTTP3Transport。我们还有一个备用机制叫做HTTP2Transport。

我们看一看网络堆栈是什么样子?HTTP1/2上无害的堆栈确实推动了当今的全球互联网革命。有一个真实的案例,早在2001年,Akamai全部网络带宽是1Gbps,而今天这一数字变成了160+Tbps。在不改变协议的情况下,速度增长了10几万倍。到如今我们仍然部署HTTP1block,现在我们也部署HTTP2,但是这个简单协议堆栈可以支持流量扩展15万倍,因此这是个很好的设计。建立在QUIC之上的HTTP/3现已对其进行了改进,并删除了在TCP不适用、不灵活的功能,转而直接使用UDP。WebSocket构建在TCP之上,并形成了一个更复杂的协议堆栈。因此这四种协议覆盖了当今互联网上99.9%的流量。

那么WebTransport可能是什么样子呢?正如我们提到的那样,它主要建立在UDP和QUIC之上。WebTransport是我们的框架,在此框架下我们有几种传输类型:QUICTransport、HTTP3Transport和HTTP2Transport。值得注意的是HTTP3Transport和QUICTransport都提供可靠流和非可靠数据报文。

截止到2020年11月,这些结论还存在争议,可能的原因是QUICTransport没有遵循HTTP的方向开发,或者两者都在继续开发,因此开发并不同步。

我们来比较一下HTTP3Transport和QUICTransport。HTTP3Transport的主要区别在于它与其他HTTP3流量在一个池中,假设我有一个终端,并且正在运行许多应用程序,而它们正在以公共主机的名义与服务器进行通信,那么所有HTTP/3流量都会共享给这个链接。HTTP/3继承了很多我们喜欢的HTTP的特性,比如负载均衡、头部信息,以及防火墙和代理的全面支持。因此,您的防火墙在看到HTTP/3时,就能理解它,但它可能不理解QUICTransport。这里讨论的应用程序是常规的Web应用、Web聊天应用程序和Pub/Sub订阅模型。

另一方面QUICTransport是客户端和服务器之间建立连接的专用连接方式,服务器可以优化客户端的传输并向客户端公开更多的统计信息,而无需依赖HTTP/3。同时,它也继承了HTTP的可扩展性特性。这里我们真正关心的是速度或性能,比如网络视频游戏和实时媒体中的应用。

HTTP3或QUIC都可以满足某些Web应用场景并且这些协议仍在不断地发展,您可以讨论是否可以使用其中任何一个来解决大多数此类案例。实际上,并不存在最好的方法,而只能基于当前环境做出的最优选择。

TCP作为回退计划也很有趣,那么如果QUIC被阻止怎么办?我们可以回退到WebSocket。它可以在根本不支持WebTransport的浏览器上实现。HTTP2Transport被认为是HTTP3Transport的一个自然回退的方案。所以,要么QUICTransport可以回退到WebSocket,要么就无路可退。

那么QUICTransport URI方案是什么样子呢?如果您熟悉Web运行方式,就会有很深刻的了解。我们有协议描述符QUIC/DASH Transport,在这种情况下我们将主机server test作为SNI的一部分与端口号一起发送,剩下的URI方案就是正在传输的页面。在TLS建立后,客户端才会接收它。

您可能想看一个QUICTransport的握手示例。我们可以打开一个QUICTransport连接,但是部分发生了一些变化,我稍后将为您详细介绍。我们想要QUICTransport转到此服务器的端口上,浏览器将用ALPN列表“wq”向该端口上的服务器发送一个hello,服务器接收后发回Server Hello,并在其中包括“wq”,浏览器接收Server Hello并在QUIC上发送带有数据流和FIN(关闭连接)的数据包,因此它发送的流非常短。服务器接收流,并接受发送源,现在应用程序可以发送和接收流和数据报文。

HT3Transport具有全新的传输,采用协议HTTPS,当创建新的HTTP/3连接时,它会使用现有的连接池,它会发送带有特定头部信息的连接请求,当然这并不是HTTP/3中的创新。服务器响应200 OK,将“sessionid”标头设置为1。现在对等客户端和服务器可以发送流和数据报文,因为它是通过ID双向关联,一旦关联的CONNECT流关闭,会话就会关闭。

现在让我们比较一下QUICTransport和WebSocket。他们的主要区别在于队首阻塞始终会影响WebSocket,但队首阻塞仅对QUICTransport中相同的流有影响,WebSocket会带给您更全面的可靠性,而QUICTransport可以提供可靠的流传输以及非可靠的数据报文。实际上,您可以取消正在进行的流,TLS和源头的信任模型是相同的,这一点二者并无区别。为防止跨协议攻击,您可以使用基于SHA-1的WebSocket握手,而在QUICTransport上应采用ALPN。为了防止中间件混乱,WebSocket采用基于XOR的掩码机制,而QUICTransport始终用TLS1.3加密。WebSocket身份验证功能可以通过Cookie启用,但是对于QUICTransport应用程序,应用程序本身必须提供一些方法来实现身份验证。所以QUIC和WebSocket有较大的差异,QUICTransport中存在队首阻塞和部分可靠性问题。

那么哪些团队在更新WebTransport呢?首先当然是IETF,他们定义了HTTP/1、HTTP/2,以及您可能使用的所有RFC。这是一个新团队,成立于2020年3月6日,所以这是IETF的一个新项目,您可以通过这里显示的链接阅读他们的提议。

谁在更新基于浏览器的API?W3C建立了一个WebTransport工作组,这个工作组于2020年9月成立,您可以在这里转到WebTransport工作组的主页。实际上我和来自Mozilla的Jan Ivar Bruaroey是这个小组的联合组长之一,合同有效期为2年。我们有一个WICG承诺的API草案,所以我们希望我们的工作能够迅速取得进展,并且我们可以从现在起的两年内将其正式化为一个标准。

因此让我们看一下孵化草案中的一些代码示例,如果您习惯于编写JavaScript类型脚本,那这里用到的语法对您来说一定并不复杂。我们假设这里有函数用来获取存在的序列化游戏状态,为了用具体例子说明我们的传输,我们只需阐明新的WebTransport。记得之前说过的HTTP3Transport和QUICTransport,现在已更改为简单的新WebTransport协议层来查找将要使用的传输类型,我们在传输层编写报文中的可编写对象,从而建立报文内容。然后,我们可以简单地使用数据报文,来编写我们从我们那里得到的信息来实现游戏状态。这一切都能得以简单实现。

这是一个使用QUIC单向流将可靠的游戏状态发送到服务器的代码示例。我们以完全相同的方式实现我们的传输。但是现在我们需要等一等,直到流返回。因此一旦流建立,我们就要从流中创建单向流。我们可以再次从可写组件中获取内容,有了这些信息,我们就可以写下我们可以发送的信息,然后关闭编写器。所以这是一种非常简单的方法,能实现沿着单向流发送数据。

接下来看看我想展示的第三个代码示例,本质上这是通过HTTP发送请求数据,通过同一个网络连接,可靠地接收无序的媒体文件。因为这是视频,所以这里我们将涉及到媒体来源。我们建立了自己的媒体源,在这之后,我们将连接源缓冲器(即初始化缓冲器),并在这里建立新的WebTransport,然后等待传入单向接收流的建立,在接收流上,我们等待可读对象的建立,从而简单地将这个缓冲器(在这个例子中是接收流的可读组件)直接附加到源缓冲区上的指定缓冲器中,并进行管道处理。这提供了一个非常清晰的接口来接收数据流,我将其放入MCS(调制与编码策略)并将其呈现在网页的视频元素中。

现在API仍然处于流动状态,我在前面的示例中提到过,您可以使用不久前更改的QUICTransport或HTTP3Transpaort传输,也可以建立一个新的WebTransport,而您使用的传输类型由初始化WebTransport时使用的URI中的协议定义。

现在Google已经在WebTransport方面做了很多工作。QUICTransport正在Chrome84进行源代码测试,部分Python代码使用的就是AIOQUIC。如果我没记错的话,对于QUIC部分,您可以从GitHub下载该项目,此外还有一个可以与之通信的客户端。Adam Yutaka和Victor还做了一个涉及Chrome 87+的演示。您可以在此处访问此网页并进行测试。请关注下一个屏幕截图,请注意,您必须在Chrome Canary中启用实验性Web平台功能,否则将无法使用。

这是我的Chrome Canary浏览器,我在验证实验性Web平台功能是否已经启用。我们来加载网页,然后我点击连接到他们公开托管的服务器,系统显示连接就绪数据报文编写器已就绪。在控制台这里,我只需确认window.com传输显示我们已经建立了一个对象,并且您可以在这里看到可公开访问的界面,现在我可以发送数据报文了,当我们发送时,他们建立的简单服务器只需回送数据报文中发送的字节数,对于单向流同样可以发送,服务器将发回在该流上接收到的字节,并关闭流和同一个双向流。我所有的组件都在这里。我们现在需要构建一些用例,其中涉及不可靠、无序的数据报文,以及非可靠并且在运行的有序流。在此基础上,您可以开始构建应用程序,并真正测试是否可行,这是一个非常令人兴奋的测试。

您怎样才能参与测试呢?IETF是一个全球性的机构,您可以免费参加IETF活动,您只需支付线下活动的参会费用。这有一个公共邮件列表,您可以免费订阅,我把它列了出来以便大家随时了解IETF中WebTransport的发展。W3C虽然需要会员身份,但网上提供了可公开访问的公共邮件列表,如果您需要其中任何注册信息,请随时联系我们。您也可以访问所示的网站,其中有一小群人正在开发这些规范,如果您有相应的使用场景,欢迎您提供宝贵意见。

这里列出了一些有用的链接,这些链接提供了关于WebTransport的背景信息。

感谢大家让我在这么短的时间里详细介绍WebTransport。很高兴与您交流,如果您对WebTransport有任何疑问,或者您想加入W3C WebTransport工作组,请随时联系我,再次感谢大家百忙之中参与我们的活动。再见!

标签: #pythonwebrtc