Laravel + Rabbit = Crontab vs Supervisor



我有一个php应用程序(laravel 5.8(,它实现了一个rabbitmq-消费者(bschmitt/laravel-amqp(
当应用程序启动时,为了控制使用者流程,还会启动一个主管流程
我的主管配置文件:

[program:message-consume]
process_name=%(program_name)s_%(process_num)02d
command=php artisan message:consume 
directory=/var/www
autostart=true
autorestart=true
numprocs=1
redirect_stderr=true
stdout_logfile=/var/www/storage/logs/supervisor.log
stopwaitsecs=3600
startretries=20

消耗命令

public function consume($routingKey)
{
Log::info("[MessagingService][consume] start consuming key: " . $ROUTING_KEY . ".*");
Amqp::consume($QUEUE_NAME, function ($message, $resolver) {
# my code...
$resolver->acknowledge($message);
}, [
'routing' => $ROUTING_KEY . '.*',
'queue' => $QUEUE_NAME,
'exchange' => $EXCHANGE,
'exchange_type' => 'topic',
'exchange_durable' => false,
'queue_force_declare' => true,
'queue_exclusive' => false,
'persistent' => true, // set true if consume forever
]);
}

一切似乎都很好,但我意识到,如果有一段时间没有消息,应用程序就会停止接收消息!

流程仍在运行,主管什么也没做
发生了什么事?我从rabbit仪表板上看到的是,没有消费者连接到该频道。

这个想法是创建一个cron脚本,每隔几分钟调用rabbitmq-api来检查队列中是否有消费者,如果有,则重新启动supervisor。

我正在与docker合作,所以我更改了startup.sh以添加cron

#!/bin/bash
supervisord
crontab /etc/cron.d/check-consumer-cron
cron -f
php-fpm

但我开始问我问题。我做得好吗?我是不是错过了什么?我需要主管吗
如果我以以下方式更改startup.sh,会发生什么变化?

#!/bin/bash
php artisan message:consume 
crontab /etc/cron.d/check-consumer-cron
cron -f
php-fpm

通过重新启动Supervisor,您从错误的一端解决了问题。主管的工作是让你的脚本继续运行,你需要理解为什么没有发生这种情况。

我相信你的问题实际上有两部分:

  1. 如果闲置时间过长,消费者将断开连接。这可能是网络超时;配置";心跳;对AMQP连接的设置可能足以使其保持活动
  2. 主管没有检测到此状态并重新启动您的消费者。这是因为它不监视用户的网络状态,只监视PHP脚本是否仍在运行。您的使用者需要一些退出PHP的代码,而不是继续等待它永远不会收到的消息

我不知道Laravel包装器,但通常情况下,消费者的工作方式是在某个地方有一个无限循环,看起来有点像:

while ( true ) {
$connection->waitForAndProcessNextMessage();
}

每当消息进入或超时时;waitForAndProcessNextMessage";方法(无论实际调用什么(将返回,此时您可以决定是继续循环,还是停止并退出脚本。您可以在那里进行状态检查,或者只查看脚本运行了多长时间:

while ( true ) {
$connection->waitForAndProcessNextMessage();
if ( ! $connection->isStillConnected() ) {
break;
}
if ( minutesSinceConsumerStarted() > 30 ) {
break;
}
}

我想回答我的问题

我做得好吗?我是不是错过了什么
我使用的包是php-amqplib之上的包装器,该包装器提供的文档有限,而且很糟糕,无法控制内部结构。当然,我无法调试和检查发生了什么。直接使用php-amqplib并遵循他们提供的示例,我再也没有遇到过这种行为。

我需要主管吗?如果我以以下方式更改startup.sh,会发生什么变化
这不是重点。

最新更新