You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jest调用AWS SQS sendMessage时出现打开句柄无法退出问题

报错产生原因

这个问题出在AWS SDK v2的默认连接机制上:

  • SDK默认开启HTTP长连接(keepAlive),会为每个服务实例维护独立的TCP连接池
  • 你当前的代码在每次调用sendToSQS时都会新建一个AWS.SQS()实例,sendMessage请求执行完成后,实例持有的底层连接不会主动关闭,对应的事件循环句柄会一直保持活跃
  • Jest在所有测试用例执行完毕后,检测到仍有未释放的活跃句柄,就会抛出该提示,阻止进程正常退出。
解决方案(无需mock、无需配置--forceExit)

方案1:复用SQS客户端实例 + 测试收尾阶段主动销毁连接

这是最推荐的做法,既不影响性能,也能彻底释放句柄:

  • 不要在方法内部重复创建SQS实例,将实例初始化逻辑移到类构造函数中全局复用:
// 类构造函数
constructor(awsConfig, queueUrl) {
  AWS.config.update({...awsConfig});
  // 全局复用单个SQS实例
  this.sqsClient = new AWS.SQS();
  this.queueUrl = queueUrl;
}

public async sendToSQS(data){
  return new Promise((resolve, reject) => {
    const params = {
      MessageBody: JSON.stringify(data),
      QueueUrl: this.queueUrl,
    };
    this.sqsClient.sendMessage(params, (error, res) => {
      if (error) {
        return reject(error);
      }
      return resolve(res.MessageId);
    });
  });
}
  • 在测试文件的全局收尾钩子中,主动销毁AWS SDK持有的连接池,释放所有句柄:
afterAll(() => {
  // 销毁SQS实例的底层HTTP连接
  sqsFile.sqsClient.config.httpOptions.agent.destroy();
});

方案2:关闭长连接配置,让请求完成后自动释放连接

如果不想调整实例初始化的结构,可以在创建SQS实例时关闭keepAlive配置,请求结束后TCP连接会自动断开,不会残留句柄:

public async sendToSQS(data){
  return new Promise((resolve, reject) => {
    AWS.config.update({...this.awsConfig});
    // 创建实例时关闭长连接
    const sqs = new AWS.SQS({
      httpOptions: {
        keepAlive: false
      }
    });
    const params = {
      MessageBody: JSON.stringify(data),
      QueueUrl: queueUrl,
    };
    sqs.sendMessage(params, (error, res) => {
      if (error) {
        return reject(error);
      }
      return resolve(res.MessageId);
    });
  });
}

注意:这个方案会让每次SQS请求都重新建立TCP连接,生产环境下会有额外的性能开销,更适合测试场景使用。


内容的提问来源于stack exchange,提问作者Mukesh Kashyap

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 06:34:02