Node.js - pipe()到http响应会导致ubuntu的响应时间变慢

tig*_*eek 2 ubuntu performance amazon-web-services node.js

当通过服务器A将来自服务B的响应传递给客户端时,我注意到了严重的性能问题.我发现这个问题,而调查性能是我们主要进行代理的节点服务器之一.我们使用http-proxy进行代理,起初我认为http-proxy很慢,但我把问题缩小到那个简单的代码片段,它只是使用http.get来向另一个服务器发出请求并返回对客户的回应.

服务器A(代理):

/*jslint node:true nomen:true vars:true*/
var http = require('http');

function outputMs() {
    'use strict';
    var d = new Date();
    var n = d.getUTCMilliseconds();
    return n;
}

http.createServer(function (req, res) {
    'use strict';
    var startTime = outputMs();

    var options = {
        hostname: '10.0.1.114',
        port: 3001,
        path: '/test'
    };

    if (req.url.indexOf('/pipe') > -1) {
        http.get(options, function (proxyRes) {
            // This is slow!!!
            proxyRes.pipe(res);
            proxyRes.on('data', function (chunk) {
                console.log('data:' + (outputMs() - startTime));
                console.log('received:' + chunk);
            });
            proxyRes.on('end', function () {
                console.log('end:' + (outputMs() - startTime));
            });
        });
    } else {
        var data;
        http.get(options, function (proxyRes) {
            // This is fast!!!
            proxyRes.on('data', function (chunk) {
                console.log('data:' + (outputMs() - startTime));
                data += chunk;
            });
            proxyRes.on('end', function () {
                console.log('end:' + (outputMs() - startTime));
                res.end(data);
            });
        });
    }
}).listen(3000);
Run Code Online (Sandbox Code Playgroud)

服务器B:

/*jslint node:true nomen:true vars:true*/
var http = require('http');

http.createServer(function (req, res) {
    'use strict';
    res.end('Hello World');
}).listen(3001);
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,请求事件似乎都需要相同的时间,但客户端收到的响应要慢得多.使用curl测试:

使用管道:

C:\github\mecs> curl -s -w "%{time_total}\n" -o /dev/null http://54.209.35.253:3000/pipe
0.265
C:\github\mecs> curl -s -w "%{time_total}\n" -o /dev/null http://54.209.35.253:3000/pipe
0.265
Run Code Online (Sandbox Code Playgroud)

不使用管道:

C:\github\mecs> curl -s -w "%{time_total}\n" -o /dev/null http://54.209.35.253:3000
0.047
C:\github\mecs> curl -s -w "%{time_total}\n" -o /dev/null http://54.209.35.253:3000
0.063
Run Code Online (Sandbox Code Playgroud)

两台服务器都在AWS上运行微实例,运行Ubuntu Server 12.04.1 LTS和node.js 0.10.21.我在节点0.10.20和0.8.24以及Ubuntu Server 12.04.2和13.10上重现了这个问题.在Windows上未观察到此问题.

有没有人遇到同样的问题?有什么工作吗?

非常感谢你的帮助...

jer*_*emy 5

您可能需要执行类似socket.setNoDelay([noDelay])的操作.不知道如何使用http模块做到这一点.我的猜测是一端正在等待套接字关闭,因为它是一条小消息,当它超时时,你会看到响应.

必须在客户端请求上调用setNoDelay(),并且我第一次尝试它是在我的代理请求上.

server.on('connection', function (socket) { 
    'use strict'; 
    console.log('server.on.connection - setNoDelay'); 
    socket.setNoDelay(true); 
});

  • 我非常喜欢那种日志风格.那是"<OBJECT>.<FUNCTION>.<EVENT> - <ACTION>`? (2认同)