zoukankan      html  css  js  c++  java
  • Swoole 中使用 Context 类管理上下文,防止发生数据错乱

    前面的文章中,我们说过:不能使用类静态变量 Class::$array / 全局变量 global $_array / 全局对象属性 $object->array / 其他超全局变量 $GLOBALS 等保存协程上下文内容,以免发生数据错乱。

    那是因为Swoole是常驻内存的,这些全局变量是共享的,在遇到并发请求时,协程A写入的内容可能会因为协程挂起或协程调度被协程B并发修改了,会导致上下文内容不一致。

    解决办法是加入一个基于协程 ID 来保存上下文的 Context 类,来隔离不同协程之间的上下文/全局变量,然后在协程退出时清理上下文内容。

    use SwooleCoroutine;
    
    class Context
    {
        protected static $pool = [];
    
        // 基于协程 `ID` 获取数据
        static function get($key)
        {
            $cid = Coroutine::getCid();
            if ($cid < 0)
            {
                return null;
            }
            if(isset(self::$pool[$cid][$key])){
                return self::$pool[$cid][$key];
            }
            return null;
        }
    
        // 基于协程 `ID` 写入数据
        static function put($key, $item)
        {
            $cid = Coroutine::getCid();
            if ($cid > 0)
            {
                self::$pool[$cid][$key] = $item;
            }
    
        }
    
        // 基于协程 `ID` 删除数据
        static function delete($key = null)
        {
            $cid = Coroutine::getCid();
            if ($cid > 0)
            {
                if($key){
                    unset(self::$pool[$cid][$key]);
                }else{
                    unset(self::$pool[$cid]);
                }
            }
        }
    }
    

    使用示例:

    $server = new SwooleHttpServer('127.0.0.1', 9501);
    
    $server->on('request', function ($request, $response) {
        if ($request->server['request_uri'] == '/a') {
            Context::put('name', 'a');
            co::sleep(1.0);
            echo Context::get('name');
            $response->end(Context::get('name'));
            //退出协程时清理
            Context::delete('name');
        } else {
            Context::put('name', 'b');
            $response->end();
            //退出协程时清理
            Context::delete();
        }
    });
    $server->start();
    

    模拟并发测试:

    curl http://127.0.0.1:9501/a
    curl http://127.0.0.1:9501/b
    
  • 相关阅读:
    net core 3.1 发布问题
    KCF追踪方法流程原理
    2
    1
    0
    LK光流算法公式详解
    MySql单表最大8000W+ 之数据库遇瓶颈记
    Quartz.net基于数据库的任务调度管理(Only.Jobs)
    轻量级代码生成器-OnlyCoder 第二篇
    轻量级代码生成器-OnlyCoder 第一篇
  • 原文地址:https://www.cnblogs.com/danhuang/p/13335697.html
Copyright © 2011-2022 走看看