使用nodemon和express实现正常关机

yrwegjxp  于 2023-01-04  发布在  Node.js
关注(0)|答案(2)|浏览(168)

当nodemon重新启动我的Express服务器时,我很难拦截信号。我需要这个来关闭数据库,否则当我下次尝试使用它时会抛出错误。**编辑:**它一开始看起来不像,但当我通过Ctrl+C终止它时,它确实调用了一些函数。我已经注解了哪些函数。
显然,nodemon在重新启动时会发送SIGUSR 2信号,但我尝试添加一个事件以及无数其他事件;这是nodemon被告知启动的文件的摘录(应用程序的主入口点在一个名为/bin/www的文件中,这是我创建express应用程序时的默认设置);如你所见我尝试了很多方法

var app = require("../app");
var debug = require("debug")("server:server");
var http = require("http");
// terminus was built to handle this, right?
const { createTerminus } = require("@godaddy/terminus");

app.set("port", "3001");

/**
 * Create HTTP server.
 */

var server = http.createServer(app);

// the terminus handler for SIGUSR2
function onSignal() {
    console.log("server is starting cleanup");
    // start cleanup of resource, like databases or file descriptors
}

async function onHealthCheck() {
    // checks if the system is healthy, like the db connection is live
    // resolves, if health, rejects if not
    return true;
}

createTerminus(server, {
    signal: "SIGUSR2",
    healthChecks: { "/healthcheck": onHealthCheck },
    onSignal
});

/**
 * Listen on provided port, on all network interfaces.
 */

server.listen(port);
server.on("error", onError);
server.on("listening", onListening);
server.on("close", () => {
    // this is never called on nodemon restart, it is when ctrl+c is pressed
    console.log("Server close");
});


/**
 * Event listener for HTTP server "listening" event.
 */

function onListening() {
    var addr = server.address();
    var bind = typeof addr === "string" ? "pipe " + addr : "port " + addr.port;
    debug("Listening on " + bind);
}


process.on("SIGTERM", function() {
    // this is never called
    console.log("SIGTERM");        
    server.close(function() {
        process.exit(0);
    });
});
process.on("SIGINT", function() {
    // this is only called on ctrl+c, not restart
    console.log("SIGINT");
    server.close(function() {
        process.exit(0);
    });
});
process.on("SIGUSR2", function() {
    // never called
    console.log("SIGUSR2");
    server.close(function() {
        process.exit(0);
    });
});
process.on("beforeExit", () => {
    // nope, never called
    console.log("before exit");
});
process.on("exit", () => {
    // only called on ctrl+c, not on restart
    console.log("exit");
});

我确信这些函数中至少有一个应该处理该事件并允许我关闭DB,但如果我通过nodemon /bin/www启动服务器,我只会得到与启动相关的输出,如果我随后通过键入rs重新启动服务器,输出日志如下所示:

Started directory watcher //normal startup
rs
[nodemon] starting `node ./bin/www` //none of the functions above is called
fnvucqvd

fnvucqvd1#

你可以为nodemon状态更改设置事件监听器,因此,你可以让它在重启时运行SQL查询来杀死应用的所有进程。
我遇到了同样的问题,在数据库中创建了一个名为 kill_other_processes 的过程,并让nodemon在重新启动时调用它。
首先,在根目录中创建一个nodemon的配置文件,名为 nodemon.json,包含以下内容:

{
  "events": {
    "restart": "mysql --user=username --password=password -Bse \"USE your_database; CALL kill_other_processes();\""
  }
}

然后,在数据库中创建过程 kill_other_processes(从this answer或您选择用来结束连接的任何其他查询):

DROP PROCEDURE IF EXISTS kill_other_processes;

DELIMITER $$

CREATE PROCEDURE kill_other_processes()
BEGIN
  DECLARE finished INT DEFAULT 0;
  DECLARE proc_id INT;
  DECLARE proc_id_cursor CURSOR FOR SELECT id FROM information_schema.processlist;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;

  OPEN proc_id_cursor;
  proc_id_cursor_loop: LOOP
    FETCH proc_id_cursor INTO proc_id;

    IF finished = 1 THEN 
      LEAVE proc_id_cursor_loop;
    END IF;

    IF proc_id <> CONNECTION_ID() THEN
      KILL proc_id;
    END IF;

  END LOOP proc_id_cursor_loop;
  CLOSE proc_id_cursor;
END$$

DELIMITER ;

现在,nodemon将在每次重启时终止连接。

e5nqia27

e5nqia272#

您可以配置nodemon以使用另一个终止信号:

  • 在控制台中:nodemon --signal SIGTERM server.js
  • 在nodemon配置中:"signal": "SIGTERM"

使用SIGTERM for nodemon时,我的Express应用程序侦听SIGINT

const shutdown = () => {
    console.debug('server: closing')
    server.close((err) => {
        if(err) {
            console.error('server: closed with ERROR', err)
            process.exit(81)
        }
        console.debug('server: closed')
        process.exit()
    })
}

process.on('SIGINT', () => {
    console.debug('process received SIGINT')
    shutdown()
})

process.on('SIGTERM', () => {
    console.debug('process received SIGTERM')
    shutdown()
})

重新启动时的日志:

[nodemon] restarting due to changes...
process received SIGINT
server: closing
server: closed
[nodemon] starting `node ./server.js`

相关问题