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

Docker容器间RabbitMQ连接报错ECONNREFUSED求助

问题:Express服务无法连接Docker Compose中的RabbitMQ容器

遇到连接拒绝错误:

Error: connect ECONNREFUSED 172.19.0.2:5672
    at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1247:16) {
  errno: -111,
  code: 'ECONNREFUSED',
  syscall: 'connect',
  address: '172.19.0.2',
  port: 5672
}

确认172.19.0.2是RabbitMQ容器IP,但连接失败。以下是相关配置和代码:

docker-compose.yml

version: '3'
services:
  rabbitmq:
    image: rabbitmq:3-management-alpine
    container_name: 'rabbitmq'
    environment:
      - RABBITMQ_DEFAULT_USER=admin
      - RABBITMQ_DEFAULT_PASS=pass
    ports:
      - 5672:5672
      - 15672:15672
  producerexpress:
    build: ./service1
    container_name: producerexpress
    ports:
      - 3000:3000
    environment:
      - PORT=3000
    depends_on:
      - rabbitmq

Express应用代码

const express = require('express');
const app = express();
const port = process.env.PORT || 3000;
const amqp = require('amqplib');

const amqpUrl = process.env.AMQP_URL || 'amqp://admin:pass@172.19.0.2:5672';

let channel;
let connection;

connect();

async function connect(){
  try{
    connection = await amqp.connect(amqpUrl);
    channel = await connection.createChannel();

    await channel.assertQueue('chatExchange', {durable: false});
  } catch (err) {
    console.log(err);
  }
}

function sendRabbitMessage(msg) {
  channel.sendToQueue('chatExchange', Buffer.from(msg));
}


app.get('/', (req, res) => {
  let msg = 'Triggered by get request';
  sendRabbitMessage(msg);
  res.send('Sent rabbitmq message!');
});


app.listen(port, () => {
    console.log(`Server started on port ${port}`);
} );

Dockerfile

FROM node:16

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .

ENV PORT=3000

ENV AMQP_URL=amqp://admin:pass@172.19.0.2:5672

EXPOSE 3000

CMD ["npm", "start"]

解决方案

1. 用服务名替代静态IP作为RabbitMQ主机地址

Docker Compose会自动为同一网络内的服务创建DNS解析,直接用服务名rabbitmq就能访问RabbitMQ容器,不需要依赖静态IP(静态IP可能在容器重启后变化)。

修改Dockerfile中的AMQP_URL:

ENV AMQP_URL=amqp://admin:pass@rabbitmq:5672

同时修改Express代码中的默认URL:

const amqpUrl = process.env.AMQP_URL || 'amqp://admin:pass@rabbitmq:5672';

2. 处理RabbitMQ启动就绪问题

depends_on仅保证producerexpress在rabbitmq之后启动,但不保证RabbitMQ服务已经完全就绪(比如还在初始化用户、端口未开放)。需要在Express应用中添加连接重试逻辑,直到RabbitMQ可用。

修改connect函数,添加重试机制:

async function connect() {
  const maxRetries = 10;
  let retries = 0;
  
  while (retries < maxRetries) {
    try {
      connection = await amqp.connect(amqpUrl);
      channel = await connection.createChannel();
      await channel.assertQueue('chatExchange', { durable: false });
      console.log('成功连接到RabbitMQ');
      // 连接成功后监听连接断开事件,自动重连
      connection.on('close', () => {
        console.log('RabbitMQ连接断开,尝试重连');
        connect();
      });
      return;
    } catch (err) {
      retries++;
      console.log(`连接失败,重试第${retries}次...`, err.message);
      await new Promise(resolve => setTimeout(resolve, 2000)); // 等待2秒后重试
    }
  }
  console.error('达到最大重试次数,无法连接RabbitMQ');
}

3. 避免发送消息时的空channel错误

在sendRabbitMessage函数中添加判断,确保channel存在再发送:

function sendRabbitMessage(msg) {
  if (!channel) {
    console.error('RabbitMQ channel未就绪,无法发送消息');
    return;
  }
  channel.sendToQueue('chatExchange', Buffer.from(msg));
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 09:42:30