容器无法连接到RabbitMQ。

huangapple go评论89阅读模式
英文:

Container cannot connect to RabbitMQ

问题

我有3个容器连接到RabbitMQ:1个容器(支付服务)作为发布者,2个容器(购物车和目录服务)作为消费者。它们都在同一个网络中,并使用Docker Compose运行。奇怪的是,支付和目录容器连接到RabbitMQ容器没有问题,而购物车服务的连接始终被拒绝。不确定是什么原因,因为在将我的服务容器化之前,这3个本地服务连接到RabbitMQ容器都没有问题。

可能的问题是购物车容器在RabbitMQ容器完成启动之前尝试连接了吗?

只在购物车容器中发生:

amqp.Dial dial tcp 192.168.96.3:5672: connect: connection refused

Docker Compose配置:

cart-service:
    build: 
      context: .
      dockerfile: ./build/cart/Dockerfile
    networks:
      - shopnetwork
    ports:
      - 50052:50052
    env_file:
      - .env
    depends_on:
      - catalog-service
      - payment-service
      - redis
      - rabbitmq
  catalog-service:
    build: 
      context: .
      dockerfile: ./build/catalog/Dockerfile
    networks:
      - shopnetwork
    ports:
      - 50051:50051
    env_file:
      - .env
    depends_on:
      - mongo1
      - mongo2
      - mongo3
      - rabbitmq
  payment-service:
    build: 
      context: .
      dockerfile: ./build/payment/Dockerfile
    networks:
      - shopnetwork
    ports:
      - 50053:50053
    env_file:
      - .env
    depends_on:
      - mongo1
      - mongo2
      - mongo3
      - rabbitmq
  rabbitmq:
    image: rabbitmq:3.9.11-management
    networks:
      - shopnetwork
    ports:
      - 5672:5672
      - 15672:15672

  networks:
    shopnetwork:

我的RabbitMQ连接初始化代码。支付、购物车和目录都使用相同的代码来建立连接(在第9行拨号时失败):

// NewRabbitMQ使用环境变量中定义的配置实例化RabbitMQ实例。
func NewRabbitMQ() (*Rabbitmq, error) {
	username := os.Getenv("RABBITMQ_USERNAME")
	password := os.Getenv("RABBITMQ_PASSWORD")
	hostname := os.Getenv("RABBITMQ_HOST")
	port := os.Getenv("RABBITMQ_PORT")

	url := fmt.Sprintf("amqp://%s:%s@%s:%s/", username, password, hostname, port)
	conn, err := amqp.Dial(url) // <----------------- 在这里失败
	if err != nil {
		return nil, fmt.Errorf("amqp.Dial %w", err)
	}

	ch, err := conn.Channel()
	if err != nil {
		return nil, fmt.Errorf("conn.Channel %w", err)
	}

	err = ch.ExchangeDeclare(
		"tasks", // name
		"topic", // type
		true,    // durable
		false,   // auto-deleted
		false,   // internal
		false,   // no-wait
		nil,     // arguments
	)
	if err != nil {
		return nil, fmt.Errorf("ch.ExchangeDeclare %w", err)
	}

	if err := ch.Qos(
		1,     // prefetch count
		0,     // prefetch size
		false, // global
	); err != nil {
		return nil, fmt.Errorf("ch.Qos %w", err)
	}

	return &Rabbitmq{
		Conn:    conn,
		Channel: ch,
	}, nil
}

我的RABBITMQ的.env文件:

RABBITMQ_USERNAME=guest
RABBITMQ_PASSWORD=guest
RABBITMQ_HOST=rabbitmq
RABBITMQ_PORT=5672
RABBITMQ_MANAGEMENT_PORT=15672
英文:

I have 3 containers that connect to RabbitMQ: 1 container (Payment service) as the publisher, and 2 containers (Cart and Catalog services) as consumers. They are all in the same network and run using Docker Compose. Weird thing is Payment and Catalog containers have no problems connecting to RabbitMQ container while Cart service connection is always refused. Not sure what's causing this, before containerizing my services all 3 local services had no issue connecting to RabbitMQ container.

Is it possible the issue is because Cart container tried to connect before RabbitMQ in its container finished starting up?

Happened in Cart container only:

amqp.Dial dial tcp 192.168.96.3:5672: connect: connection refused

Docker compose:

cart-service:
    build: 
      context: .
      dockerfile: ./build/cart/Dockerfile
    networks:
      - shopnetwork
    ports:
      - 50052:50052
    env_file:
      - .env
    depends_on:
      - catalog-service
      - payment-service
      - redis
      - rabbitmq
  catalog-service:
    build: 
      context: .
      dockerfile: ./build/catalog/Dockerfile
    networks:
      - shopnetwork
    ports:
      - 50051:50051
    env_file:
      - .env
    depends_on:
      - mongo1
      - mongo2
      - mongo3
      - rabbitmq
  payment-service:
    build: 
      context: .
      dockerfile: ./build/payment/Dockerfile
    networks:
      - shopnetwork
    ports:
      - 50053:50053
    env_file:
      - .env
    depends_on:
      - mongo1
      - mongo2
      - mongo3
      - rabbitmq
  rabbitmq:
    image: rabbitmq:3.9.11-management
    networks:
      - shopnetwork
    ports:
      - 5672:5672
      - 15672:15672

  networks:
    shopnetwork:

My rabbitmq connection initialization code. Payment, Cart, and Catalog all use the same codes for establishing the connection (failed when dialing on line 9):

// NewRabbitMQ instantiates the RabbitMQ instances using configuration defined in environment variables.
func NewRabbitMQ() (*Rabbitmq, error) {
	username := os.Getenv(&quot;RABBITMQ_USERNAME&quot;)
	password := os.Getenv(&quot;RABBITMQ_PASSWORD&quot;)
	hostname := os.Getenv(&quot;RABBITMQ_HOST&quot;)
	port := os.Getenv(&quot;RABBITMQ_PORT&quot;)

	url := fmt.Sprintf(&quot;amqp://%s:%s@%s:%s/&quot;, username, password, hostname, port)
	conn, err := amqp.Dial(url) // &lt;----------------- FAILED HERE
	if err != nil {
		return nil, fmt.Errorf(&quot;amqp.Dial %w&quot;, err)
	}

	ch, err := conn.Channel()
	if err != nil {
		return nil, fmt.Errorf(&quot;conn.Channel %w&quot;, err)
	}

	err = ch.ExchangeDeclare(
		&quot;tasks&quot;, // name
		&quot;topic&quot;, // type
		true,    // durable
		false,   // auto-deleted
		false,   // internal
		false,   // no-wait
		nil,     // arguments
	)
	if err != nil {
		return nil, fmt.Errorf(&quot;ch.ExchangeDeclare %w&quot;, err)
	}

	if err := ch.Qos(
		1,     // prefetch count
		0,     // prefetch size
		false, // global
	); err != nil {
		return nil, fmt.Errorf(&quot;ch.Qos %w&quot;, err)
	}

	return &amp;Rabbitmq{
		Conn: conn,
		Channel: ch,
	}, nil
}

My .env for RABBITMQ:

RABBITMQ_USERNAME=guest
RABBITMQ_PASSWORD=guest
RABBITMQ_HOST=rabbitmq
RABBITMQ_PORT=5672
RABBITMQ_MANAGEMENT_PORT=15672

答案1

得分: 1

"guest"用户只能从本地主机连接。

因此,我们需要添加一个配置文件,以允许来自rabbitmq容器外部的guest用户访问。

rabbitmq.config的内容如下:

[
 {rabbit,
  [
   {loopback_users, []},
  ]}
].

并将配置文件拉取到rabbitmq容器中:

  rabbitmq:
    image: rabbitmq:3.9.11-management
    networks:
      - shopnetwork
    ports:
      - 5672:5672
      - 15672:15672
    volumes:
      - ./rabbitmq.config:/etc/rabbitmq/rabbitmq.config

  • 参考 - Rabbitmq文档
  • 参考 - Michiel van Oudheusden的博客文章
英文:

"guest" user can only connect from localhost.

So we need to add a config file to enable the guest user access from outside rabbitmq container.

The contents of the rabbitmq.config:

[
 {rabbit,
  [
   {loopback_users, []},
  ]}
].

and pull the config to rabbitmq container:

  rabbitmq:
    image: rabbitmq:3.9.11-management
    networks:
      - shopnetwork
    ports:
      - 5672:5672
      - 15672:15672
    volumes:
      - ./rabbitmq.config:/etc/rabbitmq/rabbitmq.config

huangapple
  • 本文由 发表于 2021年12月29日 22:20:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/70520683.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定