SockJS 是如何选择协议的?
Posted
技术标签:
【中文标题】SockJS 是如何选择协议的?【英文标题】:How is SockJS selecting the protocol? 【发布时间】:2019-11-18 11:14:14 【问题描述】:我将首先从我所知道的开始,因为它可能对其余部分有用。
很明显,您可以使用协议子集来实例化 SockJS:
sockJsProtocols = ["xhr-streaming", "xhr-polling", ....];
socket.cliente = new SockJS(url, null, transports: sockJsProtocols));
我还发现,当 SockJS 调用 /info 端点时,服务器返回 websockets true 或 false(取决于服务器兼容性)。
我也知道漂亮的表 here 有 3 列:websockets、流和轮询。
但我有两个问题:
1) SockJS 如何决定轮询、流式传输或 websockets?它不能与浏览器兼容性有关,因为我在我们的日志中看到了许多与最近浏览器的 XHRStreaming 会话。这怎么没有记录在任何地方?
2) 为什么 SockJS 每次都需要调用 /info?服务器的兼容性将始终相同。
【问题讨论】:
【参考方案1】:好的,我必须阅读 SockJS 客户端的源代码才能了解它是如何工作的。现在我愿意。这个答案是有效的,至少对于 SockJS 1.3。
SockJS 正在计算 /info 调用的 RTT(往返时间)。然后它需要这个时间并计算一个 RTO(重传超时)。如果 RTT 小于 100ms,那么它只是简单地增加 300ms,否则,它乘以 4。
然后将 RTO 乘以每个协议的往返次数,对于 websocket 来说显然等于 2。
然后在我们打开 websocket 连接时将其用作超时,直到我们收到 OPENED 帧(Stomp CONNECTED 帧)。当这超时时,SockJS 只是关闭协议套接字并尝试下一个。如果没有剩余协议,它将重新重试。
根据团队所做的一些实验,整个逻辑听起来非常基于数据和推测性。为什么是 300 毫秒?为什么websocket的往返是2?。更令人惊讶的是,在客户端或服务器端都不能真正覆盖这个值(服务器可以用 /info 调用中的响应覆盖这个值)
这实际上意味着,如果您的 Stomp 服务器创建队列的速度太慢,客户端将在协商中丢失。
假设您的客户端距离服务器不远,那么它很可能会退回到 客户端必须在 700-800 毫秒之间接收到 CONNECTED 帧。
我找不到解决此问题的其他方法,除了通过过滤器将 /info 调用的处理速度减慢一定数量,该数量是根据测量我们的延迟到我们的代理中继的平均值而根据经验计算得出的。
【讨论】:
以上是关于SockJS 是如何选择协议的?的主要内容,如果未能解决你的问题,请参考以下文章
markdown WebSocket SockJS STOMP协议
如何使用 spring+stomp+sockjs 获得 websocket 响应
春天的 websocket stomp over sockjs 重定向到 http 协议,而在关键的 web 服务中起源是 https