0

This is a follow-up question to another SO thread:

NodeJs how to create a non-blocking computation

Much like the author of that question, I am trying to wrap my head around how to code asynchronously with node.js, and while practicing ended up with very similar code.

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;
    }
  }
}

Much like the author of that code, I stumbled upon the realization that the main event thread won't be open to new requests while waiting for the child.js to respond. This is when I came to stackoverflow and found that I will need to fork a new child process. However, doing this from the main thread will mean that a new node will get spun up for every visitor to "/people". This seems very inefficient, and this article explicitly says so: https://nodejs.org/en/docs/guides/dont-block-the-event-loop/

You should not simply create a Child Process for every client. You can receive client requests more quickly than you can create and manage children, and your server might become a fork bomb.

I want to do what the article recommends: use a worker pool. How do I achieve this by building upon what I already have (as opposed to getting an add-on as the article suggests)?

Bonus Question [MODIFIED]: It seems that node.js is best used for programs that can encounter large wait times or have a large number of I/O. The async-I/O allows the programmer the ability to handle requests while waiting for a response (from an external process or user), but the lack of worker pools means that delays in program response due to processing loops will block the program (unless you spin off a child process). Is my refined understanding more accurate?

UPDATE:

After a return to the basics, I now understand a fundamental error that I made. Node.js is asynchronous from an I/O standpoint, but not a processing standpoint. The code above appeared to be blocking while testing. However, this was not from the inability to listen to new requests, but because the sleep function in child.js locks up the program (there is a single process thread and no worker pools, so such a large loop locked up the program).

This can be demonstrated by this new version of main.js (child.js is not needed in this demo):

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);

This time, sense a proper delay was used (as opposed to a process intensive loop) the program was able to handle multiple requests. However, let us say I do have a process intensive step that truly took approx ~5 sec to complete, and I wanted to write this in node.js. I will need to have this code run on a separate thread. And, as mentioned earlier, we want to avoid creating a new thread for each client request, and instead rely on a worker pool. Is there a way to do this in node.js without having to rely on any C/C++ add-ons or extensions?

Kumar
  • 45
  • 7
  • Never, ever block main thread :) – rtn Mar 14 '18 at 00:48
  • @ralphtheninja How would I serve http requests then? http.createServer is inherently blocking because until the callback is closed, node.js can not handle any more events. – Kumar Mar 14 '18 at 17:39
  • http.createServer is asynchronous so it's definitely not blocking – rtn Mar 14 '18 at 19:43
  • It seems to me you need to read up on node basics. I can recommend `learnyounode`. Install by doing `npm i learnyounode -g` and start with `learnyounode`. – rtn Mar 14 '18 at 19:43
  • 1
    Thank you @ralphtheninja. Turns out a return to basics is just what I needed. I modified my question with a large update. If you could, please read it and let me know if I am back on the right track. – Kumar Mar 16 '18 at 23:29
  • @Kumar see the `cluster` standard module from node.js - that's what you need. Prefork your process and run your tasks in child modules. – Michał Karpacki Mar 23 '18 at 22:03

0 Answers0