var http = require('http');
var server = http.createServer().listen(4000);
server.on('close', function () {
console.log('close event', Date.now());
});
server.on('request', function (req, res) {
console.log('request', Date.now());
server.close(function () {
console.log('server closed!', Date.now());
});
res.end('res ok');
})
為什麼使用了 server.close()
,卻不能觸發 close
事件?
看了下 HTTP API 說明:
停止服務端接收新的連線。
以及 TCP API 描述:
使伺服器停止接收新連接,只保持現存的連接。這個函數是異步的,當所有連接都斷開時,伺服器關閉並且發出'close'事件...
#原來 server.close()
只是讓伺服器停止接收新連接,並沒有直接操作關閉伺服器。只有當所有連線都斷開的時候,伺服器才會處於關閉狀態並且發射 close
事件。
但是,程式碼改成延遲呼叫卻可以直接關閉伺服器(當然,得在5秒內建立一個HTTP
連線)。
var http = require('http');
var server = http.createServer().listen(4000);
server.on('close', function () {
console.log('close event', Date.now());
});
server.on('request', function (req, res) {
console.log('request', Date.now());
res.end('res ok');
})
function closeServer() {
server.close(function () {
console.log('server closed!', Date.now());
});
}
setTimeout(function () {
closeServer();
}, 5000);
如果依照 API 中的描述,close()
方法只是 停止服務端接收新的連線。那麼,為什麼改為後面這種方式卻可以直接關閉伺服器?
api 的描述是正確的。只是你測試的時候理解錯了,兩種關閉 http 服務最終都會關閉,只是運行邏輯不同。
運行過程
程式碼 1 會一直等待你建立 http 連接不關閉,直到你要求 1 次 http 連接,然後會在這次請求後的 2 分鐘後才關閉 http 服務。
代碼 2 會等你 5 秒鐘,如果 5 秒之內你沒有建立連接,會直接關閉 http 服務。如果你在 5 秒之內請求 1 次 http 連接,然後會在這次請求後的 2 分鐘後才關閉 http 服務。
運行過程的原因
原来 server.close() 只是使服务器停止接收新连接,并没有直接操作关闭服务器。只有当所有连接都断开的时候,服务器才会处于关闭状态并且发射 close 事件。
问题在于什么时候算所有连接都断开
?當你執行res.end('res ok'); 的時候,http 連接並沒有關閉,因為你的請求的
Connection
是keep-alive
,這個時候只是http 服務返回數據,瀏覽器渲染頁面,http 連接仍然是開啟狀態,然後如果你2 分鐘內沒有新的請求,這次http 連線才關閉。 2 分鐘是 http 服務(不是 http 請求)預設的 timeout。soonfy