Skip to content

超全局数组 $_SESSION

$_SESSION 是什么

GatewayWorker 中的超全局数组 $_SESSION 和 PHP 自身的 $_SESSION 功能基本相同。每个 client_id 对应一个 $_SESSION 数组, $_SESSION 数组中可以保存对应客户端的会话数据,对应的 client_id 的后续请求可以直接使用这个数组中的数据,而不用去反复读取存储。

$_SESSION 使用场景

例如客户端链接 GatewayWorker 后,需要发送验证数据让服务端验证是否合法,一般要传递一次用户名和密码数据,然后在 Gateway::onMessage($client_id, $message) 中通过查询数据库验证 $message 中的用户名密码是否正确,如果正确就可以将用户的 uid 写入到 $_SESSION 中如 $_SESSION['uid']=$uid; ,那么当这个 client_id 再次发来数据时,要判断这个客户端是否是被验证过的,就可以用 $_SESSION['uid'] 是否被设置来判断。

$_SESSION 使用注意事项

  • 使用 $_SESSION 时无需调用 session_start 等函数,可直接使用
  • $_SESSION 中无法保存资源类型的数据
  • $_SESSION 数据保存在 Gateway 进程内存中,无磁盘 IO,性能非常好
  • $_SESSION 的生命周期与 client_id 对应 socket 连接的生命周期相同,当客户端连接断开后,对应的客户端 $_SESSION 将会清除
  • GatewayWorker 中的 $_SESSION 与 WebServer (PHP-FPM/Apache 等) 中的 $_SESSION 无法互通
  • 定时器中不要直接使用 $_SESSION 变量,因为定时器运行那一刻无法确定 $_SESSION 变量里存储的值属于哪个 client_id。如果定时器里面需要获得 session,可以使用 Gateway::getSession($client_id) 获取

$_SESSION 实现原理

Gateway/Worker 中,每个客户端的 $_SESSION 数据是存储在 Gateway 进程内存中的,每次 Gateway 进程转发消息给 BusinessWorker 进程时,都会顺便携带上对应客户端的 $_SESSION 数据给 BusinessWorker 进程,这时 BusinessWorker 进程就能使用 $_SESSION 了。而当 $_SESSION 数据有更改时,BusinessWorker 会将新的 $_SESSION 数据传递给 Gateway 进程进行保存。

示例

php
class Events
{
    public static function onMessage($client_id, $data)
    {
        // data={"type":"login", "uid":"666"}
        $data = json_decode($data, true);
        // 如果没有$_SESSION['uid']说明客户端没有登录
        if(!isset($_SESSION['uid']))
        {
            // 消息类型不是登录视为非法请求,关闭连接
            if($data['type'] !== 'login')
            {
                return Gateway::closeClient($client_id);
            }
            // 设置session,标记该客户端已经登录
            $_SESSION['uid'] = $data['uid'];
        }
    }

}

基于 MIT 许可发布