我应该如何构造docker化的RabbitMQ?

我正尝试将我们的整体PHP Symfony应用程序迁移到一个更具可扩展性的Docker解决scheme。 应用程序和RabbitMQ之间有一些通信,我使用docker-compose将所有的容器,在这种情况下,应用程序和RabbitMQ服务器。

围绕这个话题进行了很多讨论,一个容器应该只产生一个stream程, Docker的最佳实践在这一点上有些模糊:

虽然这个口头禅的意图很好,但是每个容器只能有一个操作系统进程并不一定是真的。 除了容器现在可以用init进程产生的事实以外,一些程序可能会自己产生额外的进程。

为每个RabbitMQ使用者创build一个单独的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(和其他人的“构build脚本”(和其他人一样))。

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

还是应该将它们放在应用程序容器的背景中?

我会分享我的经验,所以认真思考。

消费者必须在一个独立的容器中运行一个Web应用程序。 消费者容器像这样运行一个进程pipe理器。 它的责任是产生一些儿童消费者处理器,如果他们退出重新启动它们,重新加载SIGUSR1信号,在SIGTERM上正确closures它们。 如果主进程存在,整个容器也存在。 对于这种情况,你可能会有一个警察像总是重新启动。 以下是这个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); 

容器configuration如下所示:

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

我可以以某种方式自动执行“添加新消费者”,这样每次从代码中添加新消费者时,我都不需要编辑Docker(和其他人的“构build脚本”(和其他人一样))。

不幸的是,RabbitMQ捆绑队列pipe理还有很多不足之处。 默认情况下,您必须为每个队列运行一个命令。 如果有100个队列,则需要100个进程,每个队列至less有一个进程。 有一种方法来configuration多队列使用者,但需要完全不同的设置。 顺便说一下,排队会好很多。 你可以运行一个命令来一次消耗所有的队列。 --queue命令选项允许做更准确的调整。

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

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

还是应该将它们放在应用程序容器的背景中?

我build议至less有两个应用程序容器。 一个运行一个web服务器并提供HTTP请求,另一个运行队列消费者。