Hints for creating an node.js cluster for an Angular application
In this lab you will create a node cluster for an Angular application that will display the process ids for the node process that is handling a http REST service.
The following steps may help you in implementing the lab.
First, create a express application
express --ejs cluster
This will create the full framework. Edit bin/www to change the port to the one you want, run "npm install" and you should be able to run the application with
npm start
Now modify the ejs to display the PID of the process handling the HTTP request. Change views/index.ejs to have the line.
Welcome to <%= title %> from <%= pid %>
And change the controller in routes/index.js to populate the pid field
router.get('/', function(req, res, next) {
console.log("ID "+process.pid);
res.render('index', { title: 'Cluster', pid:process.pid });
});
You should now be able to test the application using the route http://YOURIP/
Now add your REST service to get the PID in routes/index.js
router.get('/pid', function(req, res, next) {
console.log("Service ID "+process.pid);
res.json({ title: 'Cluster', pid:process.pid });
});
You should be able to test this service at http://YOURIP/pid
Now lets build an angular application to consume this service. First build the view in views/index.ejs and point it to the MainCtrl front end controller in public/javascripts/angularApp.js
Cluster
{{node.pid}}
We will need to populate the cluster array in our MainCtrl
angular.module('clusterApp', [])
.controller('MainCtrl', [
'$scope', '$http',
function($scope, $http){
$scope.cluster = [{pid:1234}];
}
]);
Test the application to make sure it works.
Now add a button to get the PID from the front end controller. For now, we just want to make sure we can update the $scope.cluster array correctly. Add to the views/index.ejs
And implement the getPIDs() function in public/javascripts/angularApp.js
$scope.getPIDs = function() {
$scope.cluster = [{pid:12},{pid:34}];
}
You should be able to test this to make sure the view displays these two fictional pids.
Now add another button to access your REST service in views/index.ejs
And implement the getMyPIDs function in public/javascripts/angularApp.js
$scope.getMyPIDs = function() {
$http.get('/pid').success(function(data){
console.log("getAll");
console.log(data);
$scope.cluster.push(data);
});
}
You should be able to test this button to make sure it displays the PID of your REST service.
Now modify your front end controller to make 100 http calls and push them all onto the $scope.cluster. You should notice that the all have the same PID.
Now that we have the angular application making a bunch of requests, we need to spawn multiple processes to handle requests to our REST service. Remember that when you run "npm start", npm is really just running the script in "bin/www". So, we should be able to spawn a bunch of workers and have them run "bin/www".
Create a cluster.js file to do this.
var cluster = require('cluster');
var numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
console.log("numCPUs "+numCPUs);
// OK, lets ignore the actual CPUS, so we can see the concurrency
numCPUs = 4;
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', function(worker, code, signal) {
console.log('worker ' + worker.process.pid + ' died');
});
} else {
console.log("Worker "+process.pid);
//change this line to Your Node.js app entry point.
require("./bin/www");
}
now run "sudo node cluster.js" and see what happens with your angular app
You should be able to run
ab -n 100 -v 10 http://YOURIP/pid
to see that your service is returning different PIDs depending on which process handles your REST service. If you have a machine with multiple processors, these would all execute concurrently.