主要事件线程中的非阻塞,计算密集型子进程

时间:2018-03-14 00:45:08

标签: node.js asynchronous nonblocking

这是另一个SO线程的后续问题:

NodeJs how to create a non-blocking computation

就像那个问题的作者一样,我试图围绕如何与node.js异步编码,并且在练习时最终得到了非常相似的代码。

main.js

var http = require("http");
var url = require('url');

http.createServer(function (request, response) {

    var path = url.parse(request.url).pathname;
    response.writeHead(200, {'Content-Type': 'text/plain'});
    response.write('Hello ');

    switch(path) {
        case '/people':
            var people = require('./child');
            people.speak(response);
        break;
        default:
            response.write('World');
        break;
    }

   response.end();

}).listen(8081);

// Console will print the message
console.log('Server running at http://127.0.0.1:8081/');

child.js

module.exports = {

  speak: function (response) {

    sleep(5000);    

    response.write('People');
  }
};

function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e14; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}

就像那段代码的作者一样,我偶然发现主要事件线程在等待child.js响应时不会对新请求开放。这是当我来到stackoverflow并发现我需要fork一个新的子进程。但是,从主线程执行此操作将意味着新节点将为每个访问者#34; / people&#34;进行调整。这看起来非常低效,本文明确指出: https://nodejs.org/en/docs/guides/dont-block-the-event-loop/

  

您不应该只是为每个客户创建一个子进程。您可以比创建和管理子项更快地接收客户端请求,并且您的服务器可能会成为一个分叉炸弹。

我想做文章推荐的内容:使用工作池。我如何通过建立我已有的东西来实现这一目标(而不是像文章所说的那样获得附加组件)?

奖金问题[修改]: 似乎node.js最适用于可能遇到大等待时间或具有大量I / O的程序。 async-I / O允许程序员在等待响应(来自外部进程或用户)时处理请求,但缺少工作池意味着由于处理循环导致的程序响应延迟将阻止程序(除非你剥离了一个子进程)。我的理解是否更准确?

更新:

回归基础后,我现在明白了我犯的一个根本错误。 Node.js从I / O角度来看是异步的,但不是处理立场。上面的代码在测试时似乎是阻塞的。但是,这不是因为无法监听新请求,而是因为child.js中的sleep函数锁定了程序(有一个进程线程而没有工作池,所以这么大的循环锁定了程序)。

这可以通过这个新版本的main.js来证明(本演示中不需要child.js):

var http = require("http");
var url = require('url');

http.createServer(function (request, response) {

    var path = url.parse(request.url).pathname;
    response.writeHead(200, {'Content-Type': 'text/plain'});
    response.write('Hello ');

    switch(path) {
        case '/people':
            setTimeout(function () {
            response.end('People');
            },5000);
        break;
        default:
            response.end('World');
        break;
    }

}).listen(8081);

这次,感觉使用了适当的延迟(与流程密集型循环相反),程序能够处理多个请求。但是,让我们说我确实有一个过程密集的步骤,真正需要大约5秒才能完成,我想在node.js中写这个。我需要在单独的线程上运行此代码。并且,如前所述,我们希望避免为每个客户端请求创建新线程,而是依赖于工作池。有没有办法在node.js中执行此操作,而不必依赖任何C / C ++加载项或扩展?

0 个答案:

没有答案