【问题标题】:Drop Packets If Falling Behind With Socket.IO in Node JS如果在 Node JS 中使用 Socket.IO 落后,则丢弃数据包
【发布时间】:2013-10-22 17:40:54
【问题描述】:

我有一个实时传感应用程序、多个客户端、一个处理服务器。

我有一个问题,我使用 Socket.IO 和 NodeJS 尽可能快地将数据推送到客户端。问题似乎是客户端从服务器上发出的传入数据开始堆积,客户端落后(不同步)。

有了足够的吞吐量,客户端就可以正常运行。有什么办法可以强制执行一项策略,服务器/客户端将丢弃任何早于指定时间段的发射?

数据被丢弃,客户端应该保持最新,所以我不担心丢失超过 2 秒的数据。

【问题讨论】:

    标签: javascript performance node.js websocket socket.io


    【解决方案1】:

    为了帮助可能遇到此问题的其他人,我设计了一个锁定系统,以便服务器仅在套接字空闲时发布数据。

    这意味着服务器仍然尽可能快地发布,它只是不会堆叠几个传出的数据请求。请注意,这仅在您的消息被丢弃并且您需要最新信息时才有效。这也意味着消息之间存在一些开销,因为客户端必须通知服务器它已准备好接收更多消息。

    然而,这意味着我的应用程序保持最新,不会因请求堆积而落后,如果您在本地运行一个浏览器并通过网络运行另一个浏览器,这在之前很明显。

    Server.js

    var socket = ...; // Create socket
    
    // Create my data, in my project this updates very quickly
    // roughly 60 times per second
    var my_data = ...;
    
    // Initially set receiving to false as the socket
    // has no outgoing data
    socket.set('receiving', false);
    
    // Listen for received event, this indicates
    // that the client has received an update
    // and is now ready to receive more
    socket.on('received', function() {
        socket.set('receiving', false);
    });
    
    // Function will be called repeatedly to send out data
    function update() {
        // Check if the socket is receiving any data
        socket.get('receiving', function(receiving) {
            if(!receiving) {
                // Lock the socket from receiving future updates
                // by setting the receiving variable to true
                socket.set('receiving', true, function() {
                    // Now emit data
                    socket.emit('update', my_data);
                });
            }
        });
    
        setTimeout(update, 0); // Recursively call update
    }
    setTimeout(update, 0); // Start update
    

    Client.js

    var socket = io.connect();
    
    socket.on('update', function(data) {
        // Store the data for processing
    
        // Tell the server we have received the data
        socket.emit('received');
    });
    

    【讨论】:

    • 您的更新函数中有一个无限循环,因为它会立即将另一个调用排队。这可能有效,但不是最佳的。最好将.emit('update' 放在.on('received' 回调中,因为您基本上希望在服务器接收到接收到的事件时发送数据更新。
    【解决方案2】:

    发送易失性消息,如果无法发送,可以将其丢弃。 Socket.IO 通常会跟踪客户端是否收到消息,但对于易失性消息,此检查不会完成,Socket.IO 进程可以继续,而不是等待:

    socket.volatile.emit('event', data);
    

    这是文档所述:

    这在功能上基本上是一劳永逸,这些消息不是 当客户端无法接收消息时在内部缓冲 例如,如果客户端有网络问题,或者客户端使用 轮询传输并处于请求/响应周期的中间。

    因此,如果您的客户错过了几条消息或 您可能希望将这些事件作为易失性消息发送。

    【讨论】:

    • 我不相信这是正确的。我已经用 volatile 进行了测试,但它似乎没有产生任何影响。数据仍在排队等待浏览器接收。它只会尝试在失败的消息尝试中不重新发送数据,但事实并非如此。我需要消息生命周期之类的东西,但在文档中找不到任何东西,所以我假设它不存在。
    • 唯一可以丢弃消息的地方是客户端和服务器。即使您要发送带有时间戳的消息,客户端仍然必须接收它才能删除它。所以是的,它没有实现。
    • 我想如果这个数字远远落后于我,我将不得不走客户定期发送消息号的路线(到目前为止,我发送的每条消息都会传递一个递增的数字)可以跳过服务器的一些发射。不理想,但我认为这可能是仍然使用 socket.io 的唯一方法。
    猜你喜欢
    • 1970-01-01
    • 2010-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-14
    • 2021-10-17
    • 1970-01-01
    相关资源
    最近更新 更多