我正在尝试使用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服务器与在后台运行的消费者一起使用?
或者它们应该放在应用容器的背景中吗?
答案 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请求另一个运行队列使用者。