我有一个非常基本的http服务器:
require("http").createServer(function (req, res) {
res.end("Hello world!");
}).listen(8080);
如何监听服务器崩溃,以便发送500
状态代码作为回应?
在process.on("uncaughtException", handler)
级别收听process
工作,但我没有请求和响应对象。
我看到的一个可能的解决方案是在try - catch
回调中使用createServer
语句,但我正在寻找是否有更好的解决方案。
我尝试在error
对象上侦听server
事件,但没有任何反应:
var s = require("http").createServer(function (req, res) {
undefined.foo; // test crash
res.end("Hello world!");
});
s.on("error", function () { console.log(arguments); });
s.listen(8080);
答案 0 :(得分:9)
您可以使用节点的内置domain module。
域提供了一种处理多个不同IO操作的方法 单组。如果注册了任何事件发射器或回调 域发出错误事件,或抛出错误,然后域 将通知对象,而不是丢失错误的上下文 在process.on('uncaughtException')处理程序中,或导致程序 立即退出并显示错误代码。
需要注意的一件非常重要的事情是:
域错误处理程序不能代替在发生错误时关闭进程。
就如何在JavaScript中使用throw的本质而言,几乎就是这样 从来没有任何方法安全地“拿起你离开的地方”,没有泄漏 引用,或创建一些其他类型的未定义的脆弱状态。
由于您只询问如何回应 (请参阅有关重新启动流程的下一部分) 500
错误,我不会像节点文档那样处理如何处理重启服务器等问题。 我强烈推荐taking a look at the example in the node docs 。
他们的示例演示了如何捕获错误,将错误响应发送回客户端(如果可能),然后重新启动服务器。我只会显示域名创建并发回500
错误响应。
域名的作用与try
/ catch
createServer
回调相同。在你的回调中:
error
事件req
和res
添加到域中(因为它们是在域存在之前创建的)run
域并调用您的请求处理程序(这类似于try
/ try
的{{1}}部分)这样的事情:
catch
通过使用var domain = require('domain');
function handleRequest(req, res) {
// Just something to trigger an async error
setTimeout(function() {
throw Error("Some random async error");
res.end("Hello world!");
}, 100);
}
var server = require("http").createServer(function (req, res) {
var d = domain.create();
d.on('error', function(err) {
// We're in an unstable state, so shutdown the server.
// This will only stop new connections, not close existing ones.
server.close();
// Send our 500 error
res.statusCode = 500;
res.setHeader("content-type", "text/plain");
res.end("Server error: " + err.message);
});
// Since the domain was created after req and res, they
// need to be explictly added.
d.add(req);
d.add(res);
// This is similar to a typical try/catch, but the "catch"
// is now d's error event.
d.run(function() {
handleRequest(req, res);
});
}).listen(8080);
模块,您可以在发生错误后很好地重新启动进程。我基本上是从这里的节点文档复制示例,但一般的想法是从主进程启动多个工作进程。 worker是处理传入连接的进程。如果其中一个具有不可恢复的错误(即我们在上一节中捕获的错误),那么它将与主进程断开连接,发送500响应并退出。当主进程看到工作进程断开连接时,它将知道发生了错误并启动了新工作程序。由于有多个工作进程同时运行,因此如果其中一个连接发生故障,则不应该出现丢失传入连接的问题。
示例代码,从here复制:
cluster
注意:我仍然要强调您应该查看domain
module documentation并查看其中的示例和说明。它解释了大部分(如果不是全部),背后的原因以及您可能遇到的其他一些情况。