Search code examples
javascriptnode.jsexpressweb-worker

Webworkers with a node.js express application


I am new to node.js and am trying to build an express application. So far, I have setup an app and have created some basic routes.

my entry-point for the application is a file where I am setting up a server with the application:

#!/usr/bin/env node

/**
 * Module dependencies.
 */

var app = require('../app');
var debug = require('debug')('main');
var http = require('http');

/**
 * Get port from environment and store in Express.
 */

var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);

/**
 * Create HTTP server.
 */

var server = http.createServer(app);

/**
 * Listen on provided port, on all network interfaces.
 */

server.listen(port);
server.on('error', onError);
server.on('listening', onListening);

/**
 * Normalize a port into a number, string, or false.
 */

function normalizePort(val) {
  var port = parseInt(val, 10);

  if (isNaN(port)) {
    // named pipe
    return val;
  }

  if (port >= 0) {
    // port number
    return port;
  }

  return false;
}

/**
 * Event listener for HTTP server "error" event.
 */

function onError(error) {
  if (error.syscall !== 'listen') {
    throw error;
  }

  var bind = typeof port === 'string'
    ? 'Pipe ' + port
    : 'Port ' + port;

  // handle specific listen errors with friendly messages
  switch (error.code) {
    case 'EACCES':
      console.error(bind + ' requires elevated privileges');
      process.exit(1);
      break;
    case 'EADDRINUSE':
      console.error(bind + ' is already in use');
      process.exit(1);
      break;
    default:
      throw error;
  }
}

/**
 * Event listener for HTTP server "listening" event.
 */

function onListening() {
  var addr = server.address();
  var bind = typeof addr === 'string'
    ? 'pipe ' + addr
    : 'port ' + addr.port;
  debug('Listening on ' + bind);
}

The express app uses mongoose to communicate with the db on appropriate http requests.

At this point, i also need a web-worker which, when the server starts, generate random numbers every 5 seconds and if the generated number is 10, identify it as an event, and store some results in the db.

I am not sure about how to start with this and include it in the structure so far.

I already have the interfaces setup for writing to the db etc. I am just lost with the web-worker implementation and integration part.


Solution

  • In node.js there is no webworkers. But we have something similar called child_process (please look documentation for more details : link)

    How to use child_process? There is many materials in stackoverflow: https://stackoverflow.com/a/13371439/4138339 there is explanation how in main module run other module (look there for details): in your main module:

    var cp = require('child_process');
    var child = cp.fork('./othermodulefile');
    
    child.on('message', function(m) {
      // Receive results from child process
      console.log('received: ' + m);
    });
    
    // Send child process some work
    child.send('Please up-case this string');
    

    Or please look this link for addictional description http://www.tutorialspoint.com/nodejs/nodejs_scaling_application.htm and exaple from that page: File: support.js

    console.log("Child Process " + process.argv[2] + " executed." );
    

    File: master.js

    const fs = require('fs');
    const child_process = require('child_process');
    
    for(var i=0; i<3; i++) {
       var workerProcess = child_process.exec('node support.js '+i,
          function (error, stdout, stderr) {
             if (error) {
                console.log(error.stack);
                console.log('Error code: '+error.code);
                console.log('Signal received: '+error.signal);
             }
             console.log('stdout: ' + stdout);
             console.log('stderr: ' + stderr);
          });
    
          workerProcess.on('exit', function (code) {
          console.log('Child process exited with exit code '+code);
       });
    }
    

    Some drawbacks of using child_process: https://stackoverflow.com/a/17340465/4138339

    Each thread cost memory, and this is generally why most of traditional systems is not much scalable as will require thread per client. For node it will be extremely inefficient from hardware resources point of view.

    and other part:

    Count of workers is recommended to be equal of CPU Cores on hardware.

    Other possibility if you need to run some a time-based job scheduler look at this module https://github.com/ncb000gt/node-cron. It is node.js cron job. installation npm install cron and usage example:

    var CronJob = require('cron').CronJob;
    new CronJob('* * * * * *', function() {
      console.log('You will see this message every second');
    }, null, true, 'America/Los_Angeles');