如何在NodeJS中调试套接字挂起错误?

63

我遇到了以下错误:

events.js:48
        throw arguments[1]; // Unhandled 'error' event
        ^
Error: socket hang up
    at createHangUpError (http.js:1091:15)
    at Socket.onend (http.js:1154:27)
    at TCP.onread (net.js:363:26)

在node v0.6.6中,我的代码有多个http.request和.get调用。请建议一些方法来跟踪是什么导致了套接字挂起,并且是哪个请求/调用导致的。谢谢


当出现上述错误时,您可以通过重新启动服务器来解决问题。我们使用pm2,只需执行pm2 restart all即可重新启动。 - 151291
5个回答

46

快速而简单的开发解决方案:

使用longjohn,你可以获得包含异步操作的长堆栈跟踪。

干净而正确的解决方案: 在Node中,每当触发一个未被监听的'error'事件时,它会抛出异常。为了避免抛出异常,请给它添加一个监听器并自行处理。这样你就可以记录更多信息的错误日志了。

为一组调用设置一个监听器,你可以使用domain,并在运行时捕获其他错误。确保与代码的其他部分不同,每个与http(Server/Client)相关的异步操作都在不同的domain上下文中,该域将自动监听error事件并将其传递到其自己的处理程序。因此,您只需监听该处理程序并获取错误数据。您还可以免费获取更多信息。(Domain已被弃用)。

正如Mike所建议的,您也可以设置NODE_DEBUG=net或使用strace。它们都提供了关于Node内部操作的信息。


然后请参考 https://dev59.com/jXRB5IYBdhLWcg3wtZIV 了解如何定位跟踪中给出的“pos”。 - Jeff
2
警告:节点域当前已弃用 - Daniel Griscom
你能展示一下如何“自己处理”的示例代码吗?我该如何打印所有相关的堆栈跟踪信息? - Daniel Kaplan
基本上添加一个错误处理程序并执行必要的逻辑以处理错误,大多数情况下您只需记录套接字挂起错误。我建议将其传递给日志处理程序,希望它支持打印错误堆栈跟踪,但如果您自己执行,则通常只需简单地使用 console.log(error) - Farid Nouri Neshat

26

此外,您可以设置 NODE_DEBUG 环境变量为 net ,以获取有关所有套接字正在执行的操作的信息。这样,您就可以确定哪个远程资源正在重置连接。


13

除了ftft1885的答案之外

http.get(url, function(res)
{
    var bodyChunks = [];

    res.on('data', function(chunk)
    {
        // Store data chunks in an array
        bodyChunks.push(chunk);
    }).on('error', function(e)
    {
        // Call callback function with the error object which comes from the response
        callback(e, null);
    }).on('end', function()
    {
        // Call callback function with the concatenated chunks parsed as a JSON object (for example)
        callback(null, JSON.parse(Buffer.concat(bodyChunks)));
    });
}).on('error', function(e) {
    // Call callback function with the error object which comes from the request
    callback(e, null);
});
当我遇到“套接字挂起”错误时,是因为我没有捕获请求错误。 回调函数可以是任何东西,这取决于您的应用程序需要什么。以下是一个回调示例,使用console.log记录数据并使用console.error记录错误:
function callback(error, data) {
    if (error) {
        console.error('Something went wrong!');
        console.error(error);
    }
    else {
        console.log('All went fine.');
        console.log(data);
    }
}

2
回调函数应该包含什么内容?我是在服务器上定义还是在响应中提供? - jlewkovich
你应该在服务器上定义它。 - fwoelffel
@jlewkovich的第一个问题怎么样? - Daniel Kaplan
如果你这样做req.on('error'...,会不会更清晰一些呢?这个想法有什么问题吗? - Daniel Kaplan
这段代码没有问题。你可以将 http.get 返回的 ClientRequest 存储在一个变量中(比如说 req),然后使用该变量添加事件监听器,而不是链式调用:const req = http.get(...); req.on('error', ...) - fwoelffel

4

使用

req.on('error',function(err){})

2
答案有点简短,但是很明确:正如Eschard1991所指出的那样,您需要处理错误事件不仅来自响应对象,还要来自请求对象。 - scravy

0

很可能您的服务器套接字连接在所有http.ServerResponse对象结束之前被关闭了。在对传入连接进行任何操作之前,请确保停止所有传入请求(传入连接与传入HTTP请求不同)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接