所以,这是一个安静的特定情况,但无论如何我都会尝试。我有一个 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/