如何设置一个非常快的Node.js UDP服务器

13

我对Node.js很陌生,我有一个应用程序的请求,该请求将接收UDP数据包负载并处理它。

我的意思是超过每秒400条消息,这将达到大约每分钟200,000条消息。

我编写了一段代码来设置UDP服务器(实际上从这里http://nodejs.org/api/all.html#all_udp_datagram_sockets获取),但是它会丢失大约5%的数据包。

我真正需要开发的是一个服务器,该服务器将获取数据包并将其发送给另一个工作线程以处理消息。但是在Node.js中进行线程处理似乎很麻烦。

这是我的核心代码:

var dgram = require("dgram");
var fs = require("fs");
var stream = fs.createWriteStream("received.json",{ flags: 'w',
  encoding: "utf8",
  mode: 0666 });

var server = dgram.createSocket("udp4");
server.on("message", function (msg, rinfo) {
  console.log("server got: " + msg + " from " +
    rinfo.address + ":" + rinfo.port);
    stream.write(msg);
});

server.on("listening", function () {
  var address = server.address();
  console.log("server listening " +
      address.address + ":" + address.port);
});

server.bind(41234);
// server listening 0.0.0.0:41234

2
请记住,与TCP套接字不同,数据报文并不保证接收。相反,数据报文注重速度,而不承认单个消息。 - skeggse
3个回答

3
您缺少一些概念,NodeJS并不是指多线程的意思,请求应该在一个循环中处理。没有其他线程存在,所以不会发生上下文切换。在多核环境下,您可以通过node的集群模块创建一个集群,我在这里有一篇博客文章(链接)
您将父进程设置为分叉子进程,只有子进程才能绑定端口。您的父进程将处理子进程之间的负载平衡。 注意:在我的博客文章中,我写了i < os.cpus().length / 2;但实际应该写成i < os.cpus().length;

抱歉,我想我没有解释清楚,但事实是:作为一个UDP客户端,我可以在一秒钟内发送超过10k个UDP包,但在本地到本地的环境下,UDP服务器丢失了约5%。无论如何,我的服务器已经非常敏感,它每秒响应超过1000个(1kb)消息,这对我来说已经足够了。 - Panthro
你写道:“我真正需要开发的是一个服务器,它可以接收数据包并将其发送到另一个工作进程来处理消息。”但我猜你想要减少5%的错误率?你能重新表达一下你的问题吗? - Mustafa

0
这里有一个微妙的提示。为什么你要用UDP进行流传输?你需要使用TCP进行流传输。UDP协议发送数据报,离散的消息。它不会在幕后将它们分开。你发送的就是你用UDP收到的。IP分段是我没有讨论的不同问题。你不必担心在另一端重新组合流。这是使用UDP而不是TCP的主要优点之一。此外,如果你正在本地主机之间进行通信,你不必担心由于网络故障而丢失数据包。但是,如果你溢出了网络堆栈缓冲区,你可能会丢失数据包,所以如果你正在进行高速数据传输,请给自己留下大的缓冲区。因此,忘记流,只需使用UDP发送:
var udp_server = dgram.createSocket({ type: 'udp4', reuseAddr: true, recvBufferSize: 20000000 // <<== 很大的缓冲区 });
udp_server.send("Badabing, badaboom", remote_port, remote_address);

Go语言是由Google开发的,旨在应对现代技术公司中出现的语言多样性(我同意,这很疯狂)。但是,由于其文化和设计禁止使用异常处理,而异常处理是现代语言中最重要的功能之一,可以消除旧式错误处理所添加的大量混乱,因此我无法使用它。除此之外,它还不错,但这对我来说是一个致命问题。


0

我编写了一个类似结构的 SOAP/XML 转发服务,发现信息会分为两个数据包。我需要更新我的代码以检测消息的两个部分并将它们重新组合在一起。这个负载大小问题可能更多是 HTTP 问题而不是 UDP 问题,但我的建议是您增加日志记录以写出您接收到的所有内容,并认真检查它们。看起来你现在正在记录你得到的东西,但你可能必须深入挖掘你丢失的那5%。

你怎么知道是5%? 如果再次发送这个流量,它是否总是5%? 同样的消息总是丢失吗?

我使用 Ruby 和 Event Machine 构建了一个 VoIP/Sip 呼叫数据的 UDP 服务器,目前情况良好。(不过我很好奇你的测试方法,我一直在用 netcat 或者一个小型 Ruby 客户端,我从未做过 10k 条消息)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接