Изменен алгоритм останова сервера - добавлен таймаут останова, экземпляр ParusAppServer больше не управляет процессом (убрал process.exit), переписан перехват сигналов останова
This commit is contained in:
parent
f01ee89790
commit
dd9f5cddbb
@ -7,6 +7,12 @@
|
||||
// Тело модуля
|
||||
//------------
|
||||
|
||||
//Общие параметры
|
||||
let common = {
|
||||
//Таймаут останова сервера (мс)
|
||||
nTerminateTimeout: 60000
|
||||
};
|
||||
|
||||
//Параметры подключения к БД
|
||||
let dbConnect = {
|
||||
//Пользователь БД
|
||||
@ -60,6 +66,7 @@ let mail = {
|
||||
//-----------------
|
||||
|
||||
module.exports = {
|
||||
common,
|
||||
dbConnect,
|
||||
outGoing,
|
||||
inComing,
|
||||
|
16
core/app.js
16
core/app.js
@ -40,6 +40,8 @@ class ParusAppServer {
|
||||
this.notifier = null;
|
||||
//Флаг остановки сервера
|
||||
this.bStopping = false;
|
||||
//Таймаут останова сервера
|
||||
this.terminateTimeout = null;
|
||||
//Список обслуживаемых сервисов
|
||||
this.services = [];
|
||||
//Привяжем методы к указателю на себя для использования в обработчиках событий
|
||||
@ -175,16 +177,14 @@ class ParusAppServer {
|
||||
await this.logger.warn("Отключение сервера приложений от БД...");
|
||||
try {
|
||||
await this.dbConn.disconnect();
|
||||
process.exit(0);
|
||||
} catch (e) {
|
||||
await this.logger.error(`Ошибка отключения от БД: ${e.sCode}: ${e.sMessage}`);
|
||||
process.exit(1);
|
||||
}
|
||||
} else {
|
||||
process.exit(0);
|
||||
//Мы закончили останов - сброс таймера аварийного останова, процесс завершится самостоятельно
|
||||
if (this.terminateTimeout) {
|
||||
clearTimeout(this.terminateTimeout);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
process.exit(0);
|
||||
}
|
||||
}
|
||||
//Инициализация сервера
|
||||
@ -252,10 +252,12 @@ class ParusAppServer {
|
||||
await this.dbConn.connect();
|
||||
}
|
||||
//Останов сервера
|
||||
async stop() {
|
||||
async stop(terminateTimeout) {
|
||||
if (!this.bStopping) {
|
||||
//Установим флаг - остановка в процессе
|
||||
this.bStopping = true;
|
||||
//Запомним таймер аварийного останова
|
||||
this.terminateTimeout = terminateTimeout;
|
||||
//Сообщаем, что начался останов сервера
|
||||
await this.logger.warn("Останов сервера приложений...");
|
||||
//Останов обслуживания очереди исходящих
|
||||
|
63
index.js
63
index.js
@ -10,7 +10,8 @@
|
||||
require("module-alias/register"); //Поддержка псевонимов при подключении модулей
|
||||
const cfg = require("./config"); //Настройки сервера приложений
|
||||
const app = require("./core/app"); //Сервер приложений
|
||||
const { makeErrorText } = require("./core/utils"); //Вспомогательные функции
|
||||
const { makeErrorText, getNowString } = require("./core/utils"); //Вспомогательные функции
|
||||
const { SCONSOLE_LOG_COLOR_PATTERN_ERR, SCONSOLE_LOG_COLOR_PATTERN_WRN } = require("./core/constants"); //Общие константы
|
||||
|
||||
//--------------------------
|
||||
// Глобальные идентификаторы
|
||||
@ -28,43 +29,41 @@ process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
||||
//Обработка события "выход" жизненного цикла процесса
|
||||
process.on("exit", code => {
|
||||
//Сообщим о завершении процесса
|
||||
appSrv.logger.warn("Сервер приложений остановлен (код: " + code + ") ");
|
||||
console.log(
|
||||
SCONSOLE_LOG_COLOR_PATTERN_WRN,
|
||||
`${getNowString()} ПРЕДУПРЕЖДЕНИЕ: `,
|
||||
`Сервер приложений остановлен (код: ${code})`
|
||||
);
|
||||
});
|
||||
|
||||
//Перехват CTRL + C (останов процесса)
|
||||
process.on("SIGINT", async () => {
|
||||
appSrv.logger.warn("Получен сигнал на останов сервера приложений: SIGINT");
|
||||
//Инициируем выход из процесса
|
||||
await appSrv.stop();
|
||||
});
|
||||
|
||||
//Перехват CTRL + \ (останов процесса)
|
||||
process.on("SIGQUIT", () => {
|
||||
appSrv.logger.warn("Получен сигнал на останов сервера приложений: SIGQUIT");
|
||||
//Инициируем выход из процесса
|
||||
appSrv.stop();
|
||||
});
|
||||
|
||||
//Перехват мягкого останова процесса
|
||||
process.on("SIGTERM", () => {
|
||||
appSrv.logger.warn("Получен сигнал на останов сервера приложений: SIGTERM");
|
||||
//Инициируем выход из процесса
|
||||
appSrv.stop();
|
||||
});
|
||||
|
||||
//Грубый останов процесса (здесь сделать ничего нельзя, но мы пытаемся)
|
||||
process.on("SIGKILL", () => {
|
||||
appSrv.logger.warn("Получен сигнал на останов сервера приложений: SIGKILL");
|
||||
//Инициируем выход из процесса
|
||||
appSrv.stop();
|
||||
["SIGINT", "SIGQUIT", "SIGTERM"].forEach(sSig => {
|
||||
process.on(sSig, async () => {
|
||||
await appSrv.logger.warn(`Получен сигнал на останов сервера приложений: ${sSig}`);
|
||||
const terminateTimeout = setTimeout(() => {
|
||||
console.log(
|
||||
SCONSOLE_LOG_COLOR_PATTERN_ERR,
|
||||
`${getNowString()} ОШИБКА: `,
|
||||
`Истекло время ожидания останова сервера приложений. Инициирован аварийный выход из процесса.`
|
||||
);
|
||||
process.exit(1);
|
||||
}, cfg.common.nTerminateTimeout);
|
||||
try {
|
||||
await appSrv.stop(terminateTimeout);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
await appSrv.logger.error(`При останове сервера приложений: ${makeErrorText(e)}`);
|
||||
clearTimeout(terminateTimeout);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
//Перехват всех неохваченных ошибок
|
||||
process.on("uncaughtException", e => {
|
||||
//Протоколируем ошибку
|
||||
appSrv.logger.error(makeErrorText(e));
|
||||
//Инициируем выход из процесса
|
||||
appSrv.stop();
|
||||
console.log(SCONSOLE_LOG_COLOR_PATTERN_ERR, `${getNowString()} НЕПРЕДВИДЕННАЯ ОШИБКА: `, makeErrorText(e));
|
||||
//Останов с ошибкой
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
//Запуск сервера приложений
|
||||
@ -82,7 +81,7 @@ const start = async () => {
|
||||
await appSrv.stop();
|
||||
} catch (e) {
|
||||
//Могут быть ошибки и при остановке - это аварийный выход
|
||||
appSrv.logger.error(makeErrorText(e));
|
||||
await appSrv.logger.error(makeErrorText(e));
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,9 @@ const Schema = require("validate"); //Схемы валидации
|
||||
// Тело модуля
|
||||
//-------------
|
||||
|
||||
//Функция проверки значения таймаута останова сервера
|
||||
const validateTerminateTimeout = val => val >= 1000 && val <= 120000 && Number.isInteger(val);
|
||||
|
||||
//Функция проверки значения размера блока одновременно обрабатываемых исходящих сообщений
|
||||
const validateMaxWorkers = val => val >= 1 && val <= 100 && Number.isInteger(val);
|
||||
|
||||
@ -25,6 +28,22 @@ const validateInComingPort = val => val >= 0 && val <= 65535 && Number.isInteger
|
||||
//Функция проверки значения порта сервера обслуживания входящих сообщений
|
||||
const validateMsgMaxSize = val => val >= 1 && val <= 1000 && Number.isInteger(val);
|
||||
|
||||
//Схема валидации общих параметров сервера приложений
|
||||
const common = new Schema({
|
||||
//Таймаут останова сервера (мс)
|
||||
nTerminateTimeout: {
|
||||
type: Number,
|
||||
required: true,
|
||||
use: { validateTerminateTimeout },
|
||||
message: {
|
||||
type: path => `Таймаут останова сервера (${path}) имеет некорректный тип данных (ожидалось - Number)`,
|
||||
required: path => `Не указан таймаут останова сервера (${path})`,
|
||||
validateTerminateTimeout: path =>
|
||||
`Таймаут останова сервера (${path}) должен быть целым числом в диапазоне от 1000 до 120000`
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
//Схема валидации параметров подключения к БД
|
||||
const dbConnect = new Schema({
|
||||
//Пользователь БД
|
||||
@ -209,6 +228,14 @@ const mail = new Schema({
|
||||
|
||||
//Схема валидации файла конфигурации
|
||||
const config = new Schema({
|
||||
//Общие параметры
|
||||
common: {
|
||||
schema: common,
|
||||
required: true,
|
||||
message: {
|
||||
required: path => `Не указаны общие параметры конфигурации сервера приложений (${path})`
|
||||
}
|
||||
},
|
||||
//Параметры подключения к БД
|
||||
dbConnect: {
|
||||
schema: dbConnect,
|
||||
@ -247,6 +274,8 @@ const config = new Schema({
|
||||
// Интерфейс модуля
|
||||
//------------------
|
||||
|
||||
//Схема валидации общих параметров сервера приложений
|
||||
exports.common = common;
|
||||
//Схема валидации записи журнала работы сервиса обмена
|
||||
exports.dbConnect = dbConnect;
|
||||
//Схема валидации параметров обработки очереди исходящих сообщений
|
||||
|
Loading…
x
Reference in New Issue
Block a user