您好,登錄后才能下訂單哦!
本篇文章為大家展示了怎樣讓Nodejs服務器優雅地退出,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
假設我們啟動了一個服務器,接收到了一些客戶端的請求,這時候,如果我們想修改一個代碼發布,需要重啟服務器,怎么辦?假設我們有以下代碼。
server.js
const net = require('net'); const server = net.createServer().listen(80);
client.js
const net = require('net'); net.connect({port:80})
如果我們直接殺死進程,那么存量的請求就會無法正常被處理。這會影響我們的服務質量。本文介紹如何使nodejs在重啟時優雅地退出,所謂優雅,即讓nodejs進程處理完存量請求后再退出。這關鍵的地方在于nodejs提供的api server.close()。我們看一下這api的介紹。
Stops the server from accepting new connections and keeps existing connections. This function is asynchronous, the server is finally closed when all connections are ended and the server emits a 'close' event. The optional callback will be called once the 'close' event occurs. Unlike that event, it will be called with an Error as its only argument if the server was not open when it was closed.
當我們使用close關閉一個server時,server會等所有的連接關閉后才會觸發close事件。我們看一下源碼。
Server.prototype.close = function(cb) { // 觸發回調 if (typeof cb === 'function') { if (!this._handle) { this.once('close', function close() { cb(new errors.Error('ERR_SERVER_NOT_RUNNING')); }); } else { this.once('close', cb); } } // 關閉底層資源 if (this._handle) { this._handle.close(); this._handle = null; } // 判斷是否需要立刻觸發close事件 this._emitCloseIfDrained(); return this; }; // server下的連接都close后觸發server的close事件 Server.prototype._emitCloseIfDrained = function() { // 還有連接則先不處理 if (this._handle || this._connections) { return; } const asyncId = this._handle ? this[async_id_symbol] : null; nextTick(asyncId, emitCloseNT, this); }; Socket.prototype._destroy = function(exception, cb) { ... // socket所屬的server if (this._server) { // server下的連接數減一 this._server._connections--; /* 是否需要觸發server的close事件, 當所有的連接(socket)都關閉時才觸發server的是close事件 */ if (this._server._emitCloseIfDrained) { this._server._emitCloseIfDrained(); } } };
從源碼中我們看到,nodejs會先關閉server對應的handle,所以server不會再接收新的請求了。但是server并沒有觸發close事件,而是等到所有連接斷開后才觸發close事件,這個通知機制給了我們一些思路。我們可以監聽server的close事件,等到觸發close事件后才退出進程。
const net = require('net'); const server = net.createServer().listen(80); server.on('close', () => { process.exit(); }); // 防止進程提前掛掉 process.on('uncaughtException', () => { }); process.on('SIGINT', function() { server.close(); })
我們首先監聽SIGINT信號,當我們使用SIGINT信號殺死進程時,首先調用server.close,等到所有的連接斷開,觸發close時候時,再退出進程。我們首先開啟服務器,然后開啟兩個客戶端。接著按下ctrl+c,我們發現這時候服務器不會退出,然后我們關閉兩個客戶端,這時候server就會優雅地退出。
上述內容就是怎樣讓Nodejs服務器優雅地退出,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。