Symfony 4工作人员使用学说无法正常工作:SQLSTATE [HY000] [2002]连接超时

Gre*_*han 5 php symfony symfony-messenger

我正在使用带有 Symfony 4 信使组件的工作人员。

这位工人是

  • 接收消息(来自rabbitMQ)
  • 启动 ffmpeg
  • 对视频进行处理
  • 并将一些内容保存在数据库中。

为了在 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
Run Code Online (Sandbox Code Playgroud)

然后,为了了解可能导致此问题的原因,我尝试调试信使以查看中间件是否正确配置

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  
 ------------------------------------------------------ 

Run Code Online (Sandbox Code Playgroud)

一切看起来都很好,对吧?

那么怎么可能看到这个:

[2019-08-23 10:25:26] messenger.ERROR:重试 App\Api\Message\AMQPvideoFFMPEG - 重试 #1。{“消息”:“[对象](应用程序\ Api \消息\ AMQPvideoFFMPEG:{})”,“类”:“应用程序\ Api \消息\ AMQPvideoFFMPEG”,“重试计数”:1,“错误”:“[对象] (Doctrine\DBAL\Exception\ConnectionException(代码: 0): 驱动程序中发生异常: SQLSTATE[HY000] [2002] 连接超时 /var/www/html/vendor/doctrine/dbal/lib/Doctrine/DBAL /Driver/AbstractMySQLDriver.php:93,Doctrine\DBAL\Driver\PDOException(代码:2002): SQLSTATE[HY000] [2002] 连接超时 /var/www/html/vendor/doctrine/dbal/lib/Doctrine/ DBAL/Driver/PDOConnection.php:31,PDOException(代码:2002):SQLSTATE[HY000] [2002] 连接超时 /var/www/html/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection .php:27)"} []

我完全迷失了,我错过了什么吗?

有时会发生这种情况,但大多数情况下它都会起作用,我想当我的工作人员失去与数据库的连接时,特别是当 ffmpeg 处理持续 7 分钟或更长时间时,就会发生此错误,但这应该通过 ping 和关闭连接的中间件来避免。所以我不清楚这里的问题是什么。

Gre*_*han 3

在阅读了我的中间件的代码,尤其是这个块之后

\n\n

https://github.com/symfony/symfony/blob/4.4/src/Symfony/Bridge/Doctrine/Messenger/DoctrinePingConnectionMiddleware.php

\n\n
class DoctrinePingConnectionMiddleware extends AbstractDoctrineMiddleware\n{\n    protected function handleForManager(EntityManagerInterface $entityManager, Envelope $envelope, StackInterface $stack): Envelope\n    {\n        $connection = $entityManager->getConnection();\n        if (!$connection->ping()) {\n            $connection->close();\n            $connection->connect();\n        }\n        if (!$entityManager->isOpen()) {\n            $this->managerRegistry->resetManager($this->entityManagerName);\n        }\n        return $stack->next()->handle($envelope, $stack);\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

我们可以看到我的处理程序在连接打开后立即被调用。\n我认为这种行为应该有效,但 FFMPEG 可以使用相同的 RabbitMQ\ 消息长时间工作。因此,我的处理程序的最后一步将某些内容插入数据库可能会提供 mySQL 已消失错误或连接超时。

\n\n

这就是为什么,我将这段代码片段放入一个方法中,而无需调用处理程序,仅包含与学说连接相关的代码,然后我在向数据库进行任何插入之前调用此方法,如下所示:

\n\n
public function __invoke(AMQPvideoFFMPEG $message)\n    {\n        // reset connection if not found\n        $this->processService->testConnection();\n        $process = $this->processService->find($message->getProcess());\n        $this->renderServcie->updateQueue($process->getQueue(), "processing");\n\n// some other stuff\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

其中 testConnection() 方法是

\n\n
 /**\n     * Reconnect if connection is aborted for some reason\n     */\n    public function testConnection()\n    {\n        $connection = $this->entityManager->getConnection();\n        if (!$connection->ping()) {\n            $connection->close();\n            $connection->connect();\n        }\n\n    }\n
Run Code Online (Sandbox Code Playgroud)\n\n

但在那之后我\xe2\x80\x99ve尝试了另一个问题

\n\n
\n

不支持重置非惰性管理器服务。将\n“doctrine.orm.default_entity_manager”服务设置为惰性服务,并在composer.json文件中要求\n“symfony/proxy-manager-bridge”。

\n
\n\n

安装“symfony/proxy-manager-bridge”后,错误消失了。

\n\n

到目前为止,还没有遇到连接超时的情况。等着瞧。

\n