我应该如何构建dockerized RabbitMQ?

时间:2017-07-05 12:42:44

标签: symfony docker rabbitmq docker-compose amqp

我正在尝试使用Docker将我们的单片PHP Symfony应用程序迁移到更具可伸缩性的解决方案。应用程序和RabbitMQ之间有一些通信,我使用docker-compose来启动所有容器,在本例中是app和RabbitMQ服务器。

围绕这个主题有很多讨论,一个容器应该只生成一个进程,而Docker best practices在这一点上有些模糊:

  

虽然这个口头禅具有良好的意图,但并不一定如此   每个容器应该只有一个操作系统进程。在   除了现在可以使用init生成容器这一事实   过程中,某些程序可能会产生自己的额外进程   一致。

为每个RabbitMQ使用者创建单独的Docker容器是否有意义?这种感觉"对"和"清洁"不要让rabbitmq服务器知道用于处理队列的语言/工具。我提出了docker-compose.yml的相关部分:

  app :
    # my php-fpm app container

  rabbitmq_server:
    container_name: sf.rabbitmq_server
    build: .docker/rabbitmq
    ports:
        - "15672:15672"
        - "5672:5672"
    networks:
      - app_network

  rabbitmq_consumer:
    container_name: sf.rabbit_consumer
    extends: app
    depends_on:
      - rabbitmq_server
    working_dir: /app
    command: "php bin/console rabbitmq:consumer test"
    networks:
      - app_network

我可以使用rabbitmq_consumer或其他在后台运行它们的方式在nohup容器中运行多个消费者。

我想我的问题是:

我可以以某种方式自动化"添加新的消费者",这样我就不必编辑"构建脚本"每次从代码中添加新的消费者时,Docker(和其他人,比如ansible)?

将RabbitMQ服务器与消费者分开是否有意义,或者我应该将Rabbit服务器与在后台运行的消费者一起使用?

或者它们应该放在应用容器的背景中吗?

1 个答案:

答案 0 :(得分:4)

我会分享我的经验,所以批判性思考它。

消费者必须在与Web应用程序不同的容器中运行。消费者容器运行流程管理器like these。它的职责是产生一些子消费者处理器,如果它们退出则重启它们,重新加载SIGUSR1信号,在SIGTERM上正确关闭它们。如果主进程存在,则整个容器也存在。对于这种情况,您可能会像警察一样重新启动。以下是consume.php脚本的外观:

<?php

// bin/consume.php
use App\Infra\SymfonyDaemon;
use Symfony\Component\Process\ProcessBuilder;

require __DIR__.'/../vendor/autoload.php';

$workerBuilder = new ProcessBuilder(['bin/console', 'enqueue:consume', '--setup-broker', '-vvv']);
$workerBuilder->setPrefix('php');
$workerBuilder->setWorkingDirectory(realpath(__DIR__.'/..'));
$daemon = new SymfonyDaemon($workerBuilder);
$daemon->start(3);

容器配置如下所示:

app_consumer:
    restart: 'always'
    entrypoint: "php bin/consume.php"
    depends_on:
      - 'rabbitmq_server'
  

我可以以某种方式自动化&#34;添加新的消费者&#34;,这样我就不必编辑&#34;构建脚本&#34;每次从代码中添加新的消费者时,Docker(和其他人,比如ansible)?

不幸的是,RabbitMQ捆绑队列管理还有很多不足之处。默认情况下,您必须为每个队列运行单个命令。如果您有100个队列,则需要100个进程,每个队列至少需要一个进程。有一种方法configure a multi-queue consumer但需要完全不同的设置。顺便说一下,enqueue做得好多了。您可以运行单个命令一次消耗所有队列。 --queue命令选项允许进行更准确的调整。

  

将RabbitMQ服务器与消费者分开是否有意义,或者我应该将Rabbit服务器与在后台运行的消费者一起使用?

RabbitMQ服务器应该在一个单独的容器中运行。我不建议添加它们将它们混合在一个容器中。

  

或者它们应该放在应用容器的背景中吗?

我建议至少拥有两个app容器。一个运行Web服务器并提供HTTP请求另一个运行队列使用者。