SockJS 是如何选择协议的?

How is SockJS selecting the protocol?

我会先从我所知道的开始,因为它可能对其他人有用。

很明显,您可以使用协议子集实例化 SockJS:

sockJsProtocols = ["xhr-streaming", "xhr-polling", ....];
socket.cliente = new SockJS(url, null, {transports: sockJsProtocols}));

我还发现当 SockJS 调用 /info 端点时,服务器返回 websockets true 或 false(取决于服务器兼容性)。

我也知道 table here 有 3 个栏目:websockets、流式传输和轮询。

但是我有两个问题:

1) SockJS 如何决定轮询、流式传输或 websockets?它不能与浏览器兼容性有关,因为我在我们的日志中看到许多与最新浏览器的 XHRStreaming 会话。这怎么没有在任何地方记录?

2) 为什么SockJS每次都需要调用/info?服务器的兼容性将始终相同。

好的,我必须阅读 SockJS 客户端的源代码才能了解它是如何工作的。现在我知道了。这个答案是有效的,至少对于 SockJS 1.3。

SockJS 正在计算 /info 调用的 RTT(往返时间)。然后它会花费这个时间并计算一个 RTO(重传超时)。如果 RTT 小于 100ms,那么它只是简单地加上 300ms,否则,它乘以 4.

然后将 RTO 乘以每个协议的往返次数,显然对于 websockets 等于 2。

这被用作超时,从我们打开 websocket 连接开始,直到我们收到 OPENED 帧(Stomp CONNECTED 帧)。当超时时,SockJS 只是关闭协议套接字并尝试下一个套接字。如果没有剩下的协议,它将重新尝试。

根据团队所做的一些实验,整个逻辑听起来非常基于数据和推测。为什么是 300 毫秒?为什么 websocket 的往返次数是 2?更令人惊讶的是,无论是客户端还是服务器端都无法真正覆盖此值(服务器可以使用 /info 调用中的响应覆盖此值)

这实际上意味着,如果您的 Stomp 服务器创建队列的速度太慢,客户端将在协商中丢失。

假设您的客户端离服务器不远,那么它很可能会退回到 < 100 毫秒的 RTT。因此,客户端必须在 700-800 毫秒之间接收到 CONNECTED 帧

我找不到解决此问题的另一种方法,除了使用过滤器减慢 /info 调用的处理速度,根据经验计算出一定数量,这些数量是根据我们对经纪人中继的平均延迟进行测量的。