Symfony:自定义会话保存处理程序最大执行时间

2022-08-30 18:36:45

我正在使用Symfony的自定义会话处理程序。当我第一次设置会话时,但当我刷新页面时,它工作正常。页面将继续加载,在php.ini中定义的30秒后,将显示错误。为了设置自定义保存处理程序,我在棘轮数据库中创建了一个表会话。表中的结构和数据:max_execution_time

Data and Structure of Sessions Table

现在,页面顶部的脚本如下所示,用于初始化自定义保存处理程序:

<?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 脚本为第 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

框架组件中是否有东西坏了,或者我错过了什么?我已遵循文档。我找不到任何新的或自己添加的。

加法

除了在 Web 应用程序中初始化会话之外,我还在脚本中初始化 symfony 会话,因为需要将相同的会话对象附加到每个连接。需要注意的要点:server

  1. 应用程序在第一次尝试时工作正常。
  2. 聊天服务器按预期工作。它永远不会引发错误。
  3. 刷新连接到 websocket 服务器的页面时,它将保持加载状态 30 秒。然后发生错误。
  4. 在其他浏览器中也会发生同样的情况。就像它会让连接建立,但当我刷新时........见上文:D

答案 1

你提到:

我也在我的服务器脚本中初始化symfony会话

这也叫?new NativeSessionStorage

我认为正在发生的事情是,您基本上创建了两个会话处理程序,但PHP只知道一个,因此只关闭数据库连接/解除其中一个的数据库锁定。让我看看我是否可以清楚地解释。每次实例化 NativeSessionStorage 时,该类都会使用 php 注册 sessionHandler(在本例中为 pdo 会话处理程序),通过 php,您可以在这里的 NativeSessionStorage 代码中看到session_set_save_handler

当 PHP 停止执行时,它会调用该方法。但是,由于您有两个实例,并且php只有一个注册为会话处理程序,因此它的关闭一个而不是另一个。这将使数据库保持锁定状态。根据您的描述,我认为这可能是您的问题。你应该能够通过显式调用 try 在应用和服务器代码中显式执行此操作来轻松测试此错误,以查看是否不再收到锁定错误。PdoSessionHandler->close()Session->save()

希望这有帮助!


答案 2

当 websocket 断开连接时,会话是否正在关闭?如果不是,它将保持会话记录的锁定,并且不允许传入请求在启动会话后继续。初始页面加载工作,因为 websocket 在页面加载完成时选取会话。


推荐