mirror of
https://github.com/jambonz/jambonz-feature-server.git
synced 2025-12-20 08:40:38 +00:00
add support for running in AWS autoscale cluster with graceful scale-in and standby
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
const assert = require('assert');
|
||||
const noopLogger = {info: () => {}, error: () => {}};
|
||||
const {LifeCycleEvents} = require('./constants');
|
||||
const Emitter = require('events');
|
||||
const debug = require('debug')('jambonz:feature-server');
|
||||
|
||||
module.exports = (logger) => {
|
||||
@@ -13,6 +15,58 @@ module.exports = (logger) => {
|
||||
assert.ok(sbcs.length, 'JAMBONES_SBCS env var is empty or misconfigured');
|
||||
logger.info({sbcs}, 'SBC inventory');
|
||||
|
||||
// listen for SNS lifecycle changes
|
||||
let lifecycleEmitter = new Emitter();
|
||||
let dryUpCalls = false;
|
||||
if (process.env.AWS_SNS_TOPIC_ARM &&
|
||||
process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY && process.env.AWS_REGION) {
|
||||
|
||||
(async function() {
|
||||
try {
|
||||
lifecycleEmitter = await require('./aws-sns-lifecycle')(logger);
|
||||
|
||||
lifecycleEmitter
|
||||
.on(LifeCycleEvents.ScaleIn, () => {
|
||||
logger.info('AWS scale-in notification: begin drying up calls');
|
||||
dryUpCalls = true;
|
||||
lifecycleEmitter.operationalState = LifeCycleEvents.ScaleIn;
|
||||
|
||||
const {srf} = require('../..');
|
||||
pingProxies(srf);
|
||||
|
||||
// if we have zero calls, we can complete the scale-in right
|
||||
setTimeout(() => {
|
||||
const calls = srf.locals.sessionTracker.count;
|
||||
if (calls === 0) {
|
||||
logger.info('scale-in can complete immediately as we have no calls in progress');
|
||||
lifecycleEmitter.completeScaleIn();
|
||||
}
|
||||
else {
|
||||
logger.info(`${calls} calls in progress; scale-in will complete when they are done`);
|
||||
}
|
||||
}, 5000);
|
||||
})
|
||||
.on(LifeCycleEvents.StandbyEnter, () => {
|
||||
dryUpCalls = true;
|
||||
const {srf} = require('../..');
|
||||
pingProxies(srf);
|
||||
|
||||
logger.info('AWS enter pending state notification: begin drying up calls');
|
||||
})
|
||||
.on(LifeCycleEvents.StandbyExit, () => {
|
||||
dryUpCalls = false;
|
||||
const {srf} = require('../..');
|
||||
pingProxies(srf);
|
||||
|
||||
logger.info('AWS enter pending state notification: re-enable calls');
|
||||
});
|
||||
} catch (err) {
|
||||
logger.error({err}, 'Failure creating SNS notifier, lifecycle events will be disabled');
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
// send OPTIONS pings to SBCs
|
||||
async function pingProxies(srf) {
|
||||
for (const sbc of sbcs) {
|
||||
try {
|
||||
@@ -21,7 +75,7 @@ module.exports = (logger) => {
|
||||
uri: `sip:${sbc}`,
|
||||
method: 'OPTIONS',
|
||||
headers: {
|
||||
'X-FS-Status': ms ? 'open' : 'closed'
|
||||
'X-FS-Status': ms && !dryUpCalls ? 'open' : 'closed'
|
||||
}
|
||||
});
|
||||
req.on('response', (res) => {
|
||||
@@ -40,6 +94,7 @@ module.exports = (logger) => {
|
||||
}, 60000);
|
||||
|
||||
return {
|
||||
lifecycleEmitter,
|
||||
getSBC: () => sbcs[idxSbc++ % sbcs.length]
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user