Node.js:一次接收过多的UDP消息,丢失它们

时间:2015-01-09 19:03:43

标签: javascript node.js sockets express udp

我的节点服务器在一秒钟内收到大约 400条UDP消息,所有都可以,我可以处理所有400条消息。

然而,当我开始在一秒钟内收到 700条UDP消息时,我丢失了2-20个消息,并且它们永远不会被解析:(

我在这里考虑了一些选项

  1. 创建所有套接字消息的队列,然后逐个消耗, 虽然我不确定如何实现这一点
    • 无法弄清楚如何实施
  2. 节点 / Express / dgram套接字中找到设置,我可以增加内存大小/缓冲区大小,类似于
    • 我找不到这样的设置:(
  3. 使用其他UDP接收器,停止在套接字UDP接收器中使用节点构建
    • 未找到其他接收器
  4. 这是我的UDP发件人的样子:

    var dgram = require("dgram");
    var udpserver = dgram.createSocket("udp4");
    var seatStateStore = require("./SeatStateStore");
    
    udpserver.on("message",
            function (msg, rinfo)
            {
            seatStateStore.parseMessage(msg.toString());
        });
    

    有人有什么想法吗?我无法找出3个选项中的任何一个:/有人可以帮助我吗?

    节点v0.10.29

    Express v3.14.0

    ===============================

    更新/解决方案

    这是我最终使用的代码(略微修改了@RoyHB的解决方案):

    var dgram = require("dgram");
    var udpserver = dgram.createSocket("udp4");
    var seatStateStore = require("./SeatStateStore");
    var Dequeue = require('dequeue');
    var FIFO = new Dequeue();
    
    fetcher();
    
    udpserver.on("message",
            function (msg, rinfo)
            {
               FIFO.push(msg.toString());
            });
    
    udpserver.bind(43278);
    
    function fetcher () {
        while (FIFO.length > 0) 
        {
            var msg = FIFO.shift();
            seatStateStore.parseMessage(msg);
        }
        setImmediate(fetcher); //make this function continuously run
    }
    

2 个答案:

答案 0 :(得分:1)

有一个名为node-dequeue的NPM模块。我对你的类似情况使用了很多。

基本上,

  1. 您的程序将收到的消息推送到队列的末尾。
  2. 间隔计时器定期激活另一个方法或函数(队列提取器),它检查队列中是否有消息,如果是,则提取一个或多个并处理它。
  3. 或者(可能更好)没有使用计时器来安排队列提取。而是使用节点process.nextTick方法。
  4. 或者,也许最好,您可以使用node process.nextTick来连续检查队列中的消息。

    理想情况下,seatStateStore.parseMessage将创建一个新对象,以异步方式处理一条消息,以便在后台继续实际消息处理时,parseMessage会立即返回。 (参见示例代码的底部)

    我还没有测试下面的代码,它的意思是说明,而不是运行

    var FIFO = require ('dequeue');
    var seatStateStore = require("./SeatStateStore");
    var dgram = require("dgram");
    
    setInterval(fetcher, 1);
    
    var udpserver = dgram.createSocket("udp4");
    
    udpserver.on("message",
        function (msg, rinfo) {
            FIFO.push(msg);
        }
    );
    
    function fetcher () {
        while (FIFO.length > 0) {
            var msg = FIFO.shift();
            seatStateStore.parseMessage(msg);
        }
    }
    

    **或(可能更好)**

    var FIFO = require ('dequeue');
    var seatStateStore = require("./SeatStateStore");
    var dgram = require("dgram");
    
    fetcher();
    
    var udpserver = dgram.createSocket("udp4");
    
    udpserver.on("message",
        function (msg, rinfo) {
            FIFO.push(msg);
        }
    );
    
    function fetcher () {
        while (FIFO.length > 0) {
            var msg = FIFO.shift();
            seatStateStore.parseMessage(msg);
            process.nextTick(fetcher);
        }
    }
    

    seatStateProcessor.parseMessage概述:

    seatStateProcessor.parseMessage = function (msg) {
        proc = new asyncProcHandler(msg, function (err) {
            if (err) {
                //handle the error
            }
        });
    }
    

答案 1 :(得分:1)

我知道已经有了答案,但是从今天起,我从官方文档official doc中找到了增加dgram缓冲区的方法。

socket.setRecvBufferSize(size)
Added in: v8.7.0
size <integer>
Sets the SO_RCVBUF socket option. Sets the maximum socket receive buffer in bytes.

socket.setSendBufferSize(size)
Added in: v8.7.0
size <integer>
Sets the SO_SNDBUF socket option. Sets the maximum socket send buffer in bytes.