连接上下文

    目录

    imi 中长连接服务(Http2、WebSocket、TCP)中使用 Imi\ConnectionContext 类对连接上下文的会话数据进行管理。在整个连接的生命周期中都有效。

    比如我们可以在客户端发送认证鉴权操作时,向连接上下文中写入当前客户端的id等信息。

    会话数据可以设置存储器,用于将会话数据保存在不同的地方,满足各种需求。

    常见使用

    use Imi\ConnectionContext;
    
    // 取值
    echo ConnectionContext::get('name');
    echo ConnectionContext::get('name', '默认值');
    
    // 赋值
    ConnectionContext::set('name', 'value');
    
    // 获取所有数据
    $array = ConnectionContext::getContext();
    
    // 使用回调并且自动加锁进行操作,回调用返回数据会保存进连接上下文
    ConnectionContext::use(function($data){
        // 本方法体会在锁中执行
        var_dump($data); // 读取数据
        $data['aaa'] = 222;
        return $data; // 写入数据,不return也可以,就是不修改
    });

    方法列表

    上下文操作可以参考(请求上下文

    /**
     * 为当前连接创建上下文.
     */
    public static function create(array $data = []): void;
    
    /**
     * 从某个连接上下文中,加载到当前上下文或指定上下文中.
     */
    public static function load(int $fromClientId, ?int $toClientId = null): void;
    
    /**
     * 销毁当前连接的上下文.
     *
     * @param int|string|null $clientId
     */
    public static function destroy($clientId = null): void;
    
    /**
     * 判断当前连接上下文是否存在.
     *
     * @param int|string|null $clientId
     */
    public static function exists($clientId = null): bool;
    
    /**
     * 获取上下文数据.
     *
     * @param mixed           $default
     * @param int|string|null $clientId
     *
     * @return mixed
     */
    public static function get(?string $name = null, $default = null, $clientId = null);
    
    /**
     * 设置上下文数据.
     *
     * @param string          $name
     * @param mixed           $value
     * @param int|string|null $clientId
     */
    public static function set(?string $name, $value, $clientId = null): void;
    
    /**
     * 批量设置上下文数据.
     *
     * @param int|string|null $clientId
     */
    public static function muiltiSet(array $data, $clientId = null): void;
    
    /**
     * 使用回调并且自动加锁进行操作,回调用返回数据会保存进连接上下文.
     *
     * @param int|string|null $clientId
     */
    public static function use(callable $callable, $clientId = null): void;
    
    /**
     * 获取一个闭包的值并将其持久化, 下次请求将直接从连接上下文中获取.
     *
     * @param int|string|null $clientId
     *
     * @return mixed
     */
    public static function remember(string $key, \Closure $closure, $clientId = null, ?string $serverName = null);
    
    /**
     * 销毁一个上下文记住的值
     */
    public static function unset(string $key): void;
    
    /**
     * 获取当前上下文.
     *
     * @param int|string|null $clientId
     */
    public static function getContext($clientId = null): array;
    
    /**
     * 绑定一个标记到当前连接.
     *
     * @param int|string|null $clientId
     */
    public static function bind(string $flag, $clientId = null): void;
    
    /**
     * 绑定一个标记到当前连接,如果已绑定返回false.
     *
     * @param int|string|null $clientId
     */
    public static function bindNx(string $flag, $clientId = null): bool;
    
    /**
     * 取消绑定.
     *
     * @param int|string $clientId
     * @param int|null   $keepTime 旧数据保持时间,null 则不保留
     */
    public static function unbind(string $flag, $clientId, ?int $keepTime = null): void;
    
    /**
     * 使用标记获取连接编号.
     *
     * @return array
     */
    public static function getClientIdByFlag(string $flag);
    
    /**
     * 使用标记获取连接编号.
     *
     * @param string[] $flags
     */
    public static function getClientIdsByFlags(array $flags): array;
    
    /**
     * 使用连接编号获取标记.
     *
     * @param int|string $clientId
     */
    public static function getFlagByClientId($clientId): ?string;
    
    /**
     * 使用连接编号获取标记.
     *
     * @param int[]|string[] $clientIds
     *
     * @return string[]
     */
    public static function getFlagsByClientIds(array $clientIds): array;
    
    /**
     * 使用标记获取旧的连接编号.
     */
    public static function getOldClientIdByFlag(string $flag): ?int;
    
    /**
     * 恢复标记对应连接中的数据.
     */
    public static function restore(string $flag, ?int $toClientId = null): void;
    
    /**
     * 获取当前连接号.
     *
     * @return int|string|null
     */
    public static function getClientId();
    

    会话存储器

    Local 本地变量存储器

    本地变量存储,性能最高,适用于单机部署场景。

    如果使用 Swoole 模式,只建议在 SWOOLE_BASE 模式下使用
    'beans' =>  [
        'ConnectionContextStore'   =>  [
            'handlerClass'  =>  \Imi\Server\ConnectionContext\StoreHandler\Local::class,
        ],
        'ConnectionContextLocal'    =>    [
            'lockId'    =>  null, // 非必设,可以用锁来防止数据错乱问题
        ],
    ],

    Redis 存储器

    数据储存在 Redis 中,需要将多实例服务的 key 设为不同,防止冲突。

    'beans' =>  [
        'ConnectionContextStore'   =>  [
            'handlerClass'  =>  \Imi\Server\ConnectionContext\StoreHandler\Redis::class,
        ],
        'ConnectionContextRedis'    =>    [
            'redisPool'    => 'redis', // Redis 连接池名称
            'redisDb'      => null, // redis中第几个库,为null或不配置则使用连接池中的设置
            'key'          => 'imi:connect_context', // 键
            'heartbeatTimespan' => 5, // 心跳时间,单位:秒
            'heartbeatTtl' => 8, // 心跳数据过期时间,单位:秒
            'dataEncode'=>  'serialize', // 数据写入前编码回调
            'dataDecode'=>  'unserialize', // 数据读出后处理回调
            'lockId'    =>  null, // 非必设,可以用锁来防止数据错乱问题
        ],
    ],

    Swoole MemoryTable 存储器

    数据储存在 Swoole 内存表中,适用于单机部署场景。

    此方案只为解决《我可以不用,但你不能没有》的问题,除非你真的很了解 Swoole Table,否则千万别用。
    'beans' =>  [
        'ConnectionContextStore'   =>  [
            'handlerClass'  =>  \Imi\Swoole\Server\ConnectionContext\StoreHandler\MemoryTable::class,
        ],
        'ConnectionContextMemoryTable' =>  [
            'tableName' =>  'ConnectionContext', // tableName 你需要实现定义 MemoryTable,请查看相关章节
            'dataEncode'=>  'serialize', // 数据写入前编码回调
            'dataDecode'=>  'unserialize', // 数据读出后处理回调
            'lockId'    =>  null, // 非必设,因为如果用 MemoryTable,默认是用 MemoryTable 的 Lock
        ],
    ],

    Workerman Gateway 连接上下文处理器

    适用于使用 Workerman Gateway 模式,支持分布式。

    在 Swoole 中使用 Workerman Gateway 模式也可以用
    'beans' =>  [
        'ConnectionContextStore'   =>  [
            'handlerClass'  =>  \Imi\WorkermanGateway\Server\ConnectionContext\StoreHandler\ConnectionContextGateway::class,
        ],
        'ConnectionContextGateway' =>  [
    
        ],
    ],