2013-06-30 36 views
9

我有一個nodejs服務器運行快速服務器出http調用。如果出現問題,是否有推薦的方法可以優雅地關閉服務器?我應該讓服務器以某種方式運行嗎?Nodejs /快遞,優雅地關機

I.E.在一個未捕獲的例外情況下,服務器只是停止,我認爲這會殺死連接的客戶端,而不是將它們交還給迴應。

我應該:

  1. 等待所有的HTTP連接完成之前,我允許服務器死亡(然後重新啓動它)。
  2. 或者我應該試着阻止服務器永生?

這是正確的嗎?

process.on('exit', function() { 
    console.log('About to exit, waiting for remaining connections to complete'); 
    app.close(); 
}); 

在這種情況下,可能已經引發錯誤而使服務器處於不確定狀態,服務器將繼續完成了剩餘的連接。

有沒有什麼好的方法來處理錯誤繼續運行,或者我應該讓服務器死機並重新啓動?

回答

6

不要試圖對未處理的異常做任何事情。讓服務器死亡。

通常,如果路由處理程序拋出異常,Express將簡單地捕獲它並向客戶端返回HTTP 500。由於Express發現異常,您的服務器不會崩潰。

通常會導致服務器關閉的情況是在回調中引發異常;例如:

app.get('/foo', function(req, res) { 
    db.query(..., function(err, r) { 
     throw new Error(); // oops, we'll crash 
    }); 
}); 

由於回調自然在Express路由器調用堆棧外執行,因此無法將其與特定請求關聯。但是,您可以防止這樣的情況:

app.get('/foo', function(req, res, next) { 
    db.query(..., function(err, r) { 
     try { 
      throw new Error(); 
     } catch(ex) { 
      next(ex); 
     } 
    }); 
}); 

快車next函數接受一個錯誤作爲第一個參數。如果調用next一個錯誤的說法,它會停止處理路線,尋找一個error handler,或只返回一個500

當然,在try/catch包裝一切可能是矯枉過正;大多數事情實際上並沒有拋出異常。你只應該這樣做,如果你知道東西可能會拋出你。否則,您可能最終很難通過吞吐異常來調試不一致的狀態。

請務必記住,一旦引發意外異常,您的應用程序處於未定義狀態。問題請求可能永遠無法完成,並且您的應用永遠不會重新啓動。或者其他任何奇怪的事情都可能發生。 (這是一個數據庫問題?文件系統?損壞的內存?)

這些類型的情況難以置信地診斷,更不用說調試。它更安全,而且可以更好地快速失敗,崩潰並重新啓動服務器。是的,任何碰巧連接的客戶都會被切斷,但他們只需簡單地重試即可。

如果您擔心可用性,請使用cluster module,以便運行多個(通常爲多個CPU核心)服務器進程,並且一次崩潰不會導致整個站點停止運行。

+1

這是一個很好的解釋。但有一點我仍然不清楚。 '重要的是要記住,一旦拋出意外的異常,你的應用程序處於未定義的狀態。問題請求可能永遠不會完成,並且您的應用程序永遠不會重新啓動。這聽起來好像我不應該打電話應用程序。關();在過程'退出'。真正? – lostintranslation

+0

在''process'' exit'處理程序中調用'app.close()'是毫無意義的:[docs say](http://nodejs.org/api/process.html#process_event_exit)*「主事件循環將會在'exit'回調完成後不再運行。「*換句話說,'exit'事件告訴你程序**將在你的函數返回後結束。由於沒有下一個勾號,關閉網絡監聽器毫無意義;接受傳入連接的代碼永遠不會有機會運行。 – josh3736

+0

真棒,謝謝! – lostintranslation

5

NodeJS在不期望發生任何事情時會關閉;當http服務器正在等待連接節點保持運行時。

server.close([callback])

停止接受新連接的服務器,並保持現有 連接。此功能是異步的,當所有連接都結束並且服務器發出事件時,服務器終於關閉了。 事件。或者,您可以傳遞迴調來偵聽事件的close 事件。

執行此操作後,服務器將繼續運行,直到最後一次連接完成,然後正常關機。

如果您不想等待連接終止,則可以在剩餘的連接上使用socket.end()socket.destroy()

http://nodejs.org/api/net.html


process.on('exit', function() { 
    console.log('About to exit, waiting for remaining connections to complete'); 
    app.close(); 
}); 

當節點存在並沒有真正告訴節點退出此功能應該運行。這裏是你可以結束你的過程,但它會無法正常結束的一種方法:

process.exit([code])

結束與指定代碼的過程。如果省略,退出使用 '成功'代碼0

要與「失敗」代碼退出:

process.exit(1);被執行節點應該看到退出代碼 作爲1殼。

http://nodejs.org/api/process.html


我希望這有助於!