【问题标题】:How does concurrency work in Node.js + Express application?Node.js + Express 应用程序中的并发性如何工作?
【发布时间】:2014-10-24 11:58:45
【问题描述】:

(找到解决方案)

我想从代码示例开始我的问题:

var express = require('express');
var customModule = require('./custom-module');

var app = express();

// Page A
app.get('/a', function(req, res) {
    res.type('text/plain');
    customModule.doHeavyOperation(25, function(result) {
        res.send('Page A, number = ' + result);
    });
});

// Page B
app.get('/b', function(req, res) {
    res.type('text/plain');
    res.send('Page B');
});

app.listen(8082);

对于 Page A 调用 doHeavyOperation() 执行一些操作,当它们完成时,它会运行我的回调,向用户发送一些信息。

cutsom-module.js:

exports.doHeavyOperation = function(number, callback) {
    for (var i=0; i<2000000000; i++) {
        number++;
    }
    callback(number);
};

对于 doHeavyOperation() 执行它的逻辑并调用我的回调需要大约 5 秒。当我在浏览器中打开两个页面时:localhost:8082/a 和 localhost:8082/b,第二个页面需要等到第一个页面加载。这意味着请求不是同时处理的。

除了 doHeavyOperation 之外,还有任何其他功能会在我的客户尝试使用我的 Web 应用程序时冻结他们。例如,我可能想要处理我的用户上传的一些大图像,对它们应用一些过滤器等。这可能需要 1-3 秒。所以如果有 100 个人同时使用我的网站,就会造成很大的问题。

例如,Apache + PHP 很好地处理了这种情况。虽然脚本 a.php 执行一些操作,但脚本 b.php 可以毫无问题地加载。

如何在 Node.js + Express 中实现这种行为?

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

根据 kamituel 的评论,我的决定是生成执行“重”计算的新进程并将结果返回给父进程。现在应用程序可以按我的意愿运行。

我修改了我的代码:

var express = require('express');

var app = express();

// Page A
app.get('/a', function(req, res) {
    // Creating child process
    var child = require('child_process').fork('custom-module.js');
    // Sending value
    child.send(25);
    // Receiving result
    child.on('message', function(result) {
        res.type('text/plain');
        res.send('Page A, number = ' + result);
    });
});

// Page B
app.get('/b', function(req, res) {
    res.type('text/plain');
    res.send('Page B');
});

app.listen(8082);

自定义模块.js:

function doHeavyOperation(number, callback) {
    for (var i=0; i<2000000000; i++) {
        number++;
    }
    callback(number);
};

process.on('message', function(number) {
    doHeavyOperation(number, function(result) {
        process.send(result);
    });
});

关于 child_process here 的更多信息。

【问题讨论】:

    标签: javascript node.js asynchronous express


    【解决方案1】:

    Javascript(因此 Node.js 也是如此)使用一个主线程来处理(几乎)您编写的所有 JS 代码。这意味着如果您有一些长时间运行的任务(如示例中的巨大循环),该任务将阻止其他代码的执行(即回调)。

    你能做些什么呢?

    • 将循环分成更小的部分,并偶尔让出控制(即使用 setTimeout/nextTick 或类似方法)。 IE。您可以从 0 迭代到 1000,然后在下一个滴答时执行下 1000 次循环迭代,依此类推。
    • 生成一个新进程并在那里处理繁重的任务。由于新进程将在 Node.js 本身之外,它不会阻止它。

    【讨论】:

      猜你喜欢
      • 2011-06-09
      • 1970-01-01
      • 2016-10-20
      • 2016-12-23
      • 2014-09-10
      • 2012-09-20
      • 1970-01-01
      • 1970-01-01
      • 2017-01-21
      相关资源
      最近更新 更多