WebRTC和WebP2P

WebRTC和WebP2P

从P2P说起

传统的P2P下载中,一般有两个角色:Tracker和Peer。Peer一般是每个用户,他们之间互相传输数据(既下载又上传),Tracker则负责收集所有在下载同一资源的用户和他们的进度,让他们互相之间能够“被发现”,从而能够在复杂的网络环境中建立起连接。

P2P

实现一个P2P模式的网络需要做两件事:第一件事是让Peer们可以互相发现对方,第二件事是让Peer们可以互相建立起连接。第一件事很好办,只要能有一个公共的服务器,不论是HTTP协议,还是其他的任何协议(比如WebSocket)。第二件事需要做NAT穿透,在Web上就比较难办了。在这之前,大家都使用Flash来实现。今天,可以使用WebRTC来实现。

WebRTC

很多人对WebRTC的印象都停留在“在线音视频”的印象中。其实WebRTC全称是Web Real-Time Communications,即“网页即时通信”。在今天,它也可以用来传输音频、视频以外的信息,例如图片、二进制文件等。

WebRTC更底层使用到了ICE。一个最基本的WebRTC结构一般是由几部分组成:

  • STUN服务器
  • TURN服务器(可选)
  • Peers(客户端)

STUN服务器的工作职责很简单,它用来获取客户端的公开网络信息。例如自己的公网IP、是否能够被直接访问到等。TURN则是一个“增强版”的STUN。除了STUN本身的识别功能外,它还带有转发功能:如果不能被直接连接,它还同时承担着中继的责任。

另外,WebRTC还有一个“信令层”,它并不限制你用什么方式实现,你可以使用WebSocket,可以使用XHR……它唯一的作用,就是用来告诉其它客户端自己准备好了。

因此,如果两台机器(假设是A、B)之间需要建立连接,它们一般有这样的流程:(下面就不涉及发送流什么的了,只作为介绍基本流程)

  • A、B分别初始化一个WebRTC。
  • A创建了一个offer,它是一个SDP,然后通过信令服务器发送给B。
  • B取得A的offer,然后创建了一个answer,通过信令服务器发送给A。
  • A取得B的answer,并通过STUN和native能力拿到了自己的网络信息,生成一个Candidate,通过信令服务器发送给B,表示自己已经准备好了。
  • B取得A的Candidate,并同样创建了一个自己的Candidate,发送给A。
  • A取得B的Candidate,开始正式建立连接(P2P打洞,如果不通的话就走转发)。

整体流程图如下:

整体流程

其中涉及到几个东西:

  • Candidate:包含了基本的网络信息,例如自身局域网的IP、公网IP、TURN服务器IP、STUN服务器IP等。
  • SDP:包含了一些音视频的相关信息。

在连接正式建立完成之后,就可以互相发送数据了。

P2P CDN

现在市面上有很多利用上述技术进行CDN分发的案例了。例如阿里云有PCDN,又拍云有PrismCDN,腾讯云有X-P2P。非常典型的用户就是各大直播、视频平台了。使用P2P CDN,相对于传统的CDN来说成本更低,并且在高并发的情况下体验会更好。以直播分发为例,传统的CDN一般是:

  • 将直播流裁剪成很多个片段(长度视平台不同而不同,一般是5-10s),分发至CDN节点
  • 实时更新一个m3u8播放列表,将每个片段的URL放入其中。
  • 客户端从CDN下载片段,拼合到一起进行播放。

使用了P2P CDN之后,大体上仍然是这样,但其将片段拆的更细,将一部分内容使用P2P的形式分发。例如,原本的直播流有一个10s的片段,其大小为5MB。P2P CDN将其拆成了10个更小的片段,每个片段只有512KB,我们将其编码为片段1-片段10。

  • 用户A、B、C在同一网络或相近的网络,观看这个直播。
  • 用户A从CDN下载了片段1-10。
  • 用户B也需要这些片段,于是从CDN下载了2-10,从用户A处获得了片段1。
  • 用户C也需要这些,于是从CDN下载了2-9,然后从用户A处获得了片段1、从用户B处获得了片段10。
  • ……

这样下来,可以发现,实际上用户A的体验会有一定降低(因为被拆成更多次的请求,导致整体稍慢一些),但是用户B、用户C,因为其从更近的地方下载到了部分片段,整体体验反而更佳。对于CDN厂商来说,流量成本也有所下降。

以斗鱼为例

举一个实际的例子:斗鱼。斗鱼大规模使用到了P2P CDN。初步观察其使用到了很多家服务,包括腾讯云、阿里云、聚网优速,以及自建服务(使用了网宿CDN)。

  • 在观看直播时,其会建立一个类似于trk-xxx-xxx-xxx-xxx.douyucdn.cn的WebSocket长连接作为信令。
  • 通过其获取到其他客户端,并与其交换所需要的数据,建立起连接。

有一位群友碰到了上行网络被斗鱼占满的情况。其实理论上不会出现:斗鱼只会将众多片段的一部分进行上传。但如果真的出现了,可以通过屏蔽P2P连接的方式,使其降级为传统CDN。屏蔽方式很简单:屏蔽信令服务或者屏蔽STUN服务。其中,腾讯云的STUN服务是IP地址形式,不太好屏蔽。但是它们的信令不约而同都采用了WebSocket,反而比较好屏蔽。

举个例子,使用uBlock将它们加入黑名单,即可屏蔽掉对应的WebSocket连接:

/trk-([0-9\-]+)\.douyucdn\.cn/
||signal.qvb.qcloud.com
||.trk.galaxyclouds.cn