我正在使用Symfony 4 messenger组件的辅助程序。
这个工人是
要在Symfony上配置这个辅助角色,我已经这样做了(中间件很重要):
// config/packages/framework.yaml
framework:
messenger:
buses:
command_bus:
middleware:
# each time a message is handled, the Doctrine connection
# is "pinged" and reconnected if it's closed. Useful
# if your workers run for a long time and the database
# connection is sometimes lost
- doctrine_ping_connection
# After handling, the Doctrine connection is closed,
# which can free up database connections in a worker,
# instead of keeping them open forever
- doctrine_close_connection
transports:
ffmpeg:
dsn: '%env(CLOUDAMQP_URL)%'
options:
auto_setup: false
exchange:
name: amq.topic
type: topic
queues:
ffmpeg: ~
routing:
# Route your messages to the transports, for now all are AMQP messages
'App\Api\Message\AMQPvideoFFMPEG': ffmpeg
## Handle multiple buses ? https://symfony.com/doc/current/messenger/multiple_buses.html
## When queries and command should be distinguished
然后,为了了解可能导致此问题的原因,我尝试调试messenger,以查看中间件的配置是否正确
root@b9eec429cb54:/var/www/html# php bin/console debug:messenger
Messenger
=========
command_bus
-----------
The following messages can be dispatched:
------------------------------------------------------
App\Api\Message\AMQPvideoFFMPEG
handled by App\Api\Message\Handler\FFMPEGHandler
------------------------------------------------------
一切似乎都好吧?
那么,这怎么可能看到这一点:
送信人。错误:正在重试App\Api\Message\amqpdvideoffmpeg-重试#1。{“message”:“[object](App\Api\message\amqpvideeoffmpeg:{})”,“class”:“App\Api\message\amqpvideffmpeg”,“retryCount”:1,“错误”:“[object](条令\DBAL\Exception\ConnectionException(代码:0):驱动程序中发生异常:SQLSTATE[HY000][2002]连接在/var/www/html/vendor/Doctrine/DBAL/lib/Doctrine/DBAL/driver/AbstractMySQLDriver.php:93,条令\DBAL\driver\PDOException(代码:2002):SQLSTATE[HY000][2002]连接在/var/www/html/vendor/doctor/dbal/lib/doctor/dbal/Driver/PDOConnection处超时。php:31,pdoception(代码:2002):SQLSTATE[HY000][2002]连接在/var/www/html/vendor/doctor/dbal/lib/doctor/dbal/Driver/PDOConnection处超时。php:27)“}[]
我完全迷路了,我错过什么了吗?
这种情况有时会发生,但大多数时候都有效,我想当我的工作人员失去与数据库的连接时会发生这种错误,特别是如果ffmpeg处理持续7分钟或更长时间,但这应该通过ping和紧密连接的中间件来避免。所以我不太清楚这里有什么问题。
读了我中间件的代码特别是这个块
https://github.com/symfony/symfony/blob/4.4/src/Symfony/Bridge/Doctrine/Messenger/DoctrinePingConnectionMiddleware.php
class DoctrinePingConnectionMiddleware extends AbstractDoctrineMiddleware
{
protected function handleForManager(EntityManagerInterface $entityManager, Envelope $envelope, StackInterface $stack): Envelope
{
$connection = $entityManager->getConnection();
if (!$connection->ping()) {
$connection->close();
$connection->connect();
}
if (!$entityManager->isOpen()) {
$this->managerRegistry->resetManager($this->entityManagerName);
}
return $stack->next()->handle($envelope, $stack);
}
}
我们可以看到我的处理程序在连接打开后被调用。我认为这种行为应该有效,但是FFMPEG可以在很长一段时间内使用相同的RabbitMQ消息。因此,我的处理程序的最后一步,将一些东西插入到数据库可以提供一个mySQL已经离开错误,或连接超时。
这就是为什么,我将这个片段放入一个方法中,而不调用处理程序,只调用与doctrine connect相关的代码,然后在插入数据库之前调用它,如下所示:
public function __invoke(AMQPvideoFFMPEG $message)
{
// reset connection if not found
$this->processService->testConnection();
$process = $this->processService->find($message->getProcess());
$this->renderServcie->updateQueue($process->getQueue(), "processing");
// some other stuff
}
其中testConnection()方法是
/**
* Reconnect if connection is aborted for some reason
*/
public function testConnection()
{
$connection = $this->entityManager->getConnection();
if (!$connection->ping()) {
$connection->close();
$connection->connect();
}
}
但在那之后我又做了一个实验
不支持重置非惰性管理器服务。将“doctrine.orm.default_entity_manager”服务设置为lazy,并要求在编写器中使用“symfony/proxy manager桥”。而不是json文件。
安装“symfony/proxy-manager桥”后,错误消失了。
到目前为止,没有出现连接超时的情况。等等看。
在执行任何插入操作之前,只需断开:
public function handle(…)
{
// your time-consuming business logic
// disconnect if needed
if (!$this->entityManager->getConnection()->ping()) {
$this->entityManager->getConnection()->close();
}
// save your work
$this->entityManager->flush();
}