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

标签 php mysql symfony session pdo

所以,这是一个安静的特定情况,但无论如何我都会尝试。我有一个 Symfony 网站和一个 Ratchet websocket 应用程序在同一服务器上运行。我想分享 symphony session 数据,如下所述:http://socketo.me/docs/sessions 。除了我想使用 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 wait_timeout 和 Interactive_timeout,并且之后打开并想要访问 session 数据的任何 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 连接,因此这在访问任何 session 数据时没有帮助。那么问题是有没有办法让Symfony PDOSessionHandler在连接超时时重新连接数据库?对我来说,这似乎是 PDO session 处理程序中应该非常标准的功能......

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

最佳答案

我们在 PDOSessionHandler 和 GOSWebsocketBundle 上也遇到了类似的问题: https://github.com/GeniusesOfSymfony/WebSocketBundle

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

我们创建了一个“定期服务”(通过 IO 循环每 x 秒运行一次的函数。) https://github.com/GeniusesOfSymfony/WebSocketBundle/blob/master/Resources/docs/PeriodicSetup.md

我们在定期服务中注入(inject)了 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>

然后在定期服务中,我们在每个“Tick”(每 X 秒)上使用 PDO 服务运行查询:

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';
    }

你可以注入(inject)一个记录器服务并将这个“ticks”和结果记录到 dev.log 或 prod.log 中。 8 小时来自 my.ini 或 .cnf 中的 wait_timeout。 确保每 X 小时运行一次“tick”,其中 X 小于 mysql 配置中的超时值。运行 SELECT 语句后,超时将重置为 8 小时。

也许我可以帮助你? :)

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

关于php - Symfony PDOSessionHandler 重新连接到 Ratchet websocket 服务器的 MySQL 数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35726259/

相关文章:

php - 提取数据 PHP 字符串

symfony - "Multiple Upload"与 Symfony 3 上的 VichUploaderBundle

javascript - 使用 TWIG 中 JS 变量的参数生成 url

php mysql 使用 concat 连接表

php - 解析由 html 表单发布的 php 中的数组

PHP语法问题

mysql - 如何从总和列表(3个表)中获取最高的x值 - MySQL

mysql - mybatis 生成器 "Column name pattern can not be NULL or empty"

mysql - MySQL 中的 CHECK 约束不起作用

Symfony LTS : how to upgrade from 2. 8 到 3.4?