PHP - 会话对象销毁失败
PHP - Session object destruction failed
我在 Symfony 上遇到了一个奇怪的问题:基本上有时,没有任何明显的原因,用户无法加载网页,直到我重新启动 php-fpm 或直到他更改它的 PHPSESSID
加载新会话。反正重启fpm后他的session还是正常的
同时,我收到了来自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 使用相同的会话 ID 同时调用不同的 URL 来重现该问题。当然在 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 配置,但实际上 "normal" 没有特殊设置,所以我不知道应该尝试或检查什么。有什么想法吗?
问题
终于找到问题所在了。基本上它来自 Symfony 本身,因为默认情况下它似乎也在 Symfony/Component/HttpFoundation/Session/Storage/Handler/StrictSessionHandler.php
中实现了某种 garbage collection logic
public function gc($maxlifetime)
{
return $this->handler->gc($maxlifetime);
}
如果 /var/lib/php/sessions/
目录属于 php.ini
中定义的同一用户,或者如果它具有 read 权限,这将不是问题,但是默认该目录属于 root
用户且不可读(因此无法列出文件)。当 Symfony 尝试在当前会话处理程序上调用垃圾收集器时,这会导致异常。
解决方案
有两种解决方法:设置
session:
gc_probability: ~
在 Symfony config.yml
中或添加 read 权限到 PHP 会话目录(或最终使用 php.ini
中定义的相同更改相关用户).希望它能对某人有所帮助。
我在 Symfony 上遇到了一个奇怪的问题:基本上有时,没有任何明显的原因,用户无法加载网页,直到我重新启动 php-fpm 或直到他更改它的 PHPSESSID
加载新会话。反正重启fpm后他的session还是正常的
同时,我收到了来自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 使用相同的会话 ID 同时调用不同的 URL 来重现该问题。当然在 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 配置,但实际上 "normal" 没有特殊设置,所以我不知道应该尝试或检查什么。有什么想法吗?
问题
终于找到问题所在了。基本上它来自 Symfony 本身,因为默认情况下它似乎也在 Symfony/Component/HttpFoundation/Session/Storage/Handler/StrictSessionHandler.php
public function gc($maxlifetime)
{
return $this->handler->gc($maxlifetime);
}
如果 /var/lib/php/sessions/
目录属于 php.ini
中定义的同一用户,或者如果它具有 read 权限,这将不是问题,但是默认该目录属于 root
用户且不可读(因此无法列出文件)。当 Symfony 尝试在当前会话处理程序上调用垃圾收集器时,这会导致异常。
解决方案
有两种解决方法:设置
session:
gc_probability: ~
在 Symfony config.yml
中或添加 read 权限到 PHP 会话目录(或最终使用 php.ini
中定义的相同更改相关用户).希望它能对某人有所帮助。