node.js性能优化和单线程架构

Chr*_*ris 6 node.js

我正在运行带有express的Node.js应用程序,并希望开始提高其性能.定义了几条路线.我们有一个基本的例子:

app.get('/users', function (req, res) {
    User.find({}).exec(function(err, users) {
        res.json(users);
    }
});
Run Code Online (Sandbox Code Playgroud)

假设我们有3个客户端A,B和C,他们试图使用这条路线.他们的请求以A,B,C的顺序到达服务器,两者之间有1毫秒的差异.

1.如果我正确理解了node.js架构,那么每个请求都会被立即处理,因为它Users.find()是异步的并且有非阻塞代码?

让我们用同步调用展开这个例子:

 app.get('/users', function (req, res) {
        var parameters = getUserParameters();

        User.find({parameters}).exec(function(err, users) {
            res.json(users);
        }
    });
Run Code Online (Sandbox Code Playgroud)

相同的请求,相同的订单.getUserParameters()完成需要50毫秒.

2. A将进入路由回调函数并阻塞node.js线程50毫秒.B和C将无法进入该功能并且必须等待.当A完成时getUsersParameters(),它将继续异步User.find()功能,B现在将进入路由回调函数.C仍然需要等待50多毫秒.当B进入异步功能时,可以最终处理C的请求.合在一起:C必须等待50毫秒才能完成A,50毫秒需要B完成,50毫秒才能完成(为简单起见,我们忽略了异步功能的等待时间)?

现在假设我们还有一个路由,只有管理员可以访问,并且每分钟都会通过crontab调用.

app.get('/users', function (req, res) {  
    User.find({}).exec(function(err, users) {
        res.json(users);
    }
});

app.get('/admin-route', function (req, res) {
    blockingFunction(); // this function takes 2 seconds to complete
});
Run Code Online (Sandbox Code Playgroud)

3.当请求X命中admin-route并被blockingFunction()调用时,A,B和C将/users在X的请求之后立即呼叫,必须等待2秒,直到它们甚至进入路由回调函数?

4.我们是否应该将每个自定义函数(即使只需要4毫秒)作为具有回调的异步函数?

rob*_*lep 6

答案是"是",在#3上:阻塞意味着阻止事件循环,这意味着任何I/O(如处理HTTP请求)都将被阻止.在这种情况下,应用程序似乎没有响应这2秒.

但是,你必须为同步代码做很多事情,需要2秒钟(非常繁重的计算,或使用*Sync()模块提供的很多方法fs).如果您真的无法使该代码异步,则应考虑在单独的进程中运行它.

关于#4:如果你可以轻松地使它异步,你可能应该.但是,只是让你的同步函数接受回调并不会奇迹般地使它异步.这取决于函数的作用,以及如何使其异步.