TypeError:终止[原因]:SocketError:另一端在获取Nodejs时关闭

问题描述 投票:0回答:1

当我不断获取外部 API 时,我收到此错误,我只是调用:

await fetch(url, method: "POST", headers:headers, body: JSON.stringify(payload))
TypeError: terminated
    at Fetch.onAborted (node:internal/deps/undici/undici:11442:53)
    at Fetch.emit (node:events:514:28)
    at Fetch.terminate (node:internal/deps/undici/undici:10695:14)
    at Object.onError (node:internal/deps/undici/undici:11537:36)
    at Request.onError (node:internal/deps/undici/undici:8310:31)
    at errorRequest (node:internal/deps/undici/undici:10378:17)
    at TLSSocket.onSocketClose (node:internal/deps/undici/undici:9811:9)
    at TLSSocket.emit (node:events:526:35)
    at node:net:337:12
    at TCP.done (node:_tls_wrap:631:7) {
  [cause]: SocketError: other side closed
      at TLSSocket.onSocketEnd (node:internal/deps/undici/undici:9790:26)
      at TLSSocket.emit (node:events:526:35)
      at endReadableNT (node:internal/streams/readable:1376:12)
      at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
    code: 'UND_ERR_SOCKET',
    socket: {
      localAddress: '172.17.0.2',
      localPort: 48798,
      remoteAddress: '13.232.157.196',
      remotePort: 443,
      remoteFamily: 'IPv4',
      timeout: undefined,
      bytesWritten: 1594938,
      bytesRead: 12318698
    }
  }
}

我已经阅读了SocketError:另一侧关闭,但是,我仍然很困惑如何解决它或获得有关此错误的更多提示。

我该如何修复它或追踪我的请求哪里有问题?

javascript fetch-api undici
1个回答
2
投票

注意:以下所有内容均不确定。我没有这方面的 Node 知识。

我们在工作中遇到了这个问题(Node 18.x,AWS Lambda 环境),我们发现 Node 有时会过早关闭 TLS 连接。

根据

undici
问题,响应必须始终被消耗(在结束当前的JS执行块之前,如果我正确理解的话)。

所以,这有时可能会失败:

const myFetcher = async (url) => await fetch(url)

这可能是一个解决方法:

const myFetcher = async (url) => {
  const res = await fetch(url)

  /**
   * Response body must be consumed to avoid socket error.
   * https://github.com/nodejs/undici/issues/583#issuecomment-855384858
   */
  const clonedRes = res.clone() // alternative: `res.clone()`

  return clonedRes; // if using previous alternative: `return res`
};

如果您不需要进一步使用响应,这可能是另一个:

const myFetcher = async (url) => {
  const res = await fetch(url)

  /**
   * Response body must be consumed to avoid socket error.
   * https://github.com/nodejs/undici/issues/583#issuecomment-855384858
   */
  res.body.getReader() //

  // There’s no point returning `res`: it is consumed by the previous line.
};

我认为解决方法是有效的,因为响应主体是在函数定义内部消耗的(= in

myFetcher
),而不是像第一个示例中那样在外部消耗。我在 MDN
Object.clone
上发现了一个关于 TCP 机制背压的注释,而且 Node 上似乎也有一个 完整指南。在我们的案例中,我对它的理解是,
fetch
响应足够大,足以让 Node 减慢其进程:基本上它是对另一方说的(
fetch
调用的 URL 背后的系统,或者是内部部分)节点在内存/缓冲区中保存响应)“在我们完成事务之前你能等一下吗?”,而远程部分可能等不及了,所以它放弃了,并抛出这个错误。这就是为什么尽快消耗身体可能可以解决这个问题。

查看堆栈时,我们只有一个地方指代“另一侧关闭”在Node中,我猜要隔离导致此行为的确切失败并不容易。

通过查找显示

at TCP.done (node:_tls_wrap:631:7)
的堆栈跟踪行,我在 Node core 中找到了一个 pull 请求来解决我们的确切问题。根据 PR 作者和一位评论者的说法,Node 不太符合 HTTP RFC 中有关消息正文长度的部分,而且显然目前在 Node 20 中也没有修复

(当然,我可能全错了。)

© www.soinside.com 2019 - 2024. All rights reserved.