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

Node.js多线程爬取Axios POST报EADDRINUSE 443错误原因及修复

错误产生原因
  • 该错误本质是短时间内发起的出站HTTPS请求过多,耗尽了本机可用临时端口,并非目标服务端口被占用。
  • 多线程爬虫运行时,每个线程爬取完成后会产生至少4万条待提交数据,如果未做批量聚合、并发控制,会在极短时间内向目标IP18.62.228.13:443发起海量TCP连接。TCP连接关闭后会进入TIME_WAIT状态,默认需要等待1-2分钟才会彻底释放端口,当新请求到来时没有可用临时端口分配,就会抛出EADDRINUSE异常。
  • 默认配置下axios不会开启TCP连接复用(keep-alive),每次POST请求都会新建独立TCP连接,请求完成后直接断开,进一步放大了端口消耗速度。加上worker线程之间资源隔离,各线程独立发起请求,全局并发数完全失控,端口耗尽是必然结果。
可行修复方案

1. 开启TCP连接复用,复用axios实例

不要每次请求新建axios实例,全局配置开启keep-alive,让多个请求复用同一个TCP连接,从根源减少新建连接数:

const axios = require('axios');
const http = require('http');
const https = require('https');

// 每个worker线程内只初始化一次该实例,重复复用
const httpAgent = new http.Agent({
  keepAlive: true,
  maxSockets: 50, // 单实例最大并发socket数
  maxFreeSockets: 10 // 最大空闲socket数
});
const httpsAgent = new https.Agent({
  keepAlive: true,
  maxSockets: 50,
  maxFreeSockets: 10
});
const requestClient = axios.create({
  httpAgent,
  httpsAgent,
  timeout: 30000
});

2. 做批量聚合+并发限流,从量级上减少请求数

  • 不要单条数据发一次POST请求,将4万条数据拆分为每批500-1000条的大块,每次请求提交一整批,直接把请求总数从4万级降到几十级。
  • 严格控制单worker线程内的提交并发,建议单worker同时发起的提交请求不超过2个,全局总并发(worker数量*单worker并发数)不超过10,禁止直接用Promise.all一次性发起所有请求。

参考实现代码:

// 数据按指定大小分块
function splitChunks(dataList, chunkSize = 1000) {
  const chunks = [];
  for (let i = 0; i < dataList.length; i += chunkSize) {
    chunks.push(dataList.slice(i, i + chunkSize));
  }
  return chunks;
}

async function batchSubmit(allData, submitUrl) {
  const chunks = splitChunks(allData, 1000);
  const concurrency = 2; // 单worker并发数
  const runningTask = [];
  for (const chunk of chunks) {
    const task = requestClient.post(submitUrl, { data: chunk })
      .then(res => { /* 处理成功逻辑 */ })
      .catch(err => { /* 处理失败重试逻辑 */ })
      .finally(() => {
        runningTask.splice(runningTask.indexOf(task), 1);
      });
    runningTask.push(task);
    if (runningTask.length >= concurrency) {
      await Promise.race(runningTask);
    }
  }
  await Promise.all(runningTask);
}

3. 操作系统参数调优(辅助方案)

如果程序运行在Linux环境,可以调整内核参数扩大临时端口范围、加快TIME_WAIT连接回收,作为代码优化的补充:

  • 编辑/etc/sysctl.conf添加以下配置:
# 扩大临时端口范围
net.ipv4.ip_local_port_range = 1024 65535
# 允许复用TIME_WAIT状态的连接
net.ipv4.tcp_tw_reuse = 1
  • 执行sysctl -p让配置生效。

注意:系统参数调优不能替代代码层面的优化,如果不做连接复用和并发控制,即使调大端口范围,依然会出现端口耗尽的问题。

内容的提问来源于stack exchange,提问作者nikita cohen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 00:01:47