作者:京东零售 周凯

一. 前言与背景

国内的互联网直播技术从2005年前后兴起,彼时最具代表性的直播产品是由PPLive创始人姚欣在华中科技大学就读期间发起的校园直播项目PPLive。当时的直播技术用的还是基于windows系统自带的mediaplayer内置的COM组件开发的播放器,采用的是RTSP协议。受当时的互联网传输带宽及成本限制,PPLive并没有采用现在比较流行的单播技术,而是采用P2P技术分发直播流。国内的直播技术也进入了一段以P2P技术为主的时期,其中比较有代表性的就是PPLive和PPStream。用P2P技术分发直播流,具有运营成本低的明显优势,每一个参与播放的终端都是一个潜在的数据热点,网络质量随着观看直播流的客户端的增加而增加。但P2P技术也有自身的不足,缺乏观众的冷门资源因参与数据共享的客户端稀少而难以保证播放质量,另外P2P难以保证UDP打洞穿透率、需要下载专用的播放器等都是限制用户数量增长的因素。

P2P直播分发技术注定是一个过渡性的技术。2005年以后,由于早期的HTML标准尚不完善,各大浏览器存在实现上的差异,被寄予厚望的HTML5规范也还尚未定稿,基于HTML的视频播放技术也不成熟。彼时,Adobe公司从Macromedia公司收购的网页多媒体插件flashplayer在这种情况下脱颖而出。在开发层面,flashplayer因其优异的多媒体表现力以及完善的开发语言和调试工具,降低了网页播放器的开发门槛。在音视频质量方面,Flashplayer内置的On2公司的VP6视频编解码器无论是在编码质量还是在解码效率上在当时都非常优秀,随着2003年才定稿的H.264/AVC视频编解码器及更高质量的AAC音频解码器也很快被内置到flashplayer内核,进一步提高了flashplayer的音视频能力。在播放器推广层面,基于flashplayer开发的播放器文件,能像分发网页一样通过网站服务器下发和更新,这极大地降低了视频网站的推广难度。上述原因,促使flashplayer成为当时最好的网页视频播放器内核。在flashplayer的技术加持下,视频点播网站如雨后春笋般涌现,尤其在2006年google收购youtube后,网页视频点播网站迎来了爆发,六间房、优酷、土豆等视频网站先后融入巨资,从众多点播网站中脱颖而出。彼时,flashplayer作为绝大部分视频点播网站统一使用的网页播放器,装机率快速提高,逐步成为事实上的网页多媒体播放器标准。2009年,随着Adobe将flashplayer内置的革命性的流媒体传输协议RTMP(Real-Time Messaging Protocol)规范开放,本就已经方兴未艾的RTMP直播技术,进入了发展的快车道。各种基于RTMP协议的开源实现陆续出现,涵盖服务器和播放器。由此,互联网直播进入了由flashplayer和RTMP协议主导的时代。

RTMP是flashplayer原生支持的流媒体传输协议,支持点播和直播模式,经过十多年的大规模应用,已经成为当前国内应用最为广泛的直播协议,各大CDN厂商都已经支持。国内技术圈还发展出了HTTP-FLV协议,即将RTMP中的直播音视频流封装成FLV文件流,通过HTTP协议传输,这进一步降低了直播技术的接入成本和实现难度。

RTMP和HTTP-FLV都是基于TCP的直播协议,TCP固有的基于拥塞控制的传输策略在需要稳定、大量传输数据的直播场景下显得过于保守,偶发的丢包或网络抖动都会造成数据收发速率的急剧下降,从而造成画面及声音的卡顿,影响直播的质量及体验。而基于带宽和延时预测的QUIC传输协议的出现,为直播行业提供了一个提升直播质量和用户体验的新的选项。

二. QUIC介绍

QUIC(读作“quick”)是一个通用的传输层网络协议,最初由Google的Jim Roskind设计。该协议于2012年实现并部署,2013年随着实验范围的扩大而公开发布,并向IETF描述。虽然长期处于互联网草案(英语:Internet Draft)阶段,但从Chrome浏览器至Google服务器的连接中超过一半的连接都使用了QUIC。Microsoft Edge、Firefox都已支持此协议;Safari实现了QUIC,但默认情况下没有启用。QUIC于RFC9000中被正式标准化。

虽然QUIC的名称最初是“快速UDP互联网连接”(Quick UDP Internet Connection)的首字母缩写,但IETF指定的标准中QUIC并不是任何内容的缩写。QUIC提高了目前使用TCP的面向连接的网络应用的性能。它通过使用用户数据报协议(UDP)在两个端点之间建立若干个多路连接来实现这一目标,其目的是为了在网络层淘汰TCP,以满足许多应用的需求,因此该协议偶尔也会获得 “TCP/2”的昵称。

QUIC与HTTP/2的多路复用连接协同工作,允许多个数据流独立到达所有端点,因此不受涉及其他数据流的丢包影响。相反,HTTP/2建立在传输控制协议(TCP)上,如果任何一个TCP数据包延迟或丢失,所有多路数据流都会遭受队头阻塞延迟。

QUIC的次要目标包括降低连接和传输时延,以及每个方向的带宽估计以避免拥塞。它还将拥塞控制算法移到了两个端点的使用者空间,而不是内核空间,据称这将使这些算法得到更快的改进。此外,该协议还可以扩展前向纠错(FEC),以进一步提高预期错误时的性能,这被视为协议演进的下一步。

三. 京东直播技术简介

京东直播体系从零开始构建,如下图所示,涵盖四大业务模块:推流端、中台源站、直播云CDN及播放端。

图1.京东直播产品体系

从上图可以看出,直播流的端到端传输,中间要经过多个链路。直播数据因数据量大、占用带宽高、传输距离长而符合典型的Long-Fat(长肥)网络定义。在应用QUIC技术之前,京东的直播产品都是使用基于TCP的协议(RTMP/HTTP-FLV/HLS等)进行直播流数据传输,TCP因其保守的拥堵控制策略,在应对Long-Fat网络应用场景时差强人意,QUIC技术的出现,为优化直播传输质量提供了新的选择。

京东从2021年上半年开始研究QUIC,基于QUIC ietf v1版本开发了自研的QUIC实现QUIC-Pro,并最先在京东的直播场景落地。QUIC在京东直播技术体系的落地过程并非一蹴而就,而是循序渐进的。考虑到直播数据流从CDN边缘服务器分发到用户端是最复杂的“最后一公里”问题,因此,我们选择QUIC最初的落地场景是直播的分发和播放。

QUIC落地之前,为了量化直播质量,方便对比优化收益,我们制定了统一的全链路质量监控及数据上报标准,收集推流端、直播源站、直播云CDN及播放端等所有环节的跟传输、播放相关的监控数据,并统一上报到数据收集平台进行聚合、分类及统计,在众多质量指标中,选定画面首开时长、卡顿率及播放失败率作为播放质量的重要量化参考指标。

本文将分别从推流端、中台源站、直播云CDN及播放端四个部分串烧式地介绍与直播相关的一些技术实践,并重点介绍QUIC技术的应用情况及收益。

四. 推流端技术

京东直播支持的推流端包括京东视频APP,PC桌面端推流工具以及web网页端企业直播工具。京东视频APP及PC桌面端推流工具除支持真人直播及美颜功能外,还支持数字人直播,数字人直播数据流程如下图所示。

图2.京东数字人直播SDK架构

上图中,VideoSource和AudioRecord分别控制图像和声音数据的输出,当真人直播时,VideoSource打开CameraCapturer,采集摄像头图像数据,并送到Filter滤镜链条进行美颜等操作,然后进行视频编码并打包发送,音频则通过AudioRecord打开MicrophoneRecord,采集麦克风声音进行录制、编码并打包发送。

当采用数字人直播时,流程经过图中黄色模块,TextureFactory模拟摄像头运行机制,按帧率设置定期生成空白纹理,纹理经过VideoSource进入滤镜链条,滤镜链条中有一个3DEngineFilter滤镜,将京东自研的数字人3D引擎生成的数字人图像渲染到纹理,然后在屏幕上展示该纹理,同时将纹理上的图像进行编码、打包、发送。数字人的音频,则通过AudioPlayer控制音频播放到设备的同时,将音频采样数据输出到AudioRecord,然后经过编码、打包,并发送出去。

五. 直播源站与CDN分发网络

京东直播包括实时音视频源站、实时转码、录制、审核等业务,推流端的实时音视频流都是先推到中台源站,然后再经过处理通过京东直播云CDN分发到播放端。中台源站还负责直播连麦相关业务的处理,包括混音、合屏等操作。

图3.京东中台直播源站低延迟直播服务架构

直播云CDN通过京东云对外提供赋能,直播云CDN承载了京东主站、京喜等含直播功能的产品的日常直播流分发服务。经过近一年的密切合作,京东直播中台团队和京东直播云CDN团队已将共建的QUIC直播流分发服务全量部署到所有服务节点。直播云服务流程如下图所示。

图4.京东直播云CDN分发流程图

上图是京东直播云CDN对直播流的分发流程图,最左侧是直播源站或直播应用直推直播流到边缘推流集群,经过录制、转码截图、中转集群等中间模块及服务处理,最后转推给第三方CDN或经由边缘播放集群分发给播放端。

六. QUIC服务端设计

当前网络上开源的服务端QUIC协议栈实现方案有多种,例如Chromium QUIC、Lsquic、Nginx 官方quic、cloudfare quic等。其中Chromium QUIC发展的最早,也相对最成熟。因此JDQUIC服务端依托Chromium QUIC,使用了其QUIC协议栈相关源码,服务器框架及其他所有代码则为自研。

6.1.JDQUIC服务器模式

为尽量减少对现有直播CDN分发体系的改造,并保持QUIC的可扩展性及高效迭代更新,JDQUIC服务器采用反向代理模式进行QUIC直播流的请求、转换与分发。

图5.JDQuicServer工作流程

如上图显示,手机端播放器发送QUIC直播流拉流请求到JDQuic-Server服务器,JDQuic-Server服务器将请求格式转换为普通的http或tcp数据,发送给后端Web或者TCP服务器,然后接收后端HTTP-FLV服务器返回的直播流数据并通过HTTP/QUIC协议下发给播放器。整个服务过程无需对后端服务体系作任何修改。

由于JDQUIC服务器一般和后端服务器部署在同一机房、甚至同一机器上,两者之间的数据传输延迟基本可以忽略不计。

6.2. JDQUIC服务端架构

JDQUIC服务端采用多进程单线程架构。消息驱动采用了Libevent epoll模式,QUIC协议栈则使用了Chromium QUIC协议栈相关代码。如下所示:

图6.JDQuic-Servrer内部架构

JDQUIC 服务端采用单线程多进程架构,单机多进程采用内核ebpf进行负载均衡。

单线程内部采用Libevent epoll进行消息监听和分发,TCP UDP Unix domain、http等多种协议依托Libevnet进行收发,同时超时和异步消息也通过Libevent架构进行回调。

Libevent 收上来的UDP数据包,在Chromium QUIC协议栈进行解析,还原出原始Http或者裸数据。这些数据经过线程内无锁调度模块,传给后端Nghttp2或tcp udp client模块,发送给后端服务器。

6.3. JDQUIC连接迁移

网络的切换在当今移动网络大规模普及的背景下,是经常发生的事情。考虑如下场景,当用户正在户外用移动4G/5G网络看着直播的过程中,走到了一个具备WIFI网络的地方,连上了可用的wifi网络,此时,网络切换便发生了。如果要保证直播连接在网络切换后仍然保持畅通,需要实现一套连接迁移机制。JDQUIC-server的实现及工作原理,如图7所示:

图7.JDQuic-Server连接迁移原理

【工作流程】

  1. 手机端从4G网络切到wifi网络。

  2. 手机端网络连到不同的运营商机房(从移动机房切到联通机房)。

  3. Ospf和nftable负载分配到一个机器quic server实例。

  4. Quic server 通过quic数据包中的connection id中第一个字节,判断数据包该发回哪个机房。

  5. Quic server 把数据包转发给原来的机房。

  6. 原来的机房再负载到正确的quic实例。

【说明】

• Ospf负载: 三层负载均衡服务,硬件负载,效率很高。

• Nftable单机负载: 操作系统内核级别的负载服务。

• QUIC服务: quic服务器,可以将quic协议转换为http去后端FMS/SRS拉流。

• 后端FMS/SRS:直播流媒体/CDN服务器。

• 红色箭头:手机端首次播放直播的拉流路线。

• 蓝色箭头:手机端网络切换WIFI后进行连接迁移的拉流路线。

6.4. JDQUIC DCID设计

连接迁移时,联通机房的quic server想要找到回源的机器,需要从quic数据包的DestionationConntion id字段获取机房信息,如下图所示。

图8.JDQuic-Server CID扩展设计方案

CID字段取一个字节来映射机房信息,例如0x01表示长春移动,0x02表示长春联通等。

6.5. JDQUIC ebpf设计

6.5.1. eBPF简介

Linux 内核一直是实现监控/可观测性、网络和安全功能的理想地方。 不过很多情况下这并非易事,因为这些工作需要修改内核源码或加载内核模块, 最终实现形式是在已有的层层抽象之上叠加新的抽象。 eBPF 是一项革命性技术,它能在内核中运行沙箱程序(sandbox programs), 而无需修改内核源码或者加载内核模块。

将 Linux 内核变成可编程之后,就能基于现有的(而非增加新的)抽象层来打造更加智能、 功能更加丰富的基础设施软件,而不会增加系统的复杂度,也不会牺牲执行效率和安全性。

图9.eBPF原理及工作流程

6.5.2. eBPF在JDQuic-Server中的应用

linux内核中,通过ebpf维护两个映射表,并编写一段ebpf JIT(即时编译)程序。客户端QUIC数据包进来后,ebpf JIT程序根据ip端口、CID进行hash,分别访问两个map表,来判断需要转发给哪个后端QUIC实例。其中,ip和端口为UDP协议数据包的字段,包括源IP、目的IP、源端口、目的端口(合称四元组),如图所示。

图10.JDQuic-Server内部ebpf负载均衡原理

七. QUIC技术收益

QUIC协议基于带宽瓶颈预测及环路延时预测的传输控制算法,相比TCP的基于网络拥塞的控制算法,在抗网络抖动、提高网络传输速率方面有显著优势。根据QuicPro在线上Android应用内的直播场景中的使用情况统计数据显示,直播卡顿率较TCP由1.43%降为1.14%,降幅为20%,首开时间较TCP的949毫秒降为659毫秒,降幅为30.5%,如下图所示:

图11.TCP与QUIC分别在直播卡顿率及首开时间上的对比

八. 结语

京东直播经过4年多的发展,技术上无论是服务架构还是播放协议都经过了多轮迭代,截至本文成文,仍在进行迄今为止最大规模的改造升级,涉及全链路的协议升级与架构优化。协议上,将原有的基于TCP的信令、推流、分发、播放等环节升级为QUIC协议,在服务架构上,进行推流及媒体服务边缘化改造,在分发上,中台与京东云直播CDN兄弟部门共建低延迟分发网络,我们共同的目标是提升传输质量、降低卡顿率的同时,将直播端到端的延迟降低到2秒甚至是1秒以内。

QUIC在京东直播的应用与实践的更多相关文章

  1. 让互联网更快:新一代QUIC协议在腾讯的技术实践分享

    本文来自腾讯资深研发工程师罗成在InfoQ的技术分享. 1.前言 如果:你的 App,在不需要任何修改的情况下就能提升 15% 以上的访问速度,特别是弱网络的时候能够提升 20% 以上的访问速度. 如 ...

  2. 直播推流端弱网优化策略 | 直播 SDK 性能优化实践

    弱网优化的场景 网络直播行业经过一年多的快速发展,衍生出了各种各样的玩法.最早的网络直播是主播坐在 PC 前,安装好专业的直播设备(如摄像头和麦克风),然后才能开始直播.后来随着手机性能的提升和直播技 ...

  3. 手游录屏直播技术详解 | 直播 SDK 性能优化实践

    在上期<直播推流端弱网优化策略 >中,我们介绍了直播推流端是如何优化的.本期,将介绍手游直播中录屏的实现方式. 直播经过一年左右的快速发展,衍生出越来越丰富的业务形式,也覆盖越来越广的应用 ...

  4. Golang在视频直播平台的高性能实践

    http://toutiao.com/i6256894054273909249/ 熊猫 TV 是一家视频直播平台,先介绍下我们系统运行的环境,下面这 6 大服务只是我们几十个服务中的一部分,由于并发量 ...

  5. 干货 | 京东技术中台的Flutter实践之路

    在 2019 年,Flutter 推出了多个正式版本,支持的终端越来越多,使用的项目也越来越多.Flutter 正在经历从小范围尝鲜到大面积应用的过程,越来越多的研发团队加入到 Flutter 的学习 ...

  6. 干货 | 京东云原生容器—SpringCloud实践(一)

    "云原生"成为近年热词并不是一种偶然,它不是一个软件,也不是一种框架,而是一堆理念集合,以及围绕这些理念所产生的一些最佳实践的工具.云原生天然就是作用于服务架构的,可以视作一个服务 ...

  7. Golang在视频直播平台的高性能实践(含PPT下载)

    熊猫 TV 是一家视频直播平台,先介绍下我们系统运行的环境,下面这 6 大服务只是我们几十个服务中的一部分,由于并发量与重要性比较高,所以成为 golang 小试牛刀的首批高性能高并发服务. 把大服务 ...

  8. quic协议实时视频直播

    扫盲 https://www.jianshu.com/p/b7546ff9b683 demo https://github.com/felix-001/QuicRtmp https://github. ...

  9. [转帖]技术扫盲:新一代基于UDP的低延时网络传输层协议——QUIC详解

    技术扫盲:新一代基于UDP的低延时网络传输层协议——QUIC详解    http://www.52im.net/thread-1309-1-1.html   本文来自腾讯资深研发工程师罗成的技术分享, ...

  10. 一泡尿的时间,快速读懂QUIC协议

    1.TCP协议到底怎么了? 现时的互联网应用中,Web平台(准确地说是基于HTTP及其延伸协议的客户端/服务器应用)的数据传输都基于 TCP 协议. 但TCP 协议在创建连接之前需要进行三次握手(如下 ...

随机推荐

  1. [转]sublime text 4注册

    1.打开浏览器进入网站https://hexed.it2.打开sublime text4安装目录选择文件sublime_text.exe3.搜索80 78 05 00 0f 94 c1更改为c6 40 ...

  2. SqlServer获取一周内每天的金额统计数据

    select datename(weekday,CAST([CompletedTime] AS date)) WeekNum, CAST([CompletedTime] AS date) AS 'Da ...

  3. Kotlin 基础

    Kotlinbase.kt @file:JvmName("kotlinbaseTest") import kotlin.math.roundToInt as atoInt fun ...

  4. UI资源,可在几分钟内创建精美的设计

    UI资源,可在几分钟内创建精美的设计 组件:https://headlessui.com 图标:https://icons8.com 插画:https://undraw.co/illustration ...

  5. PHP 计算机码、位运算、运算符优先级

    计算机码 计算机在实际存储数据的时候,是采用编码规则的(二进制编码) 计算机码存储的过程: 原码.反码和补码,数值最左边一位用来充当符号位:符号为正数为0,负数为1 原码:数据本身从十进制转换为二进制 ...

  6. RPA的数字化标签

    随着中国经济的飞速发展,"人口红利"也正在不断消失,在过去几十年中,我们已经看到了各种智能化.自动化技术的进步对各行各业产生的巨大影响.但在现代金融行业中,仍然有许多重复.简单.繁 ...

  7. 在CentOS中安装Docker

    概述 Docker是一款使用Golang开发的开源容器引擎,我们可以使用Docker将自己的应用和相关依赖进行打包,实现在不同服务器上进行快速部署,而不需要再更多关注部署环境的差异性.结合kubern ...

  8. 消息队列RabbitMQ业务场景应用及解决方案

    目录 0. 博客参考 1. 背景 2. 技术选型 3. 消息队列的几个常见问题 4. 代码功能开发及测试 4.1 生产者 4.2 消费者 5. 源代码 6.补充:消息的顺序性 0. 博客参考 http ...

  9. 【CS231n assignment 2022】Assignment2 - Part 1,全连接网络的初始化以及正反向传播

    文章目录 前言 FullyConnectedNets 网络初始化 代码注意事项 1. W 的尺寸怎么知道? 2. np.random.norml() 3. batchnorm loss(self, X ...

  10. 使用EFCore的Code First和MySql数据库迁移

    1. 感慨一下 随着.net core的持续更新和升级,至少对于从事.net开发的人员和即将踏入这个领域的人来说,我相信大家的热情还是持续高涨的.国内的.net开发生态相比于之前来说,还是大有所好转的 ...