【问题标题】:Socket Hangup Error In Node JS On Force API Timeout强制 API 超时时节点 JS 中的套接字挂断错误
【发布时间】:2020-05-13 20:41:45
【问题描述】:

我正在使用 Node JS (v8.12) 中的请求模块来调用第三方 API。由于 API 不是很可靠并且由于缺乏更好的选项,我会在 2 秒后超时调用,以防 API 没有响应。但是这样做会产生一个套接字挂起错误。下面是使用的代码和堆栈跟踪

const options = {
    url: resource_url,
    rejectUnauthorized: false,
    timeout: 2000,
    method: 'GET',
    headers: {
        'content-Type': 'application/json',
    }
};

return new Promise(function (resolve, reject) {
    request(options, function (err, res, body) {
        if (!err) {
            resolve(JSON.parse(body.data));                 
        } else {
            if (err.code === 'ETIMEDOUT' || err.code == 'ESOCKETTIMEDOUT') {
                resolve(someOldData);
            } else {
                resolve(someOldData);
            }
        }
    });
});


Error: socket hang up
    at createHangUpError (_http_client.js:331:15)
    at TLSSocket.socketCloseListener (_http_client.js:363:23)
    at scope.activate (<trace-log-base-path>/dd-trace/packages/dd-trace/src/scope/base.js:54:19)
    at Scope._activate (<trace-log-base-path>/dd-trace/packages/dd-trace/src/scope/async_hooks.js:51:14)
    at Scope.activate (<trace-log-base-path>/dd-trace/packages/dd-trace/src/scope/base.js:12:19)
    at TLSSocket.bound (<trace-log-base-path>/dd-trace/packages/dd-trace/src/scope/base.js:53:20)
    at emitOne (events.js:121:20)
    at TLSSocket.emit (events.js:211:7)
    at _handle.close (net.js:554:12)
    at TCP.done [as _onclose] (_tls_wrap.js:356:7)

在做了一些阅读和研究之后,我发现这个 article 指出了一个类似的问题,所以我切换到 http 模块,如文章中的解决方案之一所述。但是切换到 http 模块也没有解决问题。下面是使用 http 和堆栈跟踪的代码实现。

let responseData;
const requestOptions = {
    hostname: resource_host,
    path: resource_path,
    method: 'GET',
    timeout: 2000,
};

return new Promise((resolve, reject) => {
    const requestObject = http.request(requestOptions, (responseObj) => {
        responseObj.setEncoding('utf8');
        responseObj.on('data', (body) => {          
           responseData = body;
        });

        responseObj.on('end', () => {
            resolve(responseData);
        });
    });

    requestObject.on('error', (err) => {
        responseData = someOldData;
        resolve(responseData);
    });

    requestObject.on('timeout', () => {
        responseData = someOldData;
        requestObject.abort();
    });

    requestObject.end();
});

Error: socket hang up
    at connResetException (internal/errors.js:608:14)
    at Socket.socketCloseListener (_http_client.js:400:25)
    at <trace-log-base-path>/dd-trace/packages/dd-trace/src/scope/base.js:54:19
    at Scope._activate (<trace-log-base-path>/dd-trace/packages/dd-trace/src/scope/async_hooks.js:51:14)
    at Scope.activate (<trace-log-base-path>/dd-trace/packages/dd-trace/src/scope/base.js:12:19)
    at Socket.bound (<trace-log-base-path>/dd-trace/packages/dd-trace/src/scope/base.js:53:20)
    at Socket.emit (events.js:322:22)
    at Socket.EventEmitter.emit (domain.js:482:12)
    at TCP.<anonymous> (net.js:672:12)

我通过网络浏览了多个 SO 帖子和各种其他资源,但我无法解决此问题。

可能是因为第三方,因为我还尝试通过创建一个虚拟服务器来重现该问题,该服务器在请求被触发后休眠一段时间并超时该请求但无法重现该问题。

我将非常感谢您在这方面的任何帮助。

【问题讨论】:

  • 我面临同样的问题。你能解决吗?这可能是由于 dd-trace 库而发生的
  • @AvijitGupta 我能够通过使用 http 模块并在超时事件块中删除 requestObject.abort(); 来解决它
  • 感谢您的回答,很高兴它对您有用。在我们的例子中,我们没有在任何地方使用 abort 方法。我会看看能不能尽快找到解决办法。

标签: node.js sockets node-modules node-request node-https


【解决方案1】:

在使用 http 模块时删除超时事件块中的 requestObject.abort() 可以解决此问题。

【讨论】:

    猜你喜欢
    • 2018-02-24
    • 2015-05-03
    • 2019-08-02
    • 2015-10-30
    • 2014-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多