2016-03-01 95 views
2

所以,這是安靜的特定情況,但我會嘗試。我有一個Symfony網站和一個在同一臺服務器上運行的Ratchet websocket應用程序。我想分享這裏描述的交響樂會話數據:http://socketo.me/docs/sessions。除了我想使用PDOSessionHandler。我的代碼以啓動WebSocket的服務器如下所示:Symfony PDOSessionHandler重新連接到MySQL數據庫棘輪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(); 

一切8小時沒有WebSocket的服務器的流量後工作正常,只是,提供給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(); 
} 

然而,因爲我提供的PDO的連接sessionHandler啓動websocket服務器時,這在訪問任何會話數據時無效。所以問題是在連接超時時是否有辦法讓Symfony PDOSessionHandler重新連接到數據庫?對我來說,這似乎是一個應該在PDO會話處理程序中相當標準的功能......

或者,是否有可能直接從我的websocket應用程序(從命令行調用的php腳本)訪問會話數據? ?

回答

3

我們與PDOSessionHandler和GOSWebsocketBundle一個類似的問題: https://github.com/GeniusesOfSymfony/WebSocketBundle

我們使用PDOSessionHanlder通過我們的應用程序和8小時的「等待」後的會話來驗證用戶嘗試,當我們得到了相同的MySQL錯誤登錄我們的應用程序。

我們創建了一個「定期維護」(功能進行每x秒與IO循環運行。) 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> 

然後在每個「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'; 
    } 

那麼你可以注入一個logg er服務並將此「ticks」和結果記錄到dev.log或prod.log。 8小時來自my.ini或.cnf的wait_timeout。 確保每X小時運行「tick」,其中X小於mysql配置中的超時值。運行SELECT語句後,timout將重置爲8小時。

也許我會幫你嗎? :)

嗯,是的,我們先用ping();的解決方案。您也可以在每個「打勾」中運行此代碼段。只需注入EntityManager服務;-)

+0

感謝您的答案!這聽起來像一個相當優雅的解決方案最後,我通過繞開PDOSessionHandler並手動從數據庫中手動獲取PHPSESSID和會話數據來解決此問題。使用Halcyon對[this]的回答(http:// stackoverflow。)並沒有那麼多的工作。com/questions/530761/how-can-i-unserialize-session-data-to-an-variable-in-php)問題,用於從數據庫中解串會話數據字符串。 –