Kurento WebRTC连接在约30%的情况下失败

3
我已经花了几天时间寻找连接问题,但没有任何进展。我正在尝试使用Kurento实现一个相对简单的一对一呼叫。
以下是Kurento的调试日志,其中显示了连接成功和连接失败的情况。
如果您需要更多的日志(例如客户端、信令服务器、tcpdump或Kurento的跟踪日志),请告诉我,我会提供!
非常感谢您的帮助或新的输入!
问题描述:
在大约30%的情况下,无法建立WebRTC连接。不幸的是,我没有任何模式可以确定何时可以建立连接,何时不行,这似乎完全是随机的。我在同一网络中,使用相同的设备、TURN服务器和信令协议,但在30%的情况下,无法建立连接。
当我在本地运行应用程序时,它似乎更加可靠,几乎可以100%地建立连接(或者甚至100%的时间,我测试了很多次,已经失去了追踪)。我使用docker在本地设置基础架构,并在不同的网络中运行不同的容器(TURN、Kurento、信令)来模拟生产部署。
我们在开发和生产环境中都遇到了相同的问题。在我们的开发环境中,我们没有任何防火墙,所以这似乎不是问题的原因。
我尝试找出问题的原因:
主要是比较工作和不工作的情况下的日志,但我未能找到任何重大差异,可以指向问题。
我已经测试了WebRTC连接通过TURN服务器(使用Firefox和force_relay标志)和直接通过Kurento,但在两种情况下,连接在约30%的情况下失败。
我尝试过过滤掉所有不是Relay候选者的ICE候选者。
我已经嗅探了我们的信令服务器(也控制Kurento)和Kurento之间的流量,以查看JSON RPS消息交换中的任何差异,但它们似乎基本相同。
我已经使用此工具测试了我们的STUN和TURN服务器:https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/ ,并获得了看起来正确的服务器反射和Relay候选者。

我嗅探了成功和失败连接的客户端流量,但发现有显著的差异。

我简化了Kurento媒体管道(没有录制,没有集线器),但行为是相同的。

我使用了不同的浏览器(Chrome,Firefox和本机iOS实现),但行为是相同的。

在连接可以建立的情况下,Kurento调试日志:

https://gist.github.com/omnibrain/2bc7ad54f626d278d3c8bac29767ac4c

一次连接无法建立的Kurento调试日志:

https://gist.github.com/omnibrain/f7caee04a5c6d77ea22a9ccfa95dd825

2个回答

10
经过数天的调试,我们终于找到了问题的原因:
我们使用了Socket.IO的Swift客户端和Java Netty Socket.IO服务器实现。客户端(iOS)使用长轮询与服务器(Java)通信。事实证明,Netty Socket.IO服务器正在对Swift Socket.IO客户端的长轮询负载进行URL解码,但Swift Socket.IO客户端实际上并没有对其进行URL编码。这意味着从Swift Socket.IO客户端发送的每个“+”都会在服务器上被替换为一个空格。为什么这是个问题?因为客户端的SDP提供了一个ufrag,其中可以包含加号符号!因此,如果SDP包含“+”,它将在服务器上被替换为一个空格,这将导致STUN ping失败,因为无法验证消息完整性。

感谢您在Kurento社区论坛分享经验,我已将您的案例添加为文档“故障排除”部分中需要关注的事项之一:https://doc-kurento.readthedocs.io/en/6.12.0/user/troubleshooting.html#webrtc-connection-is-not-established - j1elo
@j1elo 这可能是我人生中追踪的最难的错误。我永远不会忘记那个时刻。希望这能够拯救一些可怜的灵魂,使他们免受我们在那段时间所承受的压力和挫折的折磨 :) - omnibrain

3

根据您的追踪信息,您的工作案例选择候选人10 然后 选择候选人7,而不工作的案例只选择候选人10。

kurento_logs_webrtc_working.txt

New candidate pair selected, local: 'candidate:10 1 UDP 335544831 10.10.36.134 50589 typ relay raddr 172.19.0.2 rport 9', remote: 'candidate:3993072200 1 UDP 41885695 10.10.36.134 53894 typ relay', stream_id: '1', component_id: 1
...
New candidate pair selected, local: 'candidate:7 1 UDP 1677722111 10.10.36.131 46842 typ srflx raddr 172.19.0.2 rport 46842', remote: 'candidate:266015763 1 UDP 2122260223 10.10.1.57 55125 typ host', stream_id: '1', component_id: 1

kurento_logs_webrtc_NOT_working.txt

new candidate pair selected, local: 'candidate:10 1 UDP 335544831 10.10.36.134 51280 typ relay raddr 172.19.0.2 rport 9', remote: 'candidate:3993072200 1 UDP 41885695 10.10.36.134 51287 typ relay', stream_id: '1', component_id: 1

我的第一反应是你在重复使用旧的候选者,但端口已经改变了。更换浏览器可能会改变候选者编号,我没有预料到它们在运行之间会是确定性的,所以我不得不看两次。

日志中有一个小差异 - 非工作状态下的 IceComponentStateChangedcandidate:266015763 出现之后而不是之前变为 connecting。我不知道这是否重要。

一般注释:

过去我们遇到了几类问题:

  • 客户端丢失 ICE 候选者 - 一些候选者在准备好之前就被发送了,因此我们需要将它们排队。如果我没记错,SDP 提议(或回答)中可能有一些候选者,因此您的侦听器需要在启动之前准备好。
  • 我们正在发送旧的候选者 - 在信令服务器中使用了错误的重放元素向客户端提供候选者,这些候选者不再有效。

我建议您使用带有 chrome://webrtc-internals 的 Chrome 进行帮助。在 webrtc-internals 中可以看到 ICE 候选问题,因为您可以看到状态机如何遍历其状态。在我们的工作案例中,转换比损坏的案例多得多。

为三个 ICE 事件添加客户端侦听器也很有帮助:

this.peer.peerConnection.oniceconnectionstatechange = this.logloglog.bind(this, this.peer.peerConnection);
this.peer.peerConnection.onicegatheringstatechange = this.logloglog.bind(this, this.peer.peerConnection);
this.peer.peerConnection.onsignalingstatechange = this.logloglog.bind(this, this.peer.peerConnection);

这让你可以看到谈判的进展情况,但基本上就是在 chrome://webrtc-internals 中所显示的内容。
最后注意一点,这是我在日志部分使用的代码: /etc/default/kurento-media-server

# ICE debug logging: uncomment to enable in KMS and in the 3rd-party library 'libnice'
# - Note: This can get very verbose, log size will explode in the long term
#export GST_DEBUG="$GST_DEBUG,kmsiceniceagent:5,kmswebrtcsession:5,webrtcendpoint:4"
export G_MESSAGES_DEBUG="libnice,libnice-stun"
export NICE_DEBUG="$G_MESSAGES_DEBUG"

我不记得它们是否比你使用的更好,但我会提出这个观点。


非常感谢你阅读了所有内容。今天我们终于找到了约三分之一连接失败的原因。我很快会发布答案。 - omnibrain
你发布了答案吗? - J. Longman
感谢您追踪此问题。我已经想出了一个解决方法,即在失败时进行重试,这可能需要几次尝试,但最终会连接成功。是否有修复此错误的方法?我正在使用Windows 10上的Chrome在两台PC之间进行测试,以排除其他变量。当将前两个用户连接到组呼时,似乎从未出现过这种情况,但是随着我添加更多用户,我看到它们都在发送和接收时失败并重试。 - Andrew Lindzon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接