rainzhaojy / blogs

200 stars 28 forks source link

如何建立更快更稳定的网络连接? #6

Open rainzhaojy opened 7 years ago

rainzhaojy commented 7 years ago

WebRTC应用里能连上只是最基本的用户体验, 用户还需要能够更快的连接和更稳定的连接.

Quick Call Setup

ICE协商需要一些时间, 可能从几秒至十几秒不等, 这个时间对于用户而言还是比较长的, WebRTC支持Trickle ICE, 使得用户有机会在完成所有ICE协商之前就建立连接.

然而, Trickle ICE仍然需要一些时间, 另一个业界认可的做法是TURN First:

WhatsApp, Facetime等都是这么做的.

Low Latency

如果用户A在Boston, 用户B在Singapore, 你的TURN Server在London, 那么A和B之间的网络连接可能如下:

    A <-----> TURN <-----> B
(Boston)    (London)    (Singapore)

不管A和B的网速多快, A和B之间的网络延迟(RTT)都不会小, 网络传输是hop by hop的, 经过的hop越多, 丢包率越高, RTT越大. 要想减少latency, 需要尽可能减少hops, 同时改善hop to hop的传输速率.

解决这一问题的有效办法是在全球部署多个Relay POPs, 让用户能够经过最少的hops到达Relay POP, 然后Relay POPs之间建立高速专线连接.

如果你有SFU/MCU, 那么可以在全球多个DC里部署SFU/MCU, 你的DC应该离主要用户群尽可能近一些, 然后DC之间使用专线连接. 一般的视频会议产品都是这么部署的.

那么, 如何找到最近的节点呢? 常见的做法是by GEO, 可以via DNS, via Geo IP, 或者via device location.

ICE Restart

在通话过程中, 有可能会出现RTP连接断开, 如果不做处理, 就会出现假连接, 或者单向连接等问题. 要处理这些断网问题, 首先要能够监测出断网.

WebRTC本身提供了事件: PeerConnection.oniceconnectionstatechange, WebRTC spec里定义了几种ice state, 和断网相关的有: disconnected, failed, closed. disconnected之后有可能会自动重连也可能会变成failed.

当收到上面几个有可能是断网的ice state change事件后, 就可以开始ICE restart了, 示例代码:

pc.createOffer({iceRestart: true})
  .then(function(offer) {
    return pc.setLocalDescription(offer);
  })

新创建的offer SDP里的ice-ufragice-pwd与之前的是不一样的, 这是ICE协议的要求. 接下来将offer SDP送给peer重走一次offer/answer, ICE candidates交换流程, browser会重新建立WebRTC连接.

Reliable Connections

仅仅依靠oniceconnectionstatechange监测断网可能是不够的, 也许有如下方法帮助监测断网状态.

Client应该和Signaling Server也有连接(可能是WebSocket, TCP Socket, etc), 或者你的所有media都通过SFU/MCU, 那么你可以监测信令通道或SFU/MCU的连接来确定断网状态, 下面也许是可行的方法::

不同产品可以有不同的方法, 你应该用尽可能多的办法来监测网络是否有断开.

Lite ICE

如果你的产品有Media Server (SFU or MCU), Server是有公网IP的, 那么可以支持Lite ICE. Lite ICE+Aggressive Mode可以非常快的建立网络连接.

在 #4 里我们介绍了TURN over TCP的方式来实现TCP连接, 使用Lite ICE后, 也可以使用STUN over TCP来支持TCP连接, STUN通常基于UDP, 但也是支持TCP的, Server可以返回tcp candidate, 浏览器检查UDP candidate pair连接失败但TCP candidate pair连接成功, 接下来浏览器会使用TCP连接.

Conference Server

有很多创业公司都是完全P2P的, 5人以下的群聊使用Mesh方式, 这样的方式可以大大节省开发,部署和运维Server的成本(只需要Signaling Server). 但多数面向企业的在线视频会议产品都不是P2P的, 都是有Switching Server的, 当然出于成本和效率考虑, 一般都不做transcoding.

下面是Conference Server的几个特点:

CDN

在某些应用场景下, 可以考虑使用CDN加速, 譬如网络直播应用里的用户端, 或者超级大会里的参会者, 网络流媒体以下行为主, 这时可以使用CDN加速. 主播端和主持人端使用其他的网络架构.

aisnote commented 7 years ago

cool

tc214 commented 6 years ago

hi,请教一下,我正在做一款移动IM App,使用Mesh网络架构,无服务器,使用UDP来好友发现。在网络不好的情况下,peer连接很容易断开disconnet,如果断了想通过重启ICE重新交换SDP的话,还需要重新建立TCP连接来发送SDP,感觉很麻烦,是不是这种网络架构不合适呢?

rainzhaojy commented 6 years ago

@tc214 你有信令服务器吗,SDP交换是通过信令服务器分发的吧,流媒体可以通过mesh网络分发

tc214 commented 6 years ago

@rainzhaojy 没有部署任何服务器

rainzhaojy commented 6 years ago

@tc214 建议部署一个信令/业务服务器,这样你的系统可以做的更鲁棒