Подтвердить что ты не робот

Symfony: пользовательский дескриптор сохранения сеанса Максимальное время выполнения

Я использую обработчик пользовательского сеанса Symfony. Он отлично работает, когда я устанавливаю сеанс в первый раз, но когда я обновляю страницу. Страница будет продолжать загружаться, и через 30 секунд, которая max_execution_time определена в php.ini, отображаются ошибки. Чтобы настроить пользовательский дескриптор сохранения, я создал таблицу сеансы в базе данных с храповым механизмом. Структура и данные в таблице:

Data and Structure of Sessions Table

Теперь script в верхней части страницы выглядит так, чтобы инициализировать обработчик пользовательского сохранения:

<?php 

ini_set('session.auto_start', false);

use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler;

    require dirname(__DIR__) . '/vendor/autoload.php';

    $pdo = new \PDO('mysql:host=localhost;dbname=ratchet', 'root', '');
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $storage = new NativeSessionStorage(array(), new PdoSessionHandler($pdo)); // Here when PdoSessionHandler class is initialized again on refreshing it locks the page there
    $session = new Session($storage);

    $session->start();

    $username = $session->get('username');

Ошибки, вызванные PHP script для строки 153:

Errors

Строка 153 - это оператор следующего метода, который выполняет и считывает значение сеанса из базы данных.

private function doRead($sessionId)
{
    $this->sessionExpired = false;

    if (self::LOCK_ADVISORY === $this->lockMode) {
        $this->unlockStatements[] = $this->doAdvisoryLock($sessionId);
    }

    $selectSql = $this->getSelectSql();
    $selectStmt = $this->pdo->prepare($selectSql);
    $selectStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR);
    $selectStmt->execute(); // Line 153

Что-то сломалось в компоненте framework, или я чего-то не хватает? Я следил за документацией. Я не могу найти ничего нового или добавленного мной.

Добавление

В дополнение к инициализации сеанса в веб-приложении, я инициализирую сеанс symfony в моем server script, потому что он необходим для присоединения одного и того же объекта сеанса к каждому соединению. Следует отметить:

  • Приложение работает отлично для первой попытки.
  • Чат-сервер работает по назначению. Он никогда не выдает ошибку.
  • Когда страница, в которой я подключаюсь к серверу websocket, обновляется, она остается в состоянии загрузки в течение 30 секунд. Затем возникают ошибки.
  • То же самое происходит и в других браузерах. Как и это позволит установить соединение, но когда я обновлюсь........ См. Выше: D
4b9b3361

Ответ 1

Закрывается ли сеанс при отключении websocket? Если нет, он сохраняет блокировку записи сеанса и не позволяет входящему запросу продолжить сеанс. Начальная загрузка страницы работает, потому что websocket поднимает сеанс, когда загрузка страницы завершена.

Ответ 2

Вы упомянули, что:

Я инициализирую сеанс symfony на моем сервере script, а

Вызывает ли это также вызов new NativeSessionStorage?

Я думаю, что вы создаете по существу два обработчика сеанса, но PHP знает только об одном и, таким образом, только закрывает соединение с базой данных/снимает блокировку базы данных для одного из них. Позвольте мне посмотреть, могу ли я объяснить это ясно. Каждый раз, когда вы создаете экземпляр NativeSessionStorage, класс регистрирует sessionHandler (обработчик сеанса pdo в вашем случае) с php через session_set_save_handler, который вы можете увидеть в коде NativeSessionStorage здесь.

Когда PHP прекращает выполнение, он вызывает метод PdoSessionHandler->close(). Однако, поскольку у вас есть два экземпляра, и php имеет только один зарегистрированный в качестве обработчика сеанса, его замыкающий, но не другой. Что блокирует базу данных. Основываясь на вашем описании, я думаю, что это может быть вашей проблемой. Вы должны легко проверить это, явно вызвав Session->save() попробуйте сделать это явно в своем приложении и на сервере, чтобы узнать, не больше ли вы получите заблокированную ошибку.

Надеюсь, это поможет!