所以,这是一个安静的特定情况,但我还是会尝试。我有一个Symfony网站和一个Ratchet websocket应用程序在同一台服务器上运行。我想分享交响乐会话数据,如下所述: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,之后打开并想要访问会话数据的任何 websocket 连接都会导致General error: 2006 MySQL server has gone away
。
对于 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 上遇到了类似的问题:https://github.com/GeniusesOfSymfony/WebSocketBundle
我们使用PDOSessionHanlder通过应用程序中的会话对用户进行身份验证,经过8个小时的"等待",我们在尝试登录应用程序时遇到了相同的MySQL错误。
我们创建了一个"定期服务"(使用 IO 循环每 x 秒运行一次的函数)。https://github.com/GeniusesOfSymfony/WebSocketBundle/blob/master/Resources/docs/PeriodicSetup.md
我们在定期服务中注入了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>
然后在每个"滴答"(每 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';
}
好吧,您可以注入记录器服务并将此"ticks"和结果记录到dev.log或prod.log。这 8 小时来自您的 my.ini 或 .cnf 的wait_timeout。确保每 X 小时运行一次"tick",其中 X 小于 mysql 配置中的超时值。运行 SELECT 语句后,计时将重置为 8 小时。
也许我会帮你?:)
嗯,是的,我们首先有了 ping(); 的解决方案。您也可以在每个"刻度"中运行此代码段。只需注入实体管理器服务 ;-)