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

Ubuntu环境下NestJs/RabbitMQ无法发布消息问题排查

RabbitMQ消息无法投递问题排查

问题描述

在Ubuntu机器上,无法通过路由键向Docker容器运行的RabbitMQ服务器的交换机发布消息,甚至直接向队列发布消息也失败。该功能昨日正常运行,今日突然失效。

NodeJS服务运行在另一个Alpine镜像容器中,可正常连接RabbitMQ,能创建所需的交换机、绑定关系和队列,认证无问题(修改用户名会触发认证错误)。在RabbitMQ管理控制台创建了名为all的队列,绑定路由键#以接收所有消息,但测试脚本发布的消息始终无法投递到该队列,管理控制台也看不到消息流转痕迹。RabbitMQ日志仅显示用户test认证通过,无任何错误或警告。

RabbitMQ Docker Compose配置

rabbitmq:
    image: docker.io/bitnami/rabbitmq:3.11.23
    ports:
      - '4369:4369'
      - '5551:5551'
      - '5552:5552'
      - '5672:5672'
      - '25672:25672'
      - '15672:15672'
    environment:
      RABBITMQ_SECURE_PASSWORD: no
      RABBITMQ_LOGS: /bitnami/rabbitmq/mnesia/logs
      RABBITMQ_PLUGINS: rabbitmq_management
      RABBITMQ_USERNAME: ${BROKER_USER}
      RABBITMQ_PASSWORD: ${BROKER_PASSWORD}
      TZ: Europe/Amsterdam
    volumes:
      - 'rabbitmq_data:/bitnami/rabbitmq/mnesia'
    expose:
      - 4369
      - 5551
      - 5552
      - 5672
      - 25672
      - 15672
    networks:
      - broker
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:15672"]
      interval: 5s
      timeout: 5s
      retries: 10
    restart: always

NodeJS测试脚本

const amqp = require('amqplib');

const message = {
  message: 'world',
};

async function connectAndPublish() {
  try {
    // Connect to RabbitMQ server
    const connection = await amqp.connect('amqp://test:test@rabbitmq:5672/');
    const channel = await connection.createChannel();

    // Declare exchange
    const exchangeName = 'the-exchange';
    await channel.assertExchange(exchangeName, 'topic', { durable: true });

    // Convert message to JSON and publish to the exchange
    const messageBuffer = Buffer.from(JSON.stringify(message));
    channel.publish(exchangeName, 'hello', messageBuffer);

    console.log(`Message published to exchange ${exchangeName}:`, message);

    // Close connection
    await channel.close();
    await connection.close();
  } catch (error) {
    console.error('Error:', error.message);
  }
}

// Call the function to connect and publish
connectAndPublish();

已尝试的操作

  • 升级/降级RabbitMQ服务器版本(3.11或3.12)
  • 直接向all队列发布消息,而非通过交换机和路由键
  • 重启Docker容器

可能的原因及解决方案

1. 交换机与队列绑定关系异常

检查管理控制台中the-exchange的绑定列表,确认:

  • 绑定的队列确实是all
  • 绑定的路由键是#,且交换机名称与脚本中的the-exchange完全一致(RabbitMQ名称区分大小写)
  • 绑定操作已成功保存,未因数据异常丢失

2. 消息发布后过早关闭连接

channel.publish是异步操作,脚本中发布后立即关闭通道和连接,可能导致消息还未完成投递就被中断。修改脚本添加确认逻辑:

async function connectAndPublish() {
  try {
    const connection = await amqp.connect('amqp://test:test@rabbitmq:5672/');
    const channel = await connection.createChannel();

    const exchangeName = 'the-exchange';
    await channel.assertExchange(exchangeName, 'topic', { durable: true });
    
    // 开启确认模式
    await channel.confirmSelect();

    const messageBuffer = Buffer.from(JSON.stringify(message));
    // 等待消息发布确认
    await new Promise((resolve, reject) => {
      channel.publish(exchangeName, 'hello', messageBuffer, (err) => {
        if (err) reject(new Error(`Publish failed: ${err.message}`));
        else resolve();
      });
    });

    console.log(`Message published to exchange ${exchangeName}:`, message);

    await channel.close();
    await connection.close();
  } catch (error) {
    console.error('Error:', error.message);
  }
}

3. 用户权限不足

test用户可能缺少对应权限:

  • 进入管理控制台→用户→test→权限,确认其对默认虚拟主机/拥有configure、write、read权限
  • 尝试使用docker-compose中配置的${BROKER_USER}用户测试,排除权限问题

4. RabbitMQ持久化数据损坏

持久化卷rabbitmq_data中的元数据(队列、绑定关系)可能损坏:

  • 停止RabbitMQ容器,备份rabbitmq_data卷数据
  • 删除该卷,重新启动RabbitMQ容器,重建队列和绑定关系后测试

5. 网络数据包丢失(极端情况)

虽然能连接,但可能存在底层网络问题:

  • 确认NodeJS容器和RabbitMQ容器在同一个broker网络中
  • 在NodeJS容器内执行nc -zv rabbitmq 5672测试端口连通性
  • 查看Docker网络日志,排查是否有数据包丢弃情况

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 07:34:51