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

发送大量消息时RabbitMQ连接失败,少量消息正常的原因排查

问题原因分析

你的代码核心问题是每次发送一条消息就新建一个RabbitMQ连接。当发送2000条消息时,会瞬间创建2000个连接,这直接触发了CloudAMQP的连接数限制(CloudAMQP的免费/基础套餐通常有严格的连接数上限,比如最多10-20个并发连接),同时短时间内大量TCP连接请求也会被服务器或网络层面拦截,导致ECONNREFUSED和连接被主动关闭的错误。

少量消息时,连接数还没达到限制,所以能正常工作;但消息量上去后,连接数超限就会被拒绝。

解决方案

1. 复用连接与通道

RabbitMQ的设计是一个连接可以创建多个通道,通道是轻量级的,适合复用。你应该在应用启动时创建一次连接和通道,之后所有消息都通过这个通道发送,而不是每次新建连接。

修改后的代码示例:

const express = require('express');
const XLSX = require("xlsx");
const amqp = require('amqplib/callback_api');

const app = express();
const port = process.env.PORT || 3300;

// 全局保存连接和通道
let rabbitConnection = null;
let rabbitChannel = null;
const QUEUE_NAME = "review_data";

// 启动时初始化RabbitMQ连接和通道
function initRabbitMQ() {
  amqp.connect(`amqps://nuogafvveJoldl_RhEyfs7qJzX0BIRep6J8rFIN-0@puffin.rmq2.cloudamqp.com/xxxxxxx`, (err, connection) => {
    if (err) {
      console.error("RabbitMQ连接失败:", err);
      // 可选:添加重连逻辑,间隔几秒重试
      setTimeout(initRabbitMQ, 5000);
      return;
    }
    rabbitConnection = connection;
    console.log("RabbitMQ连接成功");

    connection.createChannel((err, channel) => {
      if (err) {
        console.error("创建通道失败:", err);
        return;
      }
      rabbitChannel = channel;
      // 预先声明队列(只需要做一次)
      channel.assertQueue(QUEUE_NAME, { durable: false });
      console.log("RabbitMQ通道初始化完成");
    });

    // 监听连接关闭事件,自动重连
    connection.on('close', () => {
      console.log("RabbitMQ连接已关闭,准备重连");
      rabbitConnection = null;
      rabbitChannel = null;
      setTimeout(initRabbitMQ, 5000);
    });
  });
}

// 初始化RabbitMQ
initRabbitMQ();

// 读取Excel文件
const file = XLSX.readFile('./limit9.xlsx')

app.get('/', (req, res) => {
  if (!rabbitChannel) {
    res.status(503).send("RabbitMQ通道未就绪,请稍后重试");
    return;
  }

  const sheets = file.SheetNames;
  let messageCount = 0;
  for (let i = 0; i < sheets.length; i++) {
    const temp = XLSX.utils.sheet_to_json(file.Sheets[file.SheetNames[i]]);
    temp.forEach((rowData) => {
      const json = JSON.stringify(rowData);
      rabbitChannel.sendToQueue(QUEUE_NAME, Buffer.from(json));
      messageCount++;
    });
  }
  res.send(`成功发送 ${messageCount} 条消息到队列`);
});

app.listen(port, () => {
  console.log(`服务运行在端口 ${port}`);
});

2. 额外优化建议

  • 添加消息确认:如果需要确保消息被队列接收,可以使用sendToQueue的回调参数,或者开启通道的confirm模式,处理消息发送失败的情况。
  • 批量处理:如果Excel数据量极大,可以分批次发送,避免一次性占用过多内存。
  • 连接池(可选):如果确实需要多通道,可以使用连接池,但对于大多数场景,单连接+多通道已经足够。

关键注意点

  • 永远不要在循环或请求处理中重复创建RabbitMQ连接,这是RabbitMQ客户端开发的基本规范。
  • CloudAMQP的连接数、通道数、消息速率都有套餐限制,如果你需要更高的配额,可以升级套餐。

内容的提问来源于stack exchange,提问作者Digvijay Singh Thakur

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 15:35:20