Symfony Messenger 工作人员在 运行 处于监督之下时不会停止
Symfony messenger workers do not stop when running under supervisor
我遇到了 Symfony Messenger 组件的奇怪行为。我是按照documentation and I am issuing a messenger:stop-workers
signal on each deploy as instructed here设置的。然而,我们的系统出现了一个错误,我追溯到 Messenger 工作人员使用旧版本代码的事实。
经过更多调查,这就是我们设置中发生的情况:
- 一名工人运行,由主管管理。
- 只是为了调试这个特殊情况,我在终端中启动了一个新的 worker
app/console messenger:consume --env=prod -vv async
看看会发生什么
- 我发出停止命令
app/console messenger:stop-workers --env=prod
- 我现在希望这两个工作人员都将停止(主管将重新启动它正在处理的工作人员)。但是,这不会发生。 “调试”工人确实停止了,但主管下的 运行 什么也没做。
supervisor-managed worker 的处理时间限制为 1 小时,之后它们将停止并重新启动。我可以在 supervisord.log
中看到它运行良好。每小时都有关于进程停止和启动的日志条目。但是他们没有任何关于停止 messenger:stop-workers
命令的事情。
我正在寻找关于为什么会发生这种情况的想法。我看了worker的实现,关机信号是通过缓存发送的,但是我没有发现我们的配置有什么问题。
我 运行 遇到了类似的问题。
如您所见,为了强制停止其余消费者,该命令使用了缓存池。在我的例子中(也可能是你的),是存储在 /your_symfony_app/var/cache/{env}/pools
中的文件系统池
因此,如果您使用 Deployer 或任何其他部署系统来替换每个新部署的符号 link,您需要在文件夹 中执行命令 messenger:stop-workers
你之前的版本.
另一种选择是配置一个由所有版本共享的缓存池,例如 memcached 或 redis。
就我而言,使用 Deployer(软件仍在开发中)我已经能够通过声明这样的任务并将其放入部署主任务中来解决它:
task('messenger:stop', function () {
if (has('previous_release')) {
run('{{bin/php}} {{previous_release}}/bin/console messenger:stop-workers');
}
})->desc('Stop workers');
在我们等待更好的解决方案时,这里有一个解决此问题的方法。
只有当您的 Symfony Messenger 支持此处提交的 --failure-limit 选项时,您才能使用此解决方法:
https://github.com/symfony/symfony/pull/35453/commits/ea79206470ac3b71520a35129d36ca0d11ce4a09
通过主管启动 Messenger 总是有一个最大失败:
php bin/console messenger:consume async --failure-limit=1
在您的代码库中定义一个消息 RestartMessenger
和相应的处理程序 RestartMessengerHandler
,它只是抛出一个异常,例如 MessengerNeedsToBeRestartedException
创建一个名为 app:messenger-restart-request
的 Symfony 命令,用于调度 RestartMessenger
在您的部署脚本(bash、Ansible 或其他)中添加作为最后一步:php bin/console app:messenger-restart-request
。这将引发异常,导致 Messenger 重新启动,因为 --failure-limit=1
我遇到了 Symfony Messenger 组件的奇怪行为。我是按照documentation and I am issuing a messenger:stop-workers
signal on each deploy as instructed here设置的。然而,我们的系统出现了一个错误,我追溯到 Messenger 工作人员使用旧版本代码的事实。
经过更多调查,这就是我们设置中发生的情况:
- 一名工人运行,由主管管理。
- 只是为了调试这个特殊情况,我在终端中启动了一个新的 worker
app/console messenger:consume --env=prod -vv async
看看会发生什么 - 我发出停止命令
app/console messenger:stop-workers --env=prod
- 我现在希望这两个工作人员都将停止(主管将重新启动它正在处理的工作人员)。但是,这不会发生。 “调试”工人确实停止了,但主管下的 运行 什么也没做。
supervisor-managed worker 的处理时间限制为 1 小时,之后它们将停止并重新启动。我可以在 supervisord.log
中看到它运行良好。每小时都有关于进程停止和启动的日志条目。但是他们没有任何关于停止 messenger:stop-workers
命令的事情。
我正在寻找关于为什么会发生这种情况的想法。我看了worker的实现,关机信号是通过缓存发送的,但是我没有发现我们的配置有什么问题。
我 运行 遇到了类似的问题。
如您所见,为了强制停止其余消费者,该命令使用了缓存池。在我的例子中(也可能是你的),是存储在 /your_symfony_app/var/cache/{env}/pools
因此,如果您使用 Deployer 或任何其他部署系统来替换每个新部署的符号 link,您需要在文件夹 中执行命令 messenger:stop-workers
你之前的版本.
另一种选择是配置一个由所有版本共享的缓存池,例如 memcached 或 redis。
就我而言,使用 Deployer(软件仍在开发中)我已经能够通过声明这样的任务并将其放入部署主任务中来解决它:
task('messenger:stop', function () {
if (has('previous_release')) {
run('{{bin/php}} {{previous_release}}/bin/console messenger:stop-workers');
}
})->desc('Stop workers');
在我们等待更好的解决方案时,这里有一个解决此问题的方法。
只有当您的 Symfony Messenger 支持此处提交的 --failure-limit 选项时,您才能使用此解决方法: https://github.com/symfony/symfony/pull/35453/commits/ea79206470ac3b71520a35129d36ca0d11ce4a09
通过主管启动 Messenger 总是有一个最大失败:
php bin/console messenger:consume async --failure-limit=1
在您的代码库中定义一个消息
RestartMessenger
和相应的处理程序RestartMessengerHandler
,它只是抛出一个异常,例如MessengerNeedsToBeRestartedException
创建一个名为
app:messenger-restart-request
的 Symfony 命令,用于调度RestartMessenger
在您的部署脚本(bash、Ansible 或其他)中添加作为最后一步:
php bin/console app:messenger-restart-request
。这将引发异常,导致 Messenger 重新启动,因为--failure-limit=1