使用docker-compose在Docker容器之间发送RabbitMq消息

7
我的目标是有几个容器使用rabbitmq消息相互交互(rabbitmq服务器在单独的容器中),因此需要编写一个rabbit.py文件。
class Rabbit:
    host = 'rabbitmq-host'
    userid = 'test'
    password = 'test'


class Consumer(Rabbit):

    def __init__(self, exchange_name):
        self.exchange_name = exchange_name
        self.connection = None
        try:
            credentials = pika.PlainCredentials(self.userid, self.password)
            params = pika.ConnectionParameters(self.host, 5672, '/', credentials)
            self.connection = pika.BlockingConnection(params)
        except Exception as ex:
            print(ex)
            if self.connection is not None and self.connection.is_open:
                self.connection.close()
            raise ex

        self.channel = self.connection.channel()

证书测试:测试存在,我重新检查了。

然后从另一个文件(main.py)创建了消费者(Consumer)。

c = Consumer('media')

docker-compose.yml

version: '3'
services:

rabbitmq-server:
  image: "rabbitmq:3-management"
  hostname: "rabbitmq-host"
  environment:
    RABBITMQ_ERLANG_COOKIE: "SWQOKODSQALRPCLNMEQG"
    RABBITMQ_DEFAULT_USER: "test"
    RABBITMQ_DEFAULT_PASS: "test"
    RABBITMQ_DEFAULT_VHOST: "/"
  ports:
    - "15672:15672"
    - "5672:5672"
  labels:
    NAME: "rabbitmq1"


info-getter:
  build: ./info-getter
  depends_on:
    - rabbitmq-server
  tty: true
  ports:
    - "3000:3000"

在测试时,我在容器中运行rabbitmq服务器,但应用程序来自本地机器,一切正常,但当我执行'docker-compose up'时,出现以下异常:

info-getter_1      | 
info-getter_1      | Traceback (most recent call last):
info-getter_1      |   File "main.py", line 10, in <module>
info-getter_1      |     c = Consumer('media')
info-getter_1      |   File "libs/rabbit.py", line 27, in __init__
info-getter_1      |     raise ex
info-getter_1      |   File "libs/rabbit.py", line 22, in __init__
info-getter_1      |     self.connection = pika.BlockingConnection(params)
info-getter_1      |   File "/usr/local/lib/python3.6/site-packages/pika/adapters/blocking_connection.py", line 360, in __init__
info-getter_1      |     self._impl = self._create_connection(parameters, _impl_class)
info-getter_1      |   File "/usr/local/lib/python3.6/site-packages/pika/adapters/blocking_connection.py", line 451, in _create_connection
info-getter_1      |     raise self._reap_last_connection_workflow_error(error)
info-getter_1      | pika.exceptions.AMQPConnectionError
services_info-getter_1 exited with code 1

我错在哪里?

此外,我想补充的是,即使我已经指定了 'depends_on',但在运行 'docker-compose up' 后,info-getter 日志会出现在 rabbitmq-server 日志之前。

4个回答

4
主机名需要是你在docker-compose.yml中定义的名称:
my-worker:
    image: my-worker-image
    restart: always
    depends_on:
        - my-rabbitmq
my-rabbitmq:
    image: rabbitmq:management
    ports:
    - 5672:5672
    - 15672:15672

然后在你的消费者(Python)中:

connection = pika.BlockingConnection(pika.ConnectionParameters('my-rabbitmq'))

2
我也遇到了这个问题。关键在于 pika 库不理解没有任何域名的主机名,例如普通的 rabbitmq
因此,您可以为您的 RabbitMQ compose 服务添加一个主机别名,例如,我将主机更改为 rabbitmq.com,然后它就开始工作了:
  rabbitmq:
    image: rabbitmq:3.8.3-management
    domainname: rabbitmq.com
    ports:
      - 5672:5672   # The standard AMQP protocol port
      - 15672:15672 # HTTP management UI

使用方法如下:connection = pika.BlockingConnection(pika.ConnectionParameters(host="rabbitmq.com"))

我也尝试将主机更改为rabbitmq.local,但这也没有起作用 :)

另一个可能的解决方案是将应用程序服务的主机网络用于连接(因为您已经将Rabbit端口公开到了主机)。

info-getter:
  build: ./info-getter
  depends_on:
    - rabbitmq-server
  tty: true
  ports:
    - "3000:3000"
  network_mode: host

在这种情况下,您应该在pika连接中将localhost设置为主机值。

2
通常错误信息包含额外的状态 - 例如: pika.exceptions.AMQPConnectionError: 连接到 :5672 失败:[Errno 111] 拒绝连接
这个错误通常是由于RabbitMQ的工作进程/客户端无法连接到RabbitMQ服务器引起的。
这可能是由于多种原因造成的 - 我会列出其中的一些:
1)RabbitMQ服务器的IP地址没有正确指定。
它可能没有作为环境变量传递(这就是为什么在代码中添加检查很重要)。
当使用时,RabbitMQ服务器的IP应该被替换为服务DNS(即docker-compose.yml文件中服务的名称或如果指定了hostname属性,则为其值)。
2)RabbitMQ的工作者/客户端在RabbitMQ服务器准备好之前尝试访问它。
请注意,depend_on只表示服务之间的依赖关系,并等待服务启动而不是就绪
因此,您不能通过添加以下内容来依赖它:

  depends_on:
    - rabbitmq-server

由于RabbitMQ服务器服务引导阶段需要时间。
有关depend_on命令,请参见下面的参考文献。
请参见我提供的解决此运行时依赖性问题的解决方案如下:

3)主机上已经运行了一个使用5672端口的RabbitMQ服务器服务。在这种情况下,当您尝试启动RabbitMQ服务器服务时,您将收到明确的错误,但从RabbitMQ工作程序的角度来看,这是相同的问题。


你可以通过以下方式解决#2提到的运行时依赖问题:
A)在客户端中添加重试逻辑-考虑使用像pluggins,如ShovalFederation这样的插件。
B)如果问题的原因是#2-您可以使用restart_policy选项,在几次重试后连接将成功。
C) 使用工具,例如wait-for-itdockerize或兼容sh的wait-for。这些是小型包装脚本,您可以将它们包含在应用程序镜像中,以轮询给定的主机和端口,直到它接受TCP连接。在此处阅读更多信息。
D) 执行docker-compose up rabbitmq-server,并且只有在服务准备就绪后才执行其他服务。
E) 在工作进程执行命令中使用时间间隔(例如sleep 10)(我不建议使用此方法)。
关于 Docker-Compose 文档 中的 depends_on
在使用 depends_on 时需要注意以下几点:

depends_on 在启动 web 之前不会等待 db 和 redis 准备好,只是等它们被启动。如果您需要等待服务准备就绪,请参阅“控制启动顺序”以获取更多信息和解决方案。
版本 3 不再支持 depends_on 的条件形式。
在使用版本 3 Compose 文件部署堆栈时,depends_on 选项将被忽略。


0
尝试将主机更改为rabbitmq-server -
class Rabbit:
    host = 'rabbitmq-server'
    userid = 'test'

尝试过,结果相同。然而,rabbitmq的Web界面告诉我主机名是rabbitmq-host。 - XpyM

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接