На платформе windows PM2 не поддерживает Node.js для «Graceful Shutdown» - PullRequest
0 голосов
/ 20 марта 2020

Я пробовал вот так -

const server = app.listen(port, () => console.log('Project running on port ' + port));

process.on('SIGINT', () => {
  console.info('SIGINT signal received.')

  // Stops the server from accepting new connections and finishes existing connections.
  server.close(function(err) {
    // if error, log and exit with error (1 code)
    if (err) {
      console.error(err)
      process.exit(1)
    }

    // close your database connection and exit with success (0 code)
    // for example with mongoose
    mongoose.connection.close(function () {
      console.log('Mongoose connection disconnected')
      process.exit(0)
    })
  })
})

И 2-й тоже. Так же -

const server = app.listen(port, () => console.log('Project running on port ' + port));

process.on('message', function(msg) {

  console.info('shutdown signal received.',msg)
  if (msg == 'shutdown') {
    console.log('Closing all connections...');
    setTimeout(function() {
      console.log('Finished closing connections');
      process.exit(0);
    }, 1500);
  }
});

Но ни то, ни другое не помогает.

Что я понимаю, прочитав все связанная с этим проблема, связанная с открытым доступом, заключается в том, что PM2 скорее посылает сигнал «SIGINT» на узел, он убивает его сам.

1 Ответ

0 голосов
/ 25 марта 2020

Вместо использования pm2 мы можем самостоятельно создать bash скрипт, который перезапустит наш проект узла, если закроется с некоторой ошибкой.

    @echo off
    setlocal enableextensions enabledelayedexpansion
    set /a "x = 0"

:more_to_process
    if %x% leq 10 (
        echo %x%
        node E:\Max\Projects\dummy\API\server.js
        set /a "x = x + 1"
        goto :more_to_process
    )

    endlocal
    pause

Выше сценария повторите 10 раз, чтобы перезапустить API. Можно изменить время повтора.

Теперь для создания файлов журнала и обработки ошибок мы можем сделать

const server = app.listen(port, () => console.log('Dummy-App API running on port ' + port));

var fs = require('fs');
var util = require('util');

var path = __dirname + `/mylogfiles/debug(${getDate()}).log`, printNextLine = false
if(fs.existsSync(path)){
  printNextLine = true
}
var log_file = fs.createWriteStream(path, {flags : 'a'});  
/* 'a'  : open the file for writing, positioning the stream at the end of the file. The file is created if not existing
   'a+' : open the file for reading and writing, positioning the stream at the end of the file. The file is created if not existing
   'r+' : open the file for reading and writing
   'w+' : open the file for reading and writing, positioning the stream at the beginning of the file. The file is created if not existing

(you can find more flags at https://nodejs.org/api/fs.html#fs_file_system_flags)

*/
if(printNextLine == true){
  let prnt = '***************************************************************************************************************'
  log_file.write('\n' + '\n' + prnt + '\n');
}
var log_stdout = process.stdout;

console.log = function(d) { //
  log_file.write((new Date).toLocaleString('en-IN', { timeZone: 'Asia/Kolkata' }) + ' | ' + util.format(d) + '\n');
  log_stdout.write( util.format(d) + '\n');
};

console.error = function(d) { //
  log_file.write((new Date).toLocaleString('en-IN', { timeZone: 'Asia/Kolkata' }) + ' | ' + util.format(d) + '\n');
  log_stdout.write( util.format(d) + '\n');
};

process.on('uncaughtException', function (err) {
  console.error(err)
  // console.error((new Date).toUTCString() + ' uncaughtException:', err.message)
  // console.error(err.stack)
  process.exit(1)
})

function getDate(addDay){
    let mydate = new Date()
    var month = mydate.getMonth() + 1; // month (in integer 0-11)
    var year = mydate.getFullYear(); // year
    var date = mydate.getDate()
    let h = mydate.getHours() 
    let m = mydate.getMinutes()
    let s = mydate.getSeconds() 
    // let desiredDate = `${year}.${month}.${date} H-${h} M-${m} S-${s}`
    let desiredDate = `${year}.${month}.${date}`
    return desiredDate
}
Пожалуйста, создайте папку с именем 'mylogfiles' параллельно файлу server.js / index. js.

Теперь, что осталось до "Graceful Shutdown": -

process.on('SIGINT', () => {
  console.info('SIGINT signal received.')

  // Stops the server from accepting new connections and finishes existing connections.
  server.close(function(err) {
    // if error, log and exit with error (1 code)
    if (err) {
      console.error(err)
      process.exit(1)
    }

    // close your database connection and exit with success (0 code)
    // for example with mongoose
    mongoose.connection.close(function () {
      console.log('Mongoose connection disconnected')
      process.exit(0)
    })
  })
})

О коде process.on('SIGINT', .. поможет, если мы запустим / запустим Node.js API с командой node server.js или индексом файла. js независимо от того, что его назвали.

Вот почему мы создали наш скрипт Bash, который будет принимать 'node' в качестве команды для запуска project-API. Этот сценарий bash можно поместить в любом месте системы / сервера, если только и до тех пор, пока путь, указанный в сценарии bash для запуска основного файла API, не будет правильным.

Наконец, главный server.js / index. js файл может выглядеть как -

const express = require('express');
const bodyParser = require('body-parser'); // call body-parser here to parse body request from frontend 
var fileUpload = require('express-fileupload');  // call express-fileupload here to accept file in the form of multipart data  from frontend 

// create express app
const app = express();

// parse requests of content-type - application/json
app.use(bodyParser.json({limit:'50mb'}));  // here we try to set body request can accept requested data from frontend upto 50Mb

// parse requests of content-type - application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true,limit:'50mb' })); // here we try to set body request can accept requested data from frontend as urlencoded and upto 50Mb
app.use(fileUpload()); // here enable app to use fileupload

// Configuring the database
const dbConfig = require('./config/database.config.js');

const mongoose = require('mongoose');

mongoose.Promise = global.Promise;

const options = {
  auth: {
    user: "*********ww",
    password: "******dd"
  },
  useNewUrlParser: true,
  useCreateIndex: true,
  useFindAndModify: false,
  autoIndex: true, // Don't build indexes
  reconnectTries: Number.MAX_VALUE, // Never stop trying to reconnect
  reconnectInterval: 500, // Reconnect every 500ms
  poolSize: 10, // Maintain up to 10 socket connections
  // If not connected, return errors immediately rather than waiting for reconnect
  bufferMaxEntries: 0,
  connectTimeoutMS: 10000, // Give up initial connection after 10 seconds
  socketTimeoutMS: 45000, // Close sockets after 45 seconds of inactivity
  family: 4, // Use IPv4, skip trying IPv6
  serverSelectionTimeoutMS: 5000, // Timeout after 5s instead of 30s
  useUnifiedTopology: true
};
mongoose.connect(dbConfig.url, options).then(
    () => { 
        console.log("Successfully connected to the database");
    },
    err => { 
        /** handle initial connection error */ 
        console.log('Could not connect to the database. Exiting now...', err);
        process.exit();
    }
);

var port = process.env.PORT || 23804;        // set our port and port must be enable on server

var router = express.Router();    // call Router methode to enable api can accept multiple routes  

app.all('/*', function(req, res,next) {

  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Credentials", "true");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, X-Content-Type-Options, X-XSS-Protection, Content-Type, Accept, Key, Authorization");
  res.header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, PATCH");
  next()

});

// define a simple route
app.get('/', (req, res) => {
    res.json({"message": "Welcome to Dummy application. Sign Up and Login Quicky. Organize and keep track of all forms."});
});

// Require  routes

require('./app/routes/controlFile.routes.js')(app);

const server = app.listen(port, () => console.log('Dummy-App API running on port ' + port));

var fs = require('fs');
var util = require('util');

var path = __dirname + `/mylogfiles/debug(${getDate()}).log`, printNextLine = false
if(fs.existsSync(path)){
  printNextLine = true
}
var log_file = fs.createWriteStream(path, {flags : 'a'});  
/* 'a'  : open the file for writing, positioning the stream at the end of the file. The file is created if not existing
   'a+' : open the file for reading and writing, positioning the stream at the end of the file. The file is created if not existing
   'r+' : open the file for reading and writing
   'w+' : open the file for reading and writing, positioning the stream at the beginning of the file. The file is created if not existing

(you can find more flags at https://nodejs.org/api/fs.html#fs_file_system_flags)

*/
if(printNextLine == true){
  let prnt = '***************************************************************************************************************'
  log_file.write('\n' + '\n' + prnt + '\n');
}
var log_stdout = process.stdout;

console.log = function(d) { //
  log_file.write((new Date).toLocaleString('en-IN', { timeZone: 'Asia/Kolkata' }) + ' | ' + util.format(d) + '\n');
  log_stdout.write( util.format(d) + '\n');
};

console.error = function(d) { //
  log_file.write((new Date).toLocaleString('en-IN', { timeZone: 'Asia/Kolkata' }) + ' | ' + util.format(d) + '\n');
  log_stdout.write( util.format(d) + '\n');
};

process.on('uncaughtException', function (err) {
  console.error(err)
  // console.error((new Date).toUTCString() + ' uncaughtException:', err.message)
  // console.error(err.stack)
  process.exit(1)
})

process.on('SIGINT', () => {
  console.info('SIGINT signal received.')

  // Stops the server from accepting new connections and finishes existing connections.
  server.close(function(err) {
    // if error, log and exit with error (1 code)
    if (err) {
      console.error(err)
      process.exit(1)
    }

    // close your database connection and exit with success (0 code)
    // for example with mongoose
    mongoose.connection.close(function () {
      console.log('Mongoose connection disconnected')
      process.exit(0)
    })
  })
})

function getDate(addDay){
    let mydate = new Date()
    var month = mydate.getMonth() + 1; // month (in integer 0-11)
    var year = mydate.getFullYear(); // year
    var date = mydate.getDate()
    let h = mydate.getHours() 
    let m = mydate.getMinutes()
    let s = mydate.getSeconds() 
    // let desiredDate = `${year}.${month}.${date} H-${h} M-${m} S-${s}`
    let desiredDate = `${year}.${month}.${date}`
    return desiredDate
}
...