use docker-compose to run multiple leaked services

This commit is contained in:
Sérgio Ramos 2016-11-22 23:03:33 +00:00
parent 79da2b5e54
commit 01a527063e
15 changed files with 1688 additions and 5 deletions

10
spikes/leak/Dockerfile Normal file
View File

@ -0,0 +1,10 @@
FROM mhart/alpine-node:7
WORKDIR /src
ADD . .
RUN npm install -g yarn
RUN yarn install --production --pure-lockfile --prefer-offline
EXPOSE 8000
CMD ["node", "start.js"]

View File

@ -0,0 +1,21 @@
config:
target: "http://cpu-node:8000"
phases:
- duration: 600
arrivalRate: 10
- duration: 1200
arrivalRate: 25
- duration: 2400
arrivalRate: 50
- duration: 4800
arrivalRate: 25
- duration: 2400
arrivalRate: 10
- duration: 1200
arrivalRate: 5
- duration: 600
arrivalRate: 1
scenarios:
- flow:
- get:
url: "/cpu"

View File

@ -0,0 +1,9 @@
config:
target: "http://fast-node:8000"
phases:
- duration: 13200
arrivalRate: 1
scenarios:
- flow:
- get:
url: "/mem-fast"

View File

@ -0,0 +1,9 @@
config:
target: "http://plain-node:8000"
phases:
- duration: 13200
arrivalRate: 1
scenarios:
- flow:
- get:
url: "/ops/version"

View File

@ -0,0 +1,9 @@
config:
target: "http://slow-node:8000"
phases:
- duration: 13200
arrivalRate: 1
scenarios:
- flow:
- get:
url: "/mem-slow"

View File

@ -0,0 +1,53 @@
version: '2'
services:
fast-node:
build: .
environment:
- TYPE=node
ports:
- "8001:8000"
fast-artillery:
build: .
environment:
- TYPE=artillery
- MODE=fast
depends_on:
- fast-node
slow-node:
build: .
environment:
- TYPE=node
ports:
- "8002:8000"
slow-artillery:
build: .
environment:
- TYPE=artillery
- MODE=slow
depends_on:
- slow-node
plain-node:
build: .
environment:
- TYPE=node
ports:
- "8003:8000"
plain-artillery:
build: .
environment:
- TYPE=artillery
- MODE=plain
depends_on:
- plain-node
telemetry:
image: prom/prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
environment:
- TYPE=telemetry
depends_on:
- fast-node
- slow-node
- plain-node

View File

@ -0,0 +1 @@
{}

View File

@ -5,9 +5,15 @@
"license": "private",
"main": "src/index.js",
"dependencies": {
"artillery": "^1.5.0-17",
"clone": "^2.0.0",
"epimetheus": "^1.0.46",
"good": "^7.0.2",
"good-console": "^6.3.1",
"good-squeeze": "^5.0.1",
"hapi": "^15.2.0",
"pretty-hrtime": "^1.0.3",
"prom-client": "^6.1.2",
"require-dir": "^0.3.1"
}
}

View File

@ -0,0 +1,16 @@
scrape_configs:
- job_name: 'leak-fast'
# Override the global default and scrape targets from this job every 5 seconds.
scrape_interval: 1s
static_configs:
- targets: ['fast-node:8000']
- job_name: 'leak-slow'
# Override the global default and scrape targets from this job every 5 seconds.
scrape_interval: 1s
static_configs:
- targets: ['slow-node:8000']
- job_name: 'no-leak'
# Override the global default and scrape targets from this job every 5 seconds.
scrape_interval: 1s
static_configs:
- targets: ['plain-node:8000']

View File

@ -1,2 +1,16 @@
GET /mem
GET /cpu
cpu-node:
build: .
environment:
- TYPE=node
ports:
- "8003:8000"
cpu-artillery:
build: .
environment:
- TYPE=artillery
- MODE=cpu
depends_on:
- cpu-node

View File

@ -1,3 +1,4 @@
const epimetheus = require('epimetheus');
const requireDir = require('require-dir');
const plugins = require('./plugins');
const routes = requireDir('./routes');
@ -6,7 +7,7 @@ const Hapi = require('hapi');
const server = new Hapi.Server();
server.connection({
host: 'localhost',
host: '0.0.0.0',
port: 8000
});
@ -19,6 +20,8 @@ server.register(plugins, (err) => {
routes[name](server);
});
epimetheus.instrument(server);
server.start((err) => {
server.connections.forEach((conn) => {
console.log(`started at: ${conn.info.uri}`);

View File

@ -1 +1,17 @@
module.exports = [];
module.exports = [{
register: require('good'),
options: {
reporters: {
console: [{
module: 'good-squeeze',
name: 'Squeeze',
args: [{
response: '*',
log: '*'
}]
}, {
module: 'good-console'
}, 'stdout']
}
}
}];

View File

@ -3,7 +3,7 @@ const clone = require('clone');
// leak example from https://auth0.com/blog/four-types-of-leaks-in-your-javascript-code-and-how-to-get-rid-of-them/
let theLeak = null;
const anotherLeak = [];
let anotherLeak = [];
const fibonacci = (num) => {
if (num <= 1) return 1;
@ -14,7 +14,26 @@ const fibonacci = (num) => {
module.exports = (server) => {
server.route({
method: 'GET',
path: '/mem',
path: '/mem-fast',
config: {
handler: (req, reply) => {
const start = process.hrtime();
anotherLeak.push({
longStr: new Array(Math.ceil(anotherLeak.length * 1.5)).map((v, i) => i)
});
console.log('mem-fast %d', Math.ceil(anotherLeak.length * 1.5));
const end = process.hrtime(start);
reply(prettyHrtime(end));
}
}
});
server.route({
method: 'GET',
path: '/mem-slow',
config: {
handler: (req, reply) => {
const start = process.hrtime();
@ -29,10 +48,11 @@ module.exports = (server) => {
};
theLeak = {
longStr: new Array(1000000).join('*')
longStr: new Array(1000).join('*')
};
anotherLeak.push(anotherLeak.length);
console.log('mem-slow %d', anotherLeak.length);
const end = process.hrtime(start);
reply(prettyHrtime(end));

36
spikes/leak/start.js Normal file
View File

@ -0,0 +1,36 @@
const cp = require('child_process');
const TYPE = process.env.TYPE;
const MODE = process.env.MODE;
if (!TYPE) {
console.error(`
Usage: TYPE={type} node start.js
TYPE=node node start.js
`.trim());
process.exit(1);
}
const handler = ({
node: () => {
console.log('node src/index.js');
return cp.exec('node src/index.js', {
cwd: __dirname
})
},
artillery: () => {
console.log(`./node_modules/.bin/artillery run ${__dirname}/artillery-${MODE}.yml`);
return cp.exec(`./node_modules/.bin/artillery run ${__dirname}/artillery-${MODE}.yml`)
}
})[TYPE];
if (!handler) {
console.error(`No handler for ${TYPE}`);
process.exit(1);
}
handler().stdout.pipe(process.stdout);
handler().stderr.pipe(process.stderr);
process.stdin.pipe(handler().stdin);

1460
spikes/leak/yarn.lock Normal file

File diff suppressed because it is too large Load Diff