Skip to content

Commit 0732308

Browse files
committed
Merge branch 'improvement/CLDSRV-717-prom-cluster' into tmp/octopus/w/9.1/improvement/CLDSRV-717-prom-cluster
2 parents 941c659 + 73488a3 commit 0732308

File tree

4 files changed

+48
-36
lines changed

4 files changed

+48
-36
lines changed

lib/Config.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,6 +1032,10 @@ class Config extends EventEmitter {
10321032
'bad config: clusters must be a positive integer');
10331033
this.clusters = config.clusters;
10341034
}
1035+
if (process.env.S3BACKEND === 'mem') {
1036+
this.clusters = 1;
1037+
}
1038+
this.isCluster = this.clusters > 1;
10351039

10361040
if (config.usEastBehavior !== undefined) {
10371041
throw new Error('bad config: usEastBehavior key is deprecated. ' +

lib/server.js

Lines changed: 30 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class S3Server {
6767
constructor(config, worker) {
6868
this.config = config;
6969
this.worker = worker;
70-
this.cluster = true;
70+
this.cluster = config.isCluster;
7171
this.servers = [];
7272
http.globalAgent = new HttpAgent({
7373
keepAlive: true,
@@ -303,13 +303,23 @@ class S3Server {
303303
workerId: this.worker ? this.worker.id : undefined,
304304
workerPid: this.worker ? this.worker.process.pid : undefined,
305305
});
306-
// Will close all servers, cause disconnect event on master and kill
306+
// Will close all servers, cause disconnect event on primary and kill
307307
// worker process with 'SIGTERM'.
308308
if (this.worker) {
309309
this.worker.kill();
310310
}
311311
}
312312

313+
startServer(listenOn, port, routeRequest) {
314+
if (listenOn.length > 0) {
315+
listenOn.forEach(item => {
316+
this._startServer(routeRequest.bind(this), item.port, item.ip);
317+
});
318+
} else if (port) {
319+
this._startServer(routeRequest.bind(this), port);
320+
}
321+
}
322+
313323
initiateStartup(log) {
314324
series([
315325
next => metadata.setup(next),
@@ -329,30 +339,14 @@ class S3Server {
329339
}
330340

331341
// Start API server(s)
332-
if (this.config.listenOn.length > 0) {
333-
this.config.listenOn.forEach(item => {
334-
this._startServer(this.routeRequest.bind(this), item.port, item.ip);
335-
});
336-
} else if (this.config.port) {
337-
this._startServer(this.routeRequest.bind(this), this.config.port);
338-
}
342+
this.startServer(this.config.listenOn, this.config.port, this.routeRequest);
339343

340344
// Start internal API server(s)
341-
if (this.config.internalListenOn.length > 0) {
342-
this.config.internalListenOn.forEach(item => {
343-
this._startServer(this.internalRouteRequest.bind(this), item.port, item.ip);
344-
});
345-
} else if (this.config.internalPort) {
346-
this._startServer(this.internalRouteRequest.bind(this), this.config.internalPort);
347-
}
345+
this.startServer(this.config.internalListenOn, this.config.internalPort, this.internalRouteRequest);
348346

349-
// Start metrics server(s)
350-
if (this.config.metricsListenOn.length > 0) {
351-
this.config.metricsListenOn.forEach(item => {
352-
this._startServer(this.routeAdminRequest.bind(this), item.port, item.ip);
353-
});
354-
} else {
355-
this._startServer(this.routeAdminRequest.bind(this), this.config.metricsPort);
347+
// Start metrics server(s) only if not cluster mode worker
348+
if (!this.cluster && !this.worker) {
349+
this.startServer(this.config.metricsListenOn, this.config.metricsPort, this.routeAdminRequest);
356350
}
357351

358352
// Start quota service health checks
@@ -378,18 +372,13 @@ class S3Server {
378372
}
379373

380374
function main() {
381-
// TODO: change config to use workers prop. name for clarity
382-
let workers = _config.clusters || 1;
383-
if (process.env.S3BACKEND === 'mem') {
384-
workers = 1;
385-
}
386-
this.cluster = workers > 1;
387-
if (!this.cluster) {
375+
const workers = _config.clusters;
376+
if (!_config.isCluster) {
388377
process.env.REPORT_TOKEN = _config.reportToken;
389378
const server = new S3Server(_config);
390379
server.initiateStartup(logger.newRequestLogger());
391380
}
392-
if (this.cluster && cluster.isMaster) {
381+
if (_config.isCluster && cluster.isPrimary) {
393382
for (let n = 0; n < workers; n++) {
394383
const worker = cluster.fork();
395384
logger.info('new worker forked', {
@@ -430,12 +419,20 @@ function main() {
430419
workerPid: worker.process.pid,
431420
});
432421
});
422+
423+
const metricServer = new S3Server(_config);
424+
metricServer.startServer(_config.metricsListenOn,
425+
_config.metricsPort, metricServer.routeAdminRequest);
433426
}
434-
if (this.cluster && cluster.isWorker) {
427+
if (_config.isCluster && cluster.isWorker) {
435428
const server = new S3Server(_config, cluster.worker);
436429
server.initiateStartup(logger.newRequestLogger());
437430
}
438-
monitoringClient.collectDefaultMetrics({ timeout: 5000 });
431+
432+
// Avoid default metrics on cluster primary as it only aggregate workers
433+
if (!_config.isCluster || cluster.isWorker) {
434+
monitoringClient.collectDefaultMetrics({ timeout: 5000 });
435+
}
439436
}
440437

441438
module.exports = main;

lib/utilities/monitoringHandler.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,16 +215,27 @@ function writeResponse(res, error, results, cb) {
215215
});
216216
}
217217

218+
const registry = config.isCluster ? new client.AggregatorRegistry() : client.register;
219+
const getMetrics = config.isCluster ?
220+
registry.clusterMetrics.bind(registry) : registry.metrics.bind(registry);
218221

219222
async function routeHandler(req, res, cb) {
220223
if (req.method !== 'GET') {
221224
return cb(errors.BadRequest, []);
222225
}
223-
const promMetrics = await client.register.metrics();
226+
let promMetrics;
227+
try {
228+
// Catch timeout on IPC between worker and primary
229+
// prom-client has a 5s hardcoded timeout
230+
promMetrics = await getMetrics();
231+
} catch (err) {
232+
return cb(err, { message: err.toString() });
233+
}
234+
224235
const contentLen = Buffer.byteLength(promMetrics, 'utf8');
225236
res.writeHead(200, {
226237
'Content-Length': contentLen,
227-
'Content-Type': client.register.contentType,
238+
'Content-Type': registry.contentType,
228239
});
229240
res.end(promMetrics);
230241
return undefined;

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@zenko/cloudserver",
3-
"version": "9.0.21",
3+
"version": "9.0.22",
44
"description": "Zenko CloudServer, an open-source Node.js implementation of a server handling the Amazon S3 protocol",
55
"main": "index.js",
66
"engines": {

0 commit comments

Comments
 (0)