Swoole 中使用 Context 类管理上下文,防止发生数据错乱
前面的文章中,我们说过:不能使用类静态变量 Class::$array / 全局变量 global $_array / 全局对象属性 $object->array / 其他超全局变量 $GLOBALS 等保存协程上下文内容,以免发生数据错乱。
那是因为Swoole是常驻内存的,这些全局变量是共享的,在遇到并发请求时,协程A写入的内容可能会因为协程挂起或协程调度被协程B并发修改了,会导致上下文内容不一致。
解决办法是加入一个基于协程 ID 来保存上下文的 Context 类,来隔离不同协程之间的上下文/全局变量,然后在协程退出时清理上下文内容。
use Swoole\Coroutine;
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 Swoole\Http\Server('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
												
											Swoole 中使用 Context 类管理上下文,防止发生数据错乱的更多相关文章
- Swoole 中协程的使用注意事项及协程中的异常捕获
		
协程使用注意事项 协程内部禁止使用全局变量,以免发生数据错乱: 协程使用 use 关键字引入外部变量到当前作用域禁止使用引用,以免发生数据错乱: 不能使用类静态变量 Class::$array / 全 ...
 - 089 01 Android 零基础入门  02 Java面向对象 02 Java封装 01 封装的实现 03 # 088 01 Android 零基础入门  02 Java面向对象 02 Java封装 01 封装的实现 03 使用包进行类管理(1)——创建包
		
089 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 03 # 088 01 Android 零基础入门 02 Java面向对象 02 Java封装 ...
 - 如何获取 C# 类中发生数据变化的属性信息
		
一.前言 在平时的开发中,当用户修改数据时,一直没有很好的办法来记录具体修改了那些信息,只能暂时采用将类序列化成 json 字符串,然后全塞入到日志中的方式,此时如果我们想要知道用户具体改变了哪几个字 ...
 - 翻译《Writing Idiomatic Python》(五):类、上下文管理器、生成器
		
原书参考:http://www.jeffknupp.com/blog/2012/10/04/writing-idiomatic-python/ 上一篇:翻译<Writing Idiomatic ...
 - Android开发中Context类的作用以及Context的详细用法
		
Android中Context的作用以及Context的详细用法 本文我们一起来探讨一下关于Android中Context的作用以及Context的详细用法,这对我们学习Android的资源访问有很大 ...
 - java上下文Context类
		
Context在Java中的出现是如此频繁,但其中文翻译"上下文"又是如此诡异拗口,因此导致很多人不是很了解Context的具体含义是指什么,所以很有必要来深究一下这词的含义. 先 ...
 - boot中 Quartz注入spring管理类失败
		
在项目中用到了Quartz,想在里面实现业务操作发现sping类注入总是失败.后来网上查询了一下解决办法.下面把我成功解决问题的这个版本发出来,大家一起学习一下. 在quartz 会发现 job中无法 ...
 - Android中的Context(一)
		
Android中的Context(一) 在Android开发中,Context可以说是我们接触地非常多的一个概念了,也译作"上下文",但是这个上下文到底是什么却并不好理解. 通俗的 ...
 - Android Context类
		
一.Context类的使用场景 ①.创建Application对象时,而且整个app公用一个Application对象 ②.创建Service对象时 ③.创建Activity对象时 二.应用程序共有几 ...
 
随机推荐
- tomcat 之 httpd   session  stiky
			
# 注释中心主机 [root@nginx ~]# vim /etc/httpd/conf/httpd.conf #DocumentRoot "/var/www/html" #:配置 ...
 - 快速上手git gitlab协同合作
			
简单记录,整理. 摘要 为方便大家快速上手Git,并使用Gitlab协同合作,特编写此手册,手册内容不会太丰富与深入.主要包含如下内容: Git 使用教程1.1 安装1.2 常用命令1.3 版本控制1 ...
 - Dubbo服务调用超时
			
服务降级的发生,其实是由于消费者调用服务超时引起的,即从发出调用请求到获取到提供者的响应结果这个时间超出了设定的时限.默认服务调用超时时限为1秒.可以在消费者端与提供者端设置超时时限. 一.创建提供者 ...
 - Java易错小结
			
String 相关运算 String使用是注意是否初始化,未初始化的全部为null.不要轻易使用 string.isEmpty()等,首先确保string非空. 推荐使用StringUtils.isN ...
 - 【Java 基础】Java 根据Class获取对象实例
			
Spring在代码中获取bean的几种方式 方法一:在初始化时保存ApplicationContext对象 方法二:通过Spring提供的utils类获取ApplicationContext对象 方法 ...
 - 二级C复习
			
二级C语言 队列 计算队列中元素个数 种 : rear > front ,直接减 第二种: rear < front 上面两种综合一起,求元素个数公式 :(r - f + maxsize) ...
 - 分布式事务之TCC事务模型
			
一.引言 在上篇文章<老生常谈--利用消息队列处理分布式事务>一文中留了一个坑,今天来填坑.如下图所示 如果服务A和服务B之间是同步调用,比如服务C需要按流程调服务A和服务B,服务A和服务 ...
 - 前端浅谈-协议相关(http/https)
			
当DNS工作完之后得到了一个网址 https//192.168.1.255/index.html 这个并不符合标准的请求路径.接下来就是https的功能了.讲https前先讲讲它的前身http协议 H ...
 - HTML标签一览
			
html标签属性大全 嵌套的html窗口<iframe > <iframe src="https://www.baidu.com"></iframe& ...
 - 线程 TLS
			
TLS为什么产生呢?是软件开发中的什么问题呢? TLS 产生背景进程中的全局变量与函数内定义的静态(static)变量,是各个线程都可以访问的共享变量.在一个线程修改的内存内容,对所有线程都生效 ...