JavaScript 中对 socket.io 的订阅过多

Posted

技术标签:

【中文标题】JavaScript 中对 socket.io 的订阅过多【英文标题】:Too many subscriptions to socket.io in JavaScript 【发布时间】:2018-10-16 10:57:27 【问题描述】:

我正在使用供应商提供的流式传输,使用 socket.io 并使用以下代码:

var socket = io.connect('https://streamer.vendor-company.com/');
var subscription = ['sub1', 'sub2', 'sub3', 'sub4'];
socket.emit('SubAdd',  subs: subscription );
socket.on("m", function(message) 
    console.log(message);
    var messageType = message.substring(0, message.indexOf("~"));
    if (messageType == someMessageType) 
        dataUnpack(message);
    
    else if (messageType == otherMessageType) 
        anotherDataUnpack(message);
    
);  

方法dataUnpack和anotherDataUnpack对接收到的消息进行一些处理并显示到网页上。现在在这里,数组subscription 可能有大约 45 个订阅。

我想知道对我网站性能的影响。 socket.io 是否有某种方法可以不淹没客户端,或者是否有任何严重的性能考虑? socket.io 是为这种用途设计的吗?

更新

这与:Too many on-connection events with Socket.io, does it hurt? 不同,因为我的是针对 javascript/jquery 而我提供链接的问题是针对 node.js。

服务器不在我的控制之下。查看 jfriend00 的回答,如果我有 50 个订阅并且每秒收到大约 20-30 条消息,我需要在客户端处理这个问题。如果是这样,我应该担心的传入消息量是多少?如果可能的话,有什么技术/策略可以处理大量传入消息吗?

【问题讨论】:

嗨卡什亚普。让我解释一下为什么我的编辑是正确的,以及为什么如果你再次恢复它,我会向版主举报。写问题时,您不仅仅是在短期内寻求帮助:您正在解决一长串未来读者他们也有的问题。因此,他们想在问题中阅读的第一件事是问题是什么,而不是编辑来解释它的不同之处。问题也在搜索结果和标签列表中进行了总结,因此摘要(第一句话或第二句话)是对问题的有用描述。 我是一位经验丰富的编辑 - 我编辑了大约 47,000 篇文章,并且我知道编辑的工作原理。我参与了问题结束和元讨论,所以我对社区的运作也很了解。因此,当我知道社区支持它时,看到我的志愿者工作倒退让我感到沮丧。我会问,如果您不理解您帖子的编辑,并且如果编辑可能是一位经验丰富的编辑,请在 cmets 中 ping 他们并在回滚之前讨论它。我很高兴讨论我的任何修改。 您好@halfer,我尊重您的经验和志愿工作。但是在我过去的一个问题中,即使问题的标题完全不同,我也遇到过有人将其标记为重复。我什至对此发表了评论,要求解释我的问题如何接近重复,但标志仍然存在......记住这一点,我更愿意首先提及为什么我的问题不重复。但是关于你对问题的总结,我同意你不会回滚你的编辑。感谢您为保持清洁和有用所做的努力:) 我听到了。人们有时会对关闭/重复投票做出错误的判断,但这通常是可以的,因为任何问题都可以重新提出。用编辑标记问题以解释为什么它不重复是可以的(用户界面甚至鼓励这样做),但不会以牺牲未来的可读性为代价。 我什至编辑了这个问题,为什么它不重复。仍然没有变化......无论如何......现在会记住你的观点......谢谢 【参考方案1】:

socket.io 有什么方法可以防止客户端泛滥

没有。如果您的服务器向客户端发送消息,socket.io 会传递它。发送多少消息完全取决于您的服务器,而 socket.io 的工作是交付您告诉它发送的每一条消息。

或者是否有任何严肃的性能考虑?

如果您向大量客户端发送大量消息,则可能需要大量处理和带宽。 socket.io 只是 webSocket 之上的一个消息传递层,它是 TCP 之上的一个层。因此,如果您将 socket.io 消息从服务器发送到客户端或从服务器发送到所有客户端,则它是发送到客户端的多个 TCP 数据包之一。不淹没客户端的唯一方法是让您的服务器不发送超出其想要或可以处理的数量。

socket.io 是为这种用途设计的吗?

Socket.io 旨在可靠地将消息从服​​务器传递到客户端或客户端到服务器。它只是按照你说的去做。如果你告诉它传递 1000 条消息,它就会这样做。

如果您担心向客户端发送的消息过多,那么您需要修改您的服务器来控制它。例如,您可能决定不应每 5 秒通知客户端一次以上(出于效率原因)。要实现这一点,您需要在服务器上增加一个(您自己设计的)层。这不是 socket.io 的内置功能。


如果每个订阅每秒收到 20-30 条消息,并且每个客户端有 50 个订阅,那么每个客户端每秒接收 1000-1500 条消息。这在客户端或服务器端确实很多,而且可能不可持续,尤其是在服务器端,因为你有很多客户端都在做同样的事情。在每秒 1000 条消息的情况下,您必须在 1 毫秒内处理一条消息,以免落后。

除了非常小心地限制每条消息到达时的操作外,没有什么特殊的技术可以处理大量传入消息。例如,您不希望在每条消息上都触摸浏览器 DOM。也许您会将它们排队并每秒只批量修改 DOM 一次。进一步的建议需要看看您要如何处理这些消息。

更好的方法是找到一种方法来限制发送给每个客户端的消息数量,或者通过更智能地了解您订阅的内容,找到配置订阅以不向您发送太多消息的方法,或者创建一个干预您自己的服务器可以更智能地了解发送给每个客户端的内容。

【讨论】:

赞成。感谢您的解释。看着你的回答,我还有一个问题,我在问题中更新了。请看一看。再次感谢。 @KashyapKotak - 我在答案中添加了一些新信息。 @jfriend00-这里有些误会;我的意思是总共 23-30 条消息,结合所有订阅。但是在每条消息中排队而不接触 DOM 的想法是有用的。顺便说一句,我没有对收到的消息执行任何处理器饥饿操作。就像提取并显示以格式接收的消息中的特殊部分一样-“p1~p2~p3...~...p7~p8”(显示消息部分的数字)。 @KashyapKotak - 每秒 23-30 条消息并不是那么糟糕,只要您不更改每一个导致重新布局和重新绘制的 DOM。因此,也许具有间隔计时器的队列可以每隔几秒批量处理消息队列。像往常一样,你最终只需要在速度较慢的设备上进行测试,看看你的表现如何。 这很有帮助。谢谢

以上是关于JavaScript 中对 socket.io 的订阅过多的主要内容,如果未能解决你的问题,请参考以下文章

在 useEffect 中对 Socket.io 的第一个请求做出反应

Angular中的单元测试socket.io

javascript 中的 Socket.io 给出 NOT_RESOLVED 错误

javascript socket.io的快速备忘单

socket.io javascript客户端在重新启动服务器后无法重新连接

javascript Socket.io Starter