我应该如何构建 dockerized RabbitMQ?
How should I structure dockerized RabbitMQ?
我正在尝试将我们的整体 PHP Symfony 应用程序迁移到具有 Docker 的更具可扩展性的解决方案。应用程序和 RabbitMQ 之间存在一些通信,我使用 docker-compose
启动所有容器,在本例中是应用程序和 RabbitMQ 服务器。
关于一个容器应该只生成一个进程的话题有很多讨论,Docker best practices 对这一点有些含糊:
While this mantra has good intentions, it is not necessarily true that
there should be only one operating system process per container. In
addition to the fact that containers can now be spawned with an init
process, some programs might spawn additional processes of their own
accord.
为每个 RabbitMQ 消费者创建一个单独的 Docker 容器是否有意义?感觉 "right" 和 "clean" 不让 rabbitmq 服务器知道用于处理队列的 language/tools。我想出了(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
或其他方式 运行 在后台将它们连接起来。
我想我的问题是:
我能以某种方式使 "adding a new consumer" 自动化吗,这样我就不必在每次添加新消费者时都编辑 Docker 的 "build script"(以及其他人,如 ansible)来自代码?
将 RabbitMQ 服务器与消费者分开是否有意义,或者我应该在后台使用消费者 运行ning 的 Rabbit 服务器吗?
还是应该放在应用容器的后台?
我将分享我的经验,请认真思考。
消费者必须 运行 在与网络应用程序不同的容器中。消费者容器 运行 是一个进程管理器 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'
Can I somehow automate the "adding a new consumer", so that I would not have to edit the "build script" of Docker (and others, like ansible) every time the new consumer is added from the code?
不幸的是,RabbitMQ 捆绑队列管理还有很多不足之处。默认情况下,您必须 运行 每个队列一个命令。如果您有 100 个队列,则需要 100 个进程,每个队列至少一个。有一种方法可以 configure a multi-queue consumer 但需要完全不同的设置。顺便说一下,enqueue 做得更好。您可以 运行 一次从所有队列中使用单个命令。 --queue
命令选项允许进行更准确的调整。
Does it make sense to separate RabbitMQ server from Consumers, or should I use the Rabbit server with consumers running in the background?
RabbitMQ 服务器应该 运行 在一个单独的容器中。我不建议将它们添加到一个容器中。
Or should they be placed in the background of the app container?
我建议至少有两个应用程序容器。一个 运行 是 Web 服务器并为 HTTP 请求提供服务,另一个 运行 是队列消费者。
我正在尝试将我们的整体 PHP Symfony 应用程序迁移到具有 Docker 的更具可扩展性的解决方案。应用程序和 RabbitMQ 之间存在一些通信,我使用 docker-compose
启动所有容器,在本例中是应用程序和 RabbitMQ 服务器。
关于一个容器应该只生成一个进程的话题有很多讨论,Docker best practices 对这一点有些含糊:
While this mantra has good intentions, it is not necessarily true that there should be only one operating system process per container. In addition to the fact that containers can now be spawned with an init process, some programs might spawn additional processes of their own accord.
为每个 RabbitMQ 消费者创建一个单独的 Docker 容器是否有意义?感觉 "right" 和 "clean" 不让 rabbitmq 服务器知道用于处理队列的 language/tools。我想出了(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
或其他方式 运行 在后台将它们连接起来。
我想我的问题是:
我能以某种方式使 "adding a new consumer" 自动化吗,这样我就不必在每次添加新消费者时都编辑 Docker 的 "build script"(以及其他人,如 ansible)来自代码?
将 RabbitMQ 服务器与消费者分开是否有意义,或者我应该在后台使用消费者 运行ning 的 Rabbit 服务器吗?
还是应该放在应用容器的后台?
我将分享我的经验,请认真思考。
消费者必须 运行 在与网络应用程序不同的容器中。消费者容器 运行 是一个进程管理器 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'
Can I somehow automate the "adding a new consumer", so that I would not have to edit the "build script" of Docker (and others, like ansible) every time the new consumer is added from the code?
不幸的是,RabbitMQ 捆绑队列管理还有很多不足之处。默认情况下,您必须 运行 每个队列一个命令。如果您有 100 个队列,则需要 100 个进程,每个队列至少一个。有一种方法可以 configure a multi-queue consumer 但需要完全不同的设置。顺便说一下,enqueue 做得更好。您可以 运行 一次从所有队列中使用单个命令。 --queue
命令选项允许进行更准确的调整。
Does it make sense to separate RabbitMQ server from Consumers, or should I use the Rabbit server with consumers running in the background?
RabbitMQ 服务器应该 运行 在一个单独的容器中。我不建议将它们添加到一个容器中。
Or should they be placed in the background of the app container?
我建议至少有两个应用程序容器。一个 运行 是 Web 服务器并为 HTTP 请求提供服务,另一个 运行 是队列消费者。