Php Symfony PDOSessionHandler重新连接到Ratchet websocket服务器的MySQL数据库

Php Symfony PDOSessionHandler重新连接到Ratchet websocket服务器的MySQL数据库,php,mysql,symfony,session,pdo,Php,Mysql,Symfony,Session,Pdo,所以,这是一个特殊的情况,但我还是会试试。我有一个Symfony网站和一个Ratchet websocket应用程序在同一台服务器上运行。我想共享symphony会话数据,如下所述:。除了我想使用PDOSessionHandler之外。我启动websocket服务器的代码如下所示: //prepare websocket app $pusher = $this->getContainer()->get('webSocketApp'); $loop = \React\EventLo

所以,这是一个特殊的情况,但我还是会试试。我有一个Symfony网站和一个Ratchet websocket应用程序在同一台服务器上运行。我想共享symphony会话数据,如下所述:。除了我想使用PDOSessionHandler之外。我启动websocket服务器的代码如下所示:

//prepare websocket app
$pusher = $this->getContainer()->get('webSocketApp');
$loop   = \React\EventLoop\Factory::create();

// Listen for messages from the http server
$context = new \React\ZMQ\Context($loop);
$pull = $context->getSocket(\ZMQ::SOCKET_PULL);
$pull->bind('tcp://127.0.0.1:5050'); // Binding to 127.0.0.1 means the only client that can connect is itself
$pull->on('message', array($pusher, 'onServerMessage'));

//prepare pdosessionhandler for session data
$entityManager = $this->getContainer()->get('doctrine')->getEntityManager();
$pdo = $entityManager->getConnection()->getWrappedConnection();
$dbOptions = array(
            'db_table' => 'sessions',
            'db_id_col' => 'sess_id',
            'db_data_col' => 'sess_data',
            'db_time_col' => 'sess_time',
            'db_lifetime_col' => 'sess_lifetime',
            'lock_mode'       => 0
);
$session = new PdoSessionHandler($pdo, $dbOptions);

// Set up our WebSocket server for clients wanting real-time updates
$webSock = new \React\Socket\Server($loop);
$webSock->listen(8080, '0.0.0.0'); // Binding to 0.0.0.0 means remotes can connect
$webServer = new IoServer(
    new HttpServer(
            new WsServer(
                    new SessionProvider($pusher, $session)
            )
    ),
    $webSock
);

$loop->run();
一切正常,除了在websocket服务器上8小时没有流量之后,提供给PDOSessionHandler的pdo连接会命中mysql等待超时和交互超时,并且任何随后打开并想要访问会话数据的websocket连接都会导致
一般错误:2006 mysql服务器已离开

对于websocket服务器中的任何其他数据库查询,我可以简单地运行以下代码,以便在出现错误时重新连接到数据库:

//in case the db connection is timed out (I hope this helps...)
if ($this->em->getConnection()->ping() === false) {
    $this->em->getConnection()->close();
    $this->em->getConnection()->connect();
}
但是,由于我必须在启动websocket服务器时为sessionHandler提供pdo连接,因此这在访问任何会话数据时都没有帮助。所以问题是,当连接超时时,是否有办法让Symfony PDOSessionHandler重新连接到数据库?对我来说,这似乎是PDO会话处理程序中的一个非常标准的功能


或者,是否可以直接从我的websocket应用程序(一个从命令行调用的php脚本)访问会话数据?

我们在PDOSessionHandler和GOSWebsocketBundle上遇到了类似的问题:

我们使用PDOSessionHanlder通过应用程序中的会话对用户进行身份验证,经过8个小时的“等待”,我们在尝试登录应用程序时遇到了相同的MySQL错误

我们创建了一个“定期服务”(使用IO循环每x秒运行一次函数)

我们在定期服务中注入了PDO服务:

<service id="myapp.database_reconnect.periodic" class="My\App\AppBundle\Websocket\DatabaseReconnectPeriodic">
        <argument type="service" id="doctrine.orm.entity_manager" />
        <argument type="service" id="pdo" />
        <tag name="gos_web_socket.periodic" />
    </service>
您可以注入一个记录器服务,并将这个“滴答声”和结果记录到dev.log或prod.log中。 这8个小时是从my.ini或.cnf的等待超时开始的。 确保每X小时运行一次“勾选”,其中X小于mysql配置中的超时值。运行SELECT语句后,超时将重置为8小时

也许我能帮你?:)


是的,我们首先得到了ping()的解决方案;。您也可以在每个“记号”中运行此代码段。只需注入EntityManager服务;-)

谢谢你的回答!这听起来是一个相当优雅的解决方案。最后,我通过一起绕过PDOSessionHandler并从数据库中手动获取PHPSESSID和会话数据,解决了这个问题。使用Halcyon对问题的回答,从数据库中取消会话数据字符串的序列化,这甚至没有那么多工作。
try {
        /** @var \PDOStatement $res */
        $res = $this->pdo->query('SELECT 1'); //where $this->pdo is the injected service.
        echo 'Result: ' . $res->errorCode();
    } catch (PDOException $e) {
        echo 'PDO connection lost';
    }