upscale / swoole-session
PHP会话与Swoole Web服务器的兼容性
2.1.0
2023-06-12 20:07 UTC
Requires
- php: >=8.0
- upscale/ext-openswoole: ^4.0||^22.0
- upscale/ext-swoole: ^4.0||^5.0
Requires (Dev)
- ext-curl: *
- phpunit/phpunit: ^9.5
- upscale/swoole-launchpad: ^2.0
README
此库实现了原生PHP会话与Swoole / Open Swoole Web服务器之间的兼容性。
功能
- 透明的会话开始/停止
- 会话ID存储在cookie或查询字符串中
- 原生或自定义会话ID生成器
- 自动会话数据持久化
- 符合PHP会话配置
安装
该库通过Composer作为依赖项安装
composer require upscale/swoole-session
用法
将请求处理中间件包装到会话装饰器中
require 'vendor/autoload.php'; use Upscale\Swoole\Session\SessionDecorator; $server = new \Swoole\Http\Server('127.0.0.1', 8080); $server->set([ // Disable coroutines to safely access $_SESSION 'enable_coroutine' => false, ]); $server->on('request', new SessionDecorator(function ($request, $response) { $_SESSION['data'] ??= rand(); $response->end($_SESSION['data']); })); $server->start();
限制
协程
PHP会话依赖于超全局变量$_SESSION
,因此与Swoole协程不兼容。当请求空闲进行异步I/O操作时,其工作进程被重新用于处理其他请求。Swoole切换调用栈上下文,但超全局变量保留在协程/请求之间共享的内存中。为某个请求加载的会话数据泄漏到其他请求,导致各种数据完整性问题。
为了安全使用PHP会话,请禁用协程
$server->set([ 'enable_coroutine' => false, ]);
输出
Swoole环境中禁止直接输出绕过响应实例\Swoole\Http\Response
。写入标准输出流违反了PHP会话函数的headers_sent
要求
PHP警告:session_start(): 当headers已经发送时无法启动会话
发送headers的语句会阻碍会话
echo/print
fwrite(STDOUT)
file_put_contents('php://stdout')
include 'template.phtml'
header()
setcookie/setrawcookie()
- 等等。
输出缓冲通常由模板引擎使用,以避免这种陷阱,例如
ob_start(); include $templatePhtml; $output = ob_get_clean(); $response->end($output);
警告! 在Swoole 4.5.3之前,即使启用了输出缓冲,也会使用协程发送headers。由于上述数据完整性的原因,必须禁用协程,因此这不是问题。
阻塞
并发请求容易受到会话写竞争条件的影响。PHP默认基于文件的会话存储使用文件系统锁定来避免数据损坏。具有相同会话ID的请求依次执行,阻止它们各自的工作进程从session_start()
阻塞到session_write_close()
。
专为Swoole构建的异步协程感知库