Load testing node.js app on Amazon EC2 instance - javascript

I am trying to load test my node.js application with endpoint as API hosted on an m4.large instance using JMeter with 1 master and 3 slaves. The 'server.js' file uses clustering in node.js as follows:
var C_NUM_CPU = 2;
// Listen for dying workers
if (cluster.isMaster) {
for (var i =0; i < C_NUM_CPU; i ++)
{
cluster.fork();
}
cluster.on('exit', function (worker) {
// Replace the dead worker
console.log('Worker %d died :(', worker.id);
cluster.fork();
});
return;
}
When I tested keeping the 'var C_NUM_CPU=2', the max response time crossed 42s, however, on making it 6, the response time dropped to 1.7s! vCPU for m4.large is just 2, then how is the load being handled? Also, in such a case, how to determine the most optimal choice of an instance?

The issue was JMeter slaves. They were dying due to increased response time. Solved on increasing the number of slaves.

Related

node js clustering is repeating the same task on all 8 processes

I've been trying to enable clustering in my node js app. Currently I use this snippet to enable it:
var cluster = require('cluster');
if (cluster.isMaster) {
// Count the machine's CPUs
var cpuCount = require('os').cpus().length;
// Create a worker for each CPU
for (var i = 0; i < cpuCount; i += 1) {
cluster.fork();
}
// Listen for dying workers
cluster.on('exit', function () {
cluster.fork();
});
}
And basically my code performs writes to a Firebase database based on conditions. The problem is that the writes are occurring 8 times each, rather than one worker just taking care of one write task, it seems that all threads are performing all tasks. Is there a way to avoid this? If so, can someone point me in the direction of some resources on this? I can't find anything on google for using Firebase with node js clustering. Here is an example of the way one of my functions work (ref is my firebase reference):
ref.child('user-sent').on('child_added', function(snapshot) {
var message = snapshot.child('message');
payload['user-received/'] = message;
ref.update(payload); // this occurs once for each fork so it updates 8 times
});
If you're spawning 8 threads and each thread attaches a listener on the same location (user-sent), then each thread will fire the child_added event for each child under that location. This is the expected behavior.
If you want to implement a worker queue, where each node under user-sent is only handled by one thread, you'll have to use a work-distribution mechanism that ensures only one thread can claim each node.
The firebase-queue library implements such a work claim mechanism, using Firebase Database transactions. It's been used to scale to a small to medium number of workers (think < 10, not dozens).

What caused process.hrtime() hanging in nodejs?

Here is the code:
var process = require('process')
var c = 0;
while (true) {
var t = process.hrtime();
console.log(++c);
}
Here is my environment:
nodejs v4.2.4, Ubuntu 14.04 LTS on Oracle VM virtualbox v5.0.4 r102546 running in Windows 7
This loop can only run about 60k to 80k times before it hangs. Nothing happens after that.
In my colleague's computer maybe 40k to 60k times. But shouldn't this loop continues forever?
I was first running a benchmark which tests avg execution time of setting up connections, so I can't just get the start time at first then end time after everything finished.
Is this related to the OS that I use?
Thanks if anyone knows the problem.
==========================================================
update 2016.4.13:
One day right after I raised this question, I realized what a stupid question it was. And it was not what I really want to do. So I'm gonna explain it further.
Here is the testing structure:
I have a node server which handles connections.Client will send a 'setup' event on 'connect' event. A Redis subscribe channel will be made at server side and then make some queries from db, then call client's callback of 'setup' event. Client disconnect socket in 'setup' callback, and reconnect on 'disconnect' event.
The client codes use socket.io-client to run in backend and cluster to simulate high concurrency.
Codes are like these:
(some of the functions are not listed here)
[server]
socket.on('setup', function(data, callback) {
queryFromDB();
subscribeToRedis();
callback();
}
[client]
var requests = 1000;
if (cluster.isMaster) {
for (var i = 0; i < 100; ++i) {
cluster.fork();
}
} else {
var count = 0;
var startTime = process.hrtime();
socket = io.connect(...);
socket.on('connect', function() {
socket.emit('setup', {arg1:'...', arg2:'...'}, function() {
var setupEndTime = process.hrtime();
calculateSetupTime(startTime, setupEndTime);
socket.disconnect();
}
}
socket.on('disconnect', function() {
if (count++ < requests) {
var disconnectEndTime = process.hrtime();
calculateSetupTime(startTime, disconnectEndTime);
socket.connect();
} else {
process.exit();
}
}
}
At first the connections could only make 500 or 600 times. Somehow I removed all the hrtime() codes, it made it to 1000 times. But later I raised the number of requests to like 2000 times (without hrtime() codes), it could not finish again.
I was totally confused. Yesterday I thought it was related to hrtime, but of course it wasn't, any infinite loop would hang. I was misled by hrtime.
But what's the problem now?
===================================================================
update 2016.4.19
I solved this problem.
The reason is my client codes use socket.disconnect and socket.connect to simulate a new user. This is wrong.
In this case server may not recognize the old socket disconnected. You have to delete your socket object and new another one.
So you may find the connection count does not equal to disconnection count, and this will prevent our code from disconnecting to redis, thus the whole loop hang because of redis not responsing.
Your code is an infinite loop - at some point this will always exhaust system resources and cause your application to hang.
Other than causing your application to hang, the code you have posted does very little else. Essentially, it could be described like this:
For the rest of eternity, or until my app hangs, (whichever happens first):
Get the current high-resolution real time, and then ignore it without doing anything with it.
Increment a number and log it
Repeat as quickly as possible
If this is really what you wanted to do - you have acheived it, but it will always hang at some point. Otherwise, you may want to explain your desired result further.

How to share a variable among clusters in nodejs?

I am running my express application with clusters.
My master has some kind of caching with a variable that needs to be shared across my workers.
Can i do this in the following way as using a physical datastore is not feasible for me ?
if (cluster.isMaster) {
// Create a worker for each CPU
global.my_cache_variable = 'xyz';
console.log("Number of cpu cores", cCPUs);
for (var i = 0; i < cCPUs; i++) {
cluster.fork();
}
cluster.on('online', function (worker) {
console.log('Worker ' + worker.process.pid + ' is online.');
});
cluster.on('exit', function (worker, code, signal) {
console.log('worker ' + worker.process.pid + ' died.');
cluster.fork();
});
} else {
//create server code here
// and access the global cache variable with the workers
}
Although you can do inter-process communication, I it's not easy and may not be what you want (sharing variable across processes).
Your best option is probably to externalize your cache store, e.g. a Redis store that all clusters can access. It can be on the same machine or another one. It will also help if you need to scale horizontally, as it will be shared by multiple machines.

node.js http server how to get connections count

I'm using node as a http server with the following code:
http.createServer(function(req, res) {}).listen(8181);
I'm looking for a simple way to monitor a node js http server from within the same process. For me it would be enough to have a own function which just outputs the current resource usage and connection count as json. For now I don't need deep measuring or real time performance monitoring.
What are the key performance indicators for a node http server and is it possible to get them from node? If yes how?
What you think of the folling kpi's:
Connection Count
CPU Usage
Ram Usage
Just need to know which variables/functions I need to get the data?
Thx I really appreciate your help
You can get the amount of connection using a built in function of NodeJS. Check getConnections. Bellow an example how to use it:
var server = http.createServer(app);
server.getConnections(function(error, count) {
console.log(count);
});
I hope this is what you were looking for :)
You need something like this:
var count = 0;
http.createServer(function(req, res) {
count++;
res.on('finish', function () {
//setTimeout(function () {
count--;
//}, 60000);
}).on('close', function () {
count--;
});
}).listen(8181);
With setTimeout() you can get the active connections in the last 1 minute.
see http://nodejs.org/api/os.html#os_os_cpus for CPU usage
see http://nodejs.org/api/process.html#process_process_memoryusage for memory usage
scribbles is a logging module I created.
You can just drop in you project and get CPU, Mem & Net out of the box + more some other handy flags & metrics.
Checkout the performance-monitoring part.
To use:
const scribbles = require('scribbles');
scribbles.config({
dataOut:console.log
})
setInterval(function(){
scribbles.status();
}, 5000);
// This will give you a performance snapshot every 5 seconds.
You get:
network: Networking info
port: listening on this Port
connections: number of current established connections
state: the state of the services. e.g. "up", "blocking"
cpu: CPU info
cores: number of available cores
model: description of the processor
speed: MHz frequency speed
percUsed: load on process as percentage
percFree: available on process as percentage
sys: System info
startedAt: when it's system was started
arch: platform architecture. e.g "x64"
platform: the operating system platform
totalMem: the total megabytes of memory being used
freeMem: the total megabytes of memory free
usedMem: the total megabytes of memory being used
process:
percUsedCpu: the percentage of processing power being used by this process
percFreeMem: the percentage of memory being used by this process
usedMem: the total megabytes of memory being used by this process
startedAt: when it's process was started
pTitle: the current process title (i.e. returns the current value of ps)
pid: the ID of the process
ppid: the ID of the current parent process
user: node the name of the user who started node
vNode: version of node

Javascript dedicated web worker to send messages on demand

Is it possible to write a simple dedicated web worker so it process something continuously and sends its state only when the client asks.
What I've done so far, the Client file :
<script>
// spawn a worker
var worker = new Worker('basic-worker.js');
// decide what to do when the worker sends us a message
worker.onmessage = function(e){
document.getElementById('result').textContent = e.data;
};
</script>
<html>
<head></head>
<body>
<p>The Highest prime number discovered so far : <outpout id="result"></output></p>
</body>
</html>
The worker file :
var n = 0;
search: while (true) {
n += 1;
for (var i = 2; i <= Math.sqrt(n); i += 1)
if (n % i == 0)
continue search;
// found a prime !
postMessage(n);
}
As you can see the worker send continuously the primes it founds. I would like to be able to launch the prime calculation and asks the worker to send the latest prime he founds when I click a button on the client for example. That would be something like (I know it cannot work as but to give a general idea of what i want) :
Worker file :
var n = 0;
var lPrime = 0;
// post last prime number when receiving a message
onmessage = function(e) {
postMessage(lPrime);
}
// continously search for prime numbers
search: while (true) {
n += 1;
for (var i = 2; i <= Math.sqrt(n); i += 1)
if (n % i == 0)
continue search;
// found a prime !
//postMessage(n);
lPrime = n;
}
Client file :
<script>
// spawn a worker
var worker = new Worker('basic-worker.js');
// what to do when the worker sends us a message
worker.onmessage = function(e){
document.getElementById('result').textContent = e.data;
};
// post to the worker so the worker sends us the latest prime found
function askPrime(){
worker.postMessage();
};
</script>
<html>
<head></head>
<body>
<p>The Highest prime number discovered so far : <outpout id="result"></output></p>
<input type="button" onclick="askPrime();">
</body>
</html>
This is not a good pattern. Workers are single-threaded, so at any given moment, they can either:
perform a calculation,
send an event, or
respond to an event.
While your worker is calculating, it cannot respond to events. When you send a request for the latest prime, you must wait for the worker to finish what it is doing before it can process your request. Of course, you can use setTimeout (or other methods) to allow the browser to "interrupt" the current work (see Javascript - how to avoid blocking the browser while doing heavy work?), but the entire point of workers is to save you from resorting to such needless complexity.
A better pattern would be a non-worker variable that holds the latest prime, and is updated by the worker whenever it find a new prime. You can query that variable whenever you need the latest prime, and you never need to wait for the worker to process your request.
// spawn a worker
var worker = new Worker('basic-worker.js');
// store the latest prime as it is produced
var latestPrime = 1;
worker.onmessage = function(e){
latestPrime = e.data;
};
// fetch the latest prime from the variable
function askPrime(){
document.getElementById('result').textContent = latestPrime;
};
You could also accomplish this pattern by having two workers:
The main script spawns a worker that holds the latest known prime.
That worker spawns a second worker that actually does the work and reports new primes to the first worker as they are discovered.
That way, the first worker doesn't do any work, and is always free to respond with the latest prime, and the second worker never needs to stop its computations to respond to requests.

Categories

Resources