NodeJS和TCP性能

时间:2014-05-07 09:16:28

标签: node.js tcp

我正在使用net module测试两个NodeJS实例之间的通信。

由于TCP不依赖于消息(socket.write()),我将每条消息包装在msg "{ json: 'encoded' }";之类的字符串中,以便单独处理它们(否则,我会收到包含随机数量的连接消息。)

我在具有桥接网络和基于Core i3的主机的CentOS 6.5 VirtualBox VM上运行两个NodeJS实例(服务器和客户端)。测试取决于客户端向服务器发出请求并等待响应:

  1. 客户端连接到服务器。
  2. 客户端输出当前时间戳(Date.now())。
  3. 客户端发出 n 个请求。
  4. 服务器回复 n 请求。
  5. 客户端会在每次回复时递增一个计数器。
  6. 完成后,客户端输出当前时间戳。
  7. 代码非常简单:

    服务器

    var net = require('net');
    
    var server = net.createServer(function(socket) {
    
        socket.setNoDelay(true);
    
        socket.on('data', function(packet) {
    
            // Split packet in messages.
            var messages = packet.toString('utf-8').match(/msg "[^"]+";/gm);
    
            for (var i in messages) {
    
                // Get message content (msg "{ content: 'json' }";). Actually useless for the test.
                //var message = messages[i].match(/"(.*)"/)[1];
    
                // Emit response:
                socket.write('msg "PONG";');
    
            }
    
        });
    
    });
    
    server.listen(9999);
    

    客户端

    var net = require('net');
    
    var WSClient = new net.Socket();
    
    WSClient.setNoDelay(true);
    
    WSClient.connect(9999, 'localhost', function() {
    
        var req = 0;
        var res = 0;
    
        console.log('Start:', Date.now());
    
        WSClient.on('data', function(packet) {
    
            var messages = packet.toString("utf-8").match(/msg "[^"]+";/gm);
    
            for (var i in messages) {
    
                // Get message content (msg "{ content: 'json' }";). Actually useless for the test.
                //var message = messages[i].match(/"(.*)"/)[1];
    
                res++;
                if (res === 1000) console.log('End:', Date.now());
    
            }
    
        });
    
        // Emit requests:
        for (req = 0; req <= 1000; req++) WSClient.write('msg "PING";');
    
    });
    

    我的结果是:

    • 有1个请求:9 - 24 ms
    • 有1000个请求:478 - 512 ms
    • 有10000个请求:5021 - 5246 ms

    我对localhost的ping(ICMP)介于0.6到0.1秒之间。我没有激烈的网络流量或CPU使用率(运行SSH,FTP,Apache,Memcached和Redis)。

    对于NodeJS和TCP来说,

    这是正常的,还是我的CentOS VM或我的低性能主机?我应该转移到另一个平台,如Java还是本机C / C ++服务器?

    我认为我的项目无法接受localhost上每个请求15毫秒的延迟(平均)。

2 个答案:

答案 0 :(得分:4)

在某些文本中包装消息并搜索正则表达式匹配是不够的。

net.Socketdata接口将原始TCP流作为基础数据源。只要底层TCP流具有可用数据,就会触发data事件。

问题是,您无法控制TCP堆栈。触发data事件的时间与代码的逻辑无关。因此,您无法保证驱动您的侦听器的data事件只有一个,少于一个,多于一个,或者任何数量和一些剩余的消息被发送。实际上,您几乎可以保证底层TCP堆栈将数据分解为块。并且只有当一个块可用时,监听器才会触发。您当前的代码在override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("Cell") as! UITableViewCell cell.title.text = theWorld[indexPath.row].name return cell } 个事件之间没有共享状态。

你只提到延迟,但我希望如果你检查,你也会发现收到的消息数量(两端)不是你所期望的。这是因为任何部分消息都将完全丢失。如果TCP流在块1的末尾发送了一半的消息,而剩余的在块2中,则拆分的消息将被完全丢弃。

简单而强大的方法是使用像ØMQ这样的消息传递协议。您需要在两个端点上使用它。它负责将TCP流构成原子消息。

如果由于某种原因您将连接或接收来自外部来源的流量,他们可能会使用类似长度标题的内容。然后你要做的是创建一个缓冲传入流量的转换流,只有当标头中标识的数量到达时才会发出数据。

答案 1 :(得分:1)

你做过任何网络转储吗?您可能会因为启用“无延迟”而引入的开销而创建网络拥塞。套接字属性。此属性将尽快将数据发送到TCP堆栈,如果您有非常小的信息块,将导致许多TCP数据包具有较小的有效负载,从而降低传输效率并最终由于拥塞而使TCP暂停传输。如果你想使用“没有延迟”#39;对于您的套接字,请尝试增加接收套接字缓冲区,以便更快地从tcp堆栈中提取数据。如果有帮助,请告诉我们。