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

时间:2019-05-23 17:54:15

标签: python docker docker-compose rabbitmq pika

所以我的目标是要有几个使用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)中创建使用者。

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'后,信息获取日志也会出现在Rabbitmq-server日志之前。

4 个答案:

答案 0 :(得分:1)

通常错误消息包含其他状态-例如:

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-worker的角度来看,它是同样的问题。


您可以通过以下方法解决#2中提到的运行时相关性问题:

A)客户端中有重试逻辑-考虑使用plugginsShoval之类的Federation

B)如果问题的原因是#2-您可以使用restart_policy选项,并且在重试几次后连接将成功。

C)使用wait-for-itdockerize或与sh兼容的wait-for之类的工具。
这些是小的包装脚本,您可以将其包含在应用程序的映像中,以轮询给定的主机和端口,直到它接受TCP连接为止。在here中了解更多信息。

D)执行docker-compose up rabbitmq-server,仅在服务就绪后才执行其他服务。

E)在worker执行命令中使用时间间隔(例如sleep 10)(我不推荐这种方法)。


关于Docker-Compose docsdepends_on

使用depends_on时需要注意以下几点:

depends_on不会等待db和redis处于“就绪”状态 启动网络-仅在启动之前。如果您需要等待 要准备好服务,请参阅控制启动顺序以获取更多信息。 这个问题和解决它的策略。
版本3不再 支持depends_on的条件形式。
depends_on选项是 在群模式下使用版本3 Compose部署堆栈时忽略 文件。

答案 1 :(得分:0)

尝试将主机更改为rabbitmq-server-

class Rabbit:
    host = 'rabbitmq-server'
    userid = 'test'

答案 2 :(得分:0)

主机必须是您在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'))

答案 3 :(得分:0)

我也遇到了这个问题。关键是,pika库在没有任何域(例如纯rabbitmq)的情况下无法理解这类主机名。

因此,您可以向RabbitMQ撰写服务添加主机别名,例如,我将主机更改为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

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