回顾XP2P的发展历程,由为近几年兴起的直播业务节省带宽成本为出发点,经过日益发展完善,XP2P已经在底层借助STUN、端口预测、生日攻击、UPnP构建了完善的互联直连基础,并且在直连的UDP连接的基础上拥有了高效、可靠传输协议XNTP,借此再高屋建瓴,在之上实现了广泛应用的HTTP协议,至此万物互联的服务框架已经基本搭建完成,具备网络负载小、传输性能高、稳定的特点。本文来自于腾讯云高级工程师张鹏在LiveVideoStackCon2019北京站上的精彩分享。
文 / 张鹏
整理 / LiveVideoStack
大家好,我是腾讯云张鹏,从2014年开始一直深耕P2P技术,攻克P2P技术难题。
在过去几年中,腾讯云XP2P技术已在多个产品线落地并经受了大流量阅兵直播、赛事直播等考验,今天我将为大家着重讲解腾讯云P2P技术在网络穿透、网络传输以及网络拓扑组建等方面内容。
1. 什么是XP2P?
P2P架构体现了互联网架构的核心技术,简而言之就是“你有、我有、大家都有的东西,大家相互联接共享之”,因此这种概念被描述在RFC 1里面,可谓由来已久,是最早互联网建设者心中最梦寐以求的架构。
那为什么到现在一直仍是中心化的服务模式呢?
主要还是它的一些历史原因和技术原因没有解决。
但是我们依旧能在近30年互联网技术飞速发展中看到P2P的产物,比如netsper、PPlive、bt,此外06-08年是国内P2P学术圈的黄金时期,国内高校有着非常高的产出,如清华大学的GridMedia、香港科技大学的CoolStreaming、华中科技大学的AnySee等等,代表着当时流式P2P的最高境界了。
2008年之后,由于P2P流量给网络带来了很大的负载,经历了运营商的打压陷入一段低潮期,直到2014年直播兴起,腾讯云XP2P也再次重新进入云服务市场。
2. XP2P产品功能
2.1 穿透篇
2.1.1 P2P的NAT穿透
说到P2P就肯定要讲到它的起点——如何建立起互联的关系。
我们知道IPv4地址已经日益衰竭,现在家庭带宽中“猫”的路由器的出网IP已经不是公网IP了,而NAT(网络地址转换)可以解决这个问题,当然NAT也是一把双刃剑。
比如当我们在发送请求的时候,我们用内网地址加一个端口标识这个请求,当请求数据来到因特网,则被NAT映射成一个公网地址和端口。
但这时就会带来一个问题,虽然我们知道对方的地址,但却无法连接,这是因为我们在发送数据时,由于对方NAT并不认识我而被阻止,因此我们需要首先把Peer之间建立起连接的过程打通。
下图描述了通过中间转发服务器把两个Peer打通的过程。
2.1.2 NAT类型
最新的STUN协议对NAT类型分为7种:
Open Internet、UDP Blocked、Symmetric Firewall、Full Cone、Restricted Cone、Port Restricted Cone、Symmetric。
关于它们的介绍,在此请看下PPT,不做过多介绍了,只简单说一下,对称型是最难办的,对称型在连接不同外部Peer时会拥有随机的不同映射地址,因此它也有了端口限制型的特点,难以穿透。
2.1.3 STUN协议
STUN协议就是探测前面提到的7种NAT类型的协议,它的包格式如下图左侧显示,右侧为其流程图,这张图中有几点需要特别注意:
首先是Test II,它是请求原来的STUN服务器地址,然而是换一个IP给我回包看是否可以收到。
第二点是Test III,它是请求原来的STUN服务器地址,然而是换一个端口给我响应看是否可以收到。
这两点尤其需要特别关注。
目前大多数P2P应用都是基于STUN协议做穿透建立直连通道,但STUN协议并未完全解决问题,它无法建立起对称型和端口限制型、对称型的连接。
下图是一个对称型连接端口限制型的案例:
对称型和端口限制型都会连接一个外网的打洞服务器,它们彼此知晓地址,当对称型向端口限制型发包时,由于目标地址变了,因此也换了一个新的映射地址,建立的一个新的“洞”;
然而通过打洞服务器中转给端口限制型的信息里面,仍然是对称型之前与打洞服务器建立的旧“洞”,导致此时端口限制型可以回包,但是返回的是给旧“洞”,与对称型计划与该限制型通信的新“洞”不同,因此通信被拒绝,打洞失败。
更加雪上加霜的是,伴随安全等级的提升,对称型和端口限制型越来越多,而STUN对此却无能为力,非常遗憾。
2.1.4 攻破对称型NAT穿透:
端口预测
如何攻破对称型NAT的穿透成为了P2P技术的关键之一。
此前一篇论文提出一个方式,通过端口预测的方式来解决对称型NAT的穿透:
首先Client到外网探测自身端口变化规律,相当于端口预测;
Sever也同样探索自身端口变化规律;
最后通过穿透服务器中转知晓彼此信息并预测对方下一次端口,朝其发包,从而实现成功打洞。
这个放在当年是可行的,因为当年95%的设备都是端口递增的;
然而如今NAT端口变化大部分却是随机的,因此也很遗憾。
那我们到此就束手无策了吗?
依然还剩下大部分随机端口对称型连端口限制型、对称型的case悬而未决!
2.1.5 攻破随机端口对称型NAT的穿透:
生日攻击
我们知道端口限制型的地址是不会变的,而随机端口对称型的映射地址是随着目标地址变化而随机变化的,那他们两个怎么打洞建立起直连通道呢?
受端口预测方式的启发,其实还是能够以较小代价打通的。
这里采用的方案是生日攻击法,也即是随机碰撞的原理来实现穿透。
生日攻击来自于生日悖论,讲的是一个会议室坐着23个人,一年有365天,他们中任何一个人的生日可能在任何一天,然而他们中至少有一对是同一天生日的概率为50%。
更直白点,是利用了远小于样本集(生日共有365种可能)的尝试次数(23个人),便能很大概率收获到一对相同采样碰撞(同一天生日)的结果。
那么,假如样本集是65535个端口,要想两方随机打洞多少个端口,才能让两方刚好碰撞成功一次的概率达到80%呢?
它具体是这样做的:
1. 随机型NAT通过新建socket,朝端口限制型的外网地址发包,这些包在出NAT时,会被随机映射成不同的“洞”
2. 端口限制型,随机地向对方不同端口地址发包。
然后看,是否有一个目标端口恰好发送给第1步里面随机型NAT映射的外网端口“洞”上,如果碰对,即可成功建立起连接
双方通过向对方各自发400个包,即可让穿透成功率达到80%以上,而400个包的代价,每个包只包含IP头部、UDP头部、连接ID,再加上一个以太网帧头部,顶多50字节,400个包总共也就20KB,以此换取优质节点的连接成功,还是完全可以接受的。
生日攻击的手法,大大提高了两方成功建立起连接的可能性。
但是仅仅如此还是不够,生日攻击只能应付对称型与端口限制型的穿透,然而随机端口对称型与对称型的连接依旧无法建立!
2.1.6 UPnP:
变Symmetric NAT为Full Cone
UPnP协议(通用即插即拔服务)是一个旨在让家庭设备与互联网其他设备无缝建立起连接,并简化网络过程的协议。
它其实更像是一个物联网协议,包罗万象。
我们发现其中包含两个服务WANIPConnection和WANPPPConnection,它们可以从内网主动添加到外网的Full Cone型端口映射,因此对于对称型难以穿透的情况,我们就可以使用这种协议将它转变为Full Cone型,从而进一步提升穿透成功率。
到此为止,我们已经几乎实现了最优的peer to peer的穿透方案,比WebRTC更优,比libp2p更优,并会达到一个很好的连接建立成功率,这将是我们P2P的核心基础。
2.2 传输篇
2.2.1 TCP协议的弊端
提到传输协议就不得不说TCP,它是互联网这二、三十年来的基础,但它同样存在一些薄弱环节:
首先就是启动慢,TCP有一个慢启动——每次是以倍增的速度去尝试直到一个阈值,它从一个很低的初始速度上升到理想速度,中间需要很多回合的RTT,所以称之为“慢”启动。
在初始阶段,它的增速甚至不如一个固定的较大斜率的直线增速快。
第二点是拥塞控制差,TCP每个回合会增加一个包(发送窗口),一旦超过网络最大限制,就会直接减少一半,从而就使得它的平均发送速率只能达到网络的75%。
第三点是TCP的抗抖动、抗丢包差,大家可能都听过一句话“TCP丢包率超过20%,基本就废了“,这里给大家举一个例子:
假定我们的丢包率是30%,也就是说一个包连续丢三次的概率就是2.7%,这意味着当加性增发数据到累计发了40个包后,就会发生一次连续3次重复ACK,从而导致速度降为一半,循环往复TCP的速度也就再也起不来了。
最后是重传歧义,当发生丢包之后,在下一个回合接收到这个包,然而我却无法确认接收到的是原本的包,还是重新发送的包。
2.2.2 XNTP之Pacing
针对TCP的问题,我们的协议做了很多优化。
首先是Pacing发送,Pacing发送我理解就是均匀的发送,在早期的TCP的发送方式,可能一刻间交给网络去传输该RTT内要发送的所有包,然后RTT会越来越大,因此它会有排队, RTT进而变得更大,这样会发送更多,最终会导致路由器排队撑不过来,就会导致丢包,网速抖动。
更好的传输方式是均匀的发,一个RTT是40毫秒,我发40个包,这里每一毫秒发一个包,然后一毫秒之后再发另外一个包,这样对路由器非常均匀,就可以不会哪样频繁地丢包,把网络利用上去。
Pacing-Race本身并无稀奇,它仅是我们传输协议的基础,后续的很多优化其实都依赖它。
2.2.3 XNTP之抗抖动
我们对于抗抖动的策略是来源于QUIC的灵感,QUIC每包有两个序号:
包序号和内容序号,我们认为,它才是解决网络传输抗抖动的关键,达到了发生拥塞时,滑动窗口不停滞的效果。
假设正常发包,滑动窗口是11,接收方在接到第11个包之后发送ACK表示第2个包丢了,TCP会把滑动窗口滑到[2,13],然后重传2和11包,效率底下;
而QUIC遇到丢包时则会以新的包序号重传,而该包的内容序号不变,效果则是相较于TCP类似于滑动窗口直接滑到[12, 23],丢的包以新的序号12、13进行传输,滑动窗口不影响。
这样就使得即便在20%丢包率的情况下,依旧可以使用剩余的80%网络传输数据。
2.2.4 XNTP之“快启动”
我们首先了解下Google的BBR,它有两个关键因子:
探测到的最小RTT和最大带宽,从而确定最优发送法:
本次发送量=最小RTT * 最大带宽。
这个思路同样可以借鉴到“快启动”中吗?
我们之前提到过Pacing虽然解决了TCP发送队列缓存延迟问题,但是在初始速度方面仍存在自身劣势,那突发就一无是处吗?
突发的意义在于让发送方的发送速度达到了瞬间无限大,我们的解决思路便是依赖于此!
我们认为首包的RTT就是最小RTT,并且在前面少量几个包采用突发的方式,比如第一回合发送的10个包中前4个包采用突发,突发的方式也意味着发送速率无限大,因此接收方可以通过统计这4个包的接收速度得到一个我们认为近似的最大带宽,从而1-RTT后拿到ACK的时候,最小RTT、最大带宽都拿到了,使用BBR的方式,便可以得到一个“最优发送法”,结束慢启动,进入拥塞控制。
像快启动这样的网络传输创新,我们还有很多其他对传输协议的系统性的认知,在经过多方验证数据后,我们也会努力开放给学术界、工业界的朋友,由于时间原因,暂时不先过多介绍了。
2.3 应用篇
有了XNTP提供的这种可靠传输,相当于有了“TCP”,我们也顺势在XNTP上构建了HTTP语义,这里不仅实现了HTTP的基本语义,还实现了HTTP 2的多路复用——在同一个链路上复用多个流,除此之外我们也实现了HTTP Client和HTTP Server。
也就是在P2P很高的连接成功率和XNTP很好传输性能的基础上,在HTTP协议上可以构建HTTP服务。
我们知道Unix的简单哲学之一体现在“一切皆文件”,而我们这套框架也可以简单理解为“一切皆服务”,以后也会一直奉行这个简单的思路,而XP2P/PCDN自然而然也就成为这套框架的第一个应用服务。
2.4 P2P技术怎么做?
2.4.1 必要条件 — 切片
对于P2P技术实现,首先所有节点都要有全网数据一致性,也就是你的某一片数据和我的这一片数据一定是相同的,否则就没意义。
对于点播而言,文件长度和播放时长都是确定的,因此数据一致性的实现算法非常简单,易于实现。
但是对于直播来说,直播内容稍纵即逝,并且每个观众观看直播的时间点也不相同,因此无法像点播一样按照Offset分片。
2.4.2 P2P针对直播的切片
针对直播的切片,传统方式包括按照dts制定,或者使用中心服务器将直播流切片为小文件来约定数据一致性,比如HLS和DASH。
而我们目前采用的方式是直接在原始直播流上做切片,FLV和FMP4在格式中天生带有明显边界信息——FLV的tag或FMP4的box,因此我们只需要和其他Peer约定好起始节点和边界信息,就可以突破在原始直播流上实现P2P的限制。
2.4.3 P2P的自适应码率
在直播中流畅的观看体验是非常重要的,而HLS和DASH天生是为自适应码率而生的,它们会在网络条件较差的时候自动切换到较低的码率,我们知道HLS和DASH是对直播流做了切片,而FLV和FMP4则不需要,只要在一个HTTP链接,把新的解码参数给到客户端(播放器)就可以实现自适应码率。
那相比于HLS和DASH有什么优势呢?
大家都知道,HTTP 2相比于HTTP 1.1最大的改善是把多个HTTP请求用一个TCP连接传输,因为单一TCP连接的拥塞控制和顺序到达是要比多个TCP连接的拥塞竞争要好的,然而HLS和DASH却反而把直播流请求变成多个连接的文件请求,这其实是一个倒退。
而我们直接在一道流式直播上实现自适应码率,我们认为是比HLS、DASH还要领先的技术。
2.4.4 P2P网络拓扑结构
下面是三种比较常见的网络拓扑结构:
网状模型、树状模型、平均分流模型。
各有各的优点和缺点。
但你要问我们腾讯云用了哪种模型,答案是我们那种都没用!
目前腾讯云使用的是网状模型和树状模型的混合模型,在结合两者优点的同时,相对减少了树状结构的层数,从而平衡树状模型所带来的弊端,这也是腾讯云P2P和分享率做的很好的原因。
3. XP2P应用场景
提到P2P应用场景,首先会想到流量分发加速,比如直播、点播和文件下载场景的应用,其实P2P发展到今天,已经不怎么会引起网络高负载,而是更友好地提升网络能力。
我们认为P2P其实是实现了某种程度上的多播协议,起到了优化带宽传输,降低网络负载的功能:
比如同一小区有两个人观看同一个视频,其实只有一个人需要从远程服务器拉取数据,另一个人可以通过内部网络分享获取,这样就减少了数据包在网络上流转,从而降低网络负载。
特别值得一提的是,我们实现了很高成功率的P2P穿透,实现了可靠的网络传输和HTTP,我认为再结合边缘计算、雾计算是很有可能打破现在的中心化部署服务的限制,有可能将简单服务器部署在真正的分布式网络中。
4. XP2P的未来与展望
最后,我们对XP2P的未来进行展望。
腾讯云X-P2P某种意义上实现了多播协议,即优化了网络质量,又降低了网络的负载;
而456(4K、5G、IPv6)的到来,将会使X-P2P进一步发挥能力和得到更广泛的应用;
区块链的底层所使用的P2P技术和腾讯云X-P2P有异曲同工之妙,然而libp2p除了搞了一堆不必要的概念,还没有看到怎么接触到穿透的核心技术;
边缘计算也将依赖稳健、安全、高效的P2P技术底层;
XNTP传输协议会继续优化,未来甚至将可以和quic相提并论;
特别值得一提的是,雾计算绝不止流量分享这样的应用那么简单,它还需要一股风真正把它重定义,就像当年AWS重新定义云计算那样伟大。
而这套万物互联的服务框架,将遵循一切皆互联服务的简单思路继续发展,可能就是重新定义雾计算的钥匙,这才是更令人兴奋的!
LiveVideoStackCon 2019深圳讲师招募
12月13-14日,LiveVideoStackCon首次来到深圳,将全球前沿多媒体技术实践与深圳本地产业结合,触发技术与商业灵感。欢迎将你的技术实践、踩坑与填坑经历、技术与商业创业的思考分享出来。请将个人资料和话题信息邮件到 [email protected] 或点击【阅读原文】了解成为LiveVideoStackCon讲师的权益与义务,我们会在48小时内回复。
LiveVideoStack正在招募编辑/记者/运营,与全球顶尖多媒体技术专家和LiveVideoStack年轻的伙伴一起,推动多媒体技术生态发展。同时,也欢迎你利用业余时间、远程参与内容生产。了解岗位信息请在BOSS直聘上搜索“LiveVideoStack”,或通过微信“Tony_Bao_”与主编包研交流。