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

基于Node.js的S3批量下载时网络中断及MySQL连接丢失问题求助

问题原因与解决方案

核心原因

你使用Promise.all一次性发起1000个S3下载请求,会瞬间耗尽Node.js的TCP连接池/系统文件描述符上限。Node.js的HTTP模块默认对每个域名的并发套接字数有限制(通常为10),AWS SDK虽有自己的连接池配置,但上千个并发请求远超合理阈值,导致后续请求无法建立网络连接。

这种网络资源耗尽会影响整个进程的网络操作,包括MySQL连接——长时间无操作或无法发送心跳包,会被MySQL服务器主动断开连接,最终触发事务失败的报错。

而测试5个1GB文件时,并发数仅为5,远低于连接池上限,因此能正常完成下载。

解决方案

1. 限制并发请求数

放弃Promise.all一次性发起所有请求,改用带并发限制的异步遍历,将并发数控制在20-50之间(可根据服务器配置调整)。推荐使用p-limit库实现,也可自行编写简单的并发控制逻辑:

import pLimit from 'p-limit';

// 设置最大并发数为30
const limit = pLimit(30);
const readablePayloads: Array<{ filename: string; buffer: Readable; }> = [];

// 用limit包装每个下载任务
await Promise.all(Ids.map(id => limit(async () => {
  // 根据id获取bucket和key
  const buffer = await S3Helper.getReadable({bucket, key}, {accessKeyId, secretAccessKey});
  readablePayloads.push({ filename, buffer });
})));

2. 优化AWS SDK连接池配置

调整S3客户端的HTTP连接池参数,避免连接耗尽:

import { S3Client } from '@aws-sdk/client-s3';
import { NodeHttpHandler } from '@aws-sdk/node-http-handler';
import https from 'https';

function createS3Client(awsOpts) {
  return new S3Client({
    ...awsOpts,
    requestHandler: new NodeHttpHandler({
      httpsAgent: new https.Agent({
        maxSockets: 50 // 调整为符合服务器资源的数值
      })
    })
  });
}

3. 修复代码中的错误

原代码存在两处明显问题:

  • 变量名拼写错误:bugffer应改为buffer
  • readablePayloads声明在map回调内部,每次循环都会重新创建,最终无法收集到任何数据,需将其移至回调外部

4. 防止MySQL连接被断开

由于下载过程耗时较长,MySQL连接可能因长时间闲置被服务器主动断开。可采取以下措施:

  • 使用MySQL连接池时,设置合理的connectionLimit和idleTimeout参数
  • 在下载过程中定期向MySQL发送心跳请求(如SELECT 1;),保持连接活跃

内容的提问来源于stack exchange,提问作者hg.park

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 15:14:58