PHP - 会话对象销毁失败

3
我在Symfony上遇到了一个奇怪的问题:有时候用户无法加载网页,直到我重新启动php-fpm或者他更改了PHPSESSID加载新的会话。然而,重启fpm后他的会话仍然正常工作。
同时,我从PHP收到了2个警告:
PHP Warning: session_start(): Session object destruction failed in /home/unix/releases/1/vendor/symfony/symfony/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php on line 145
PHP Warning: session_start(): Failed to decode session object. Session has been destroyed in /home/unix/releases/1/vendor/symfony/symfony/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php on line 145
需要注意的是,我们谈论的是一个私人网站,最多只有2-3个用户同时使用,但即使只有1个用户在浏览也可能发生这种情况。
当前设置为:
Debian 9.4 stretch 4.14.0-0.bpo.3-amd64 php-fpm 7.1.15
Symfony 3.4.4
我可以使用apache ab并发调用不同的URL,使用相同的会话ID来重现此问题。当然,在N请求后我会超时。
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
apr_pollset_poll: The timeout specified has expired (70007)
Total of 872 requests completed

我现在正在尝试检查 PHP 配置,但实际上它是相当“正常”的,没有特殊设置,所以我不知道应该尝试或检查什么。有什么想法吗?


你会在session中保存实体吗?我曾经遇到过类似的问题,其中session变得太大,无法再解码。尝试保存ID而不是实体。 - Vyctorya
也许是您达到了最大变量允许值(https://dev59.com/u3VC5IYBdhLWcg3wrDJd#12916515)或最大会话大小(https://dev59.com/YG445IYBdhLWcg3w5OEH#4649934)? - Vyctorya
此外,您可以尝试使用PdoSessionHandler将会话存储在数据库中 - Evgeny Ruban
此外,您可以尝试将PHP升级到最新的稳定版本-7.2.x。在7.1中存在一些类似问题。 - Evgeny Ruban
你在 php.ini 中的 session.auto_start 里设置了什么? - Evgeny Ruban
显示剩余4条评论
1个回答

3

问题

最终我找到了问题所在。基本上它来自于Symfony本身,因为默认情况下似乎也实现了一种类似于垃圾回收逻辑的东西,在Symfony/Component/HttpFoundation/Session/Storage/Handler/StrictSessionHandler.php中。

public function gc($maxlifetime)
{
    return $this->handler->gc($maxlifetime);
}

如果/var/lib/php/sessions/目录属于在php.ini中定义的同一用户或具有读取权限,则不会出现问题,但默认情况下该目录属于root用户且不可读(因此无法列出文件)。这会导致当Symfony尝试在当前会话处理程序上调用垃圾回收器时出现异常。

解决方案

有两个解决方案:设置

session:
    gc_probability: ~

在Symfony中,可以通过修改config.yml文件或者给PHP会话目录添加read权限(或者最终使用与php.ini中定义的相同的用户)来解决问题。希望这能帮到某些人。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接