For performance testing, it is generally necessary to configure many machines generating simultaneous load against an endpoint. With servers these days having many CPU cores, a good tool should utilize all cores.
Flood has simplified the process of aggregating test counters across many machines with many CPUs.
To install the package globally, run:
# npm install flood -g
This will add two commands to your system, flood
and flood-watch
.
Machines that will actually generate the load by spawning worker threads will
be running the flood
command. This service listens for jobs and executes
them. An HTTP-like listener is opened on port 5143, where clients may submit
jobs and wait for completion. Here is an example in curl:
curl -i -X POST \
-H 'Content-Type: text/javascript' \
-H 'X-Signature: XXXXXXXXXXXX' \
-d @mytest.js \
http://localhost:5143/test/mytest.js
The test file mytest.js
simply needs to define exports.counters
and
exports.run
. The exports.counters
is an array of counter names the test can
then increment. The exports.run
is a function that is called which should run
indefinitely, incrementing counters.
exports.counters = ['beeps'];
exports.run = function (snapshot) {
function beep() {
snapshot.counterInc('beeps');
setImmediate(beep);
}
beep();
};
Along with the counterInc()
function, there is a counterAdd()
function that
will produce slightly different behavior but is useful for finding averages of
arbitrary data produced by your tests, such as the time in milliseconds requests
take to run.
exports.counters = ['timers'];
exports.run = function (snapshot) {
function stuff() {
var start = getMilliseconds();
// do stuff...
var end = getMilliseconds();
snapshot.counterAdd('timers', (end-start));
setImmediate(stuff);
}
stuff();
};
Optionally, exports.setUp
may be a function that initializes the test, before
snapshot timers begin. It must call its callback
argument when complete.
Additional arguments passed to callback
will be given to exports.run
:
exports.counters = ['beeps'];
exports.setUp = function (callback) {
require('fs').readFile('beeps.txt', function (err, beepsData) {
callback(beepsData);
}
};
exports.run = function (snapshot, beepsData) {
function beep() {
snapshot.counterInc('beeps');
setImmediate(beep);
}
beep();
};
The service configuration file, flood.conf.json
, is installed into the
etc
directory of the node package (likely /usr/lib/node_modules/flood/
).
This file has several options:
-
clientPort
: The port to listen for connections on. -
urlPrefix
: The expected prefix for every POST, without trailing slash. -
publicKeyFile
: The public key file used to verify digital signatures of incoming test scripts. Must correspond to theprivateKeyFile
option given inflood-watch
configuration.
The intention of the flood-watch
process is to connect to all the flood
processes and aggregate all their counters over a set time. A single argument
with the JSON configuration file is passed to flood-watch
, which looks
something like this:
{
"clients": [
"localhost"
],
"clientPort": 5143,
"dependencies": [],
"privateKeyFile": "/etc/flood/private.pem",
"snapshots": 10,
"interval": 1000,
"workerModule": "beeps.js",
"numWorkers": 0
}
The options are:
-
clients
: A socket connection is initiated to theflood
service on each host in the list to run the test. -
clientPort
: The port to use for client connections. -
dependencies
: An array of packages to be installed locally by npm before running the test. -
privateKeyFile
: A private key file used to generate a digital signature of the the test file. Verification of the signature by theflood
service prevents execution of malicious scripts. -
snapshots
: Number of counter snapshots to gather for the test. Corresponds to theX-Snapshots
header to theflood
service. -
interval
: The length, in milliseconds, of each snapshot window. The entire run-length of the test is given byinterval * snapshots
. Corresponds to theX-Snapshot-Length
header. -
workerModule
: This file is read in and passed to theflood
service as the test file. -
numworkers
: The number of worker threads created by each machine running theflood
service. Positive numbers indicate an exact number of threads, while zero and negatives will subtract from the number of CPU cores. Corresponds to theX-Workers
header.
To streamline the process of generating private and public keys for digital
content signatures, flood installs a script called flood-genkeys
. This
script will generate private.pem
and public.pem
in the directory
specified by the first given argument (defaults to /etc/flood
).
Don't forget the private key only needs to be accessible by the machine
running flood-watch
, and the public key only needs to be accessible by the
machines running flood
.