Swoole中的协程使用相关说明,快来围观

组合苔藓
• 阅读 1012

什么是协程
​ 协程可以简单理解为线程,只不过这个线程是用户态的,不需要操作系统参与,创建销毁和切换的成本非常低,和线程不同的是协程没法利用多核 cpu 的,想利用多核 cpu 需要依赖 Swoole 的多进程模型。

协程特点
开发者可以无感知的用同步的代码编写方式达到异步 IO 的效果和性能,避免了传统异步回调所带来的离散的代码逻辑和陷入多层回调中导致代码无法维护。
同时由于底层封装了协程,所以对比传统的 PHP 层协程框架,开发者不需要使用 yield 关键词来标识一个协程 IO 操作,所以不再需要对 yield 的语义进行深入理解以及对每一级的调用都修改为 yield,这极大的提高了开发效率。
协程适合 IO 密集型应用,因为协程在 IO 阻塞 时会自动调度,减少 IO 阻塞导致的时间损失。
睡眠 1 万次,读取,写入,检查和删除文件 1 万次,使用 PDO 和 MySQLi 与数据库通信 1 万次,创建 TCP 服务器和多个客户端相互通信 1 万次,创建 UDP 服务器和多个客户端到相互通信 1 万次...... 一切都在一个进程一秒内完美完成!
适用场景
​ 高并发服务,如秒杀系统、高性能API接口、RPC服务器,连接池,IM聊天、游戏服务器、物联网、消息服务器等。

示例1:
用户可以通过go函数创建一个协程,以达到并发执行的效果,如下面代码所示:

go(function () {
    echo "one" . PHP_EOL;
});

go(function () {
    echo "two" . PHP_EOL;
});

go(function () {
    echo "three" . PHP_EOL;
});

每当出现一个go,底层会自动创建一个协程,协程输出内容后,然后自动退出
示例2:
通过协程可以并发执行客户端请求,使用到协程调度带来的 IO 阻塞时的调度,来实现高性能服务,下面是通过 defer 机制实现请求的并发执行:

go(function () {
    // 协程 MySQL 客户端
    $mysql = new Swoole\Coroutine\MySQL();
    $mysql->connect([
        'host' => '172.17.0.1',
        'user' => 'root',
        'password' => 'root',
        'database' => 'swoole',
    ]);
    $mysql->setDefer();
    $mysql->query('select sleep(2);');
    
     print_r("time1: " . time() . PHP_EOL);
    
    // 协程 Redis 客户端
    $redis = new Swoole\Coroutine\Redis();
    $redis->connect('172.17.0.1', 6379);
    $redis->setDefer();
    $redis->set('name', '张三');
    $redis->recv();
    
    print_r("time2: " . time() . PHP_EOL);

    $redis->setDefer();
    $redis->get('name');

    $res1 = $mysql->recv();
    $res2 = $redis->recv();

    print_r(['result1: ' => $res1[0]['sleep'], 'result2: ' => $res2, 'time3: ' => time()]);
});

以上述代码为例,可以简单理解为 defer 模式下, 多个客户端的请求响应是并发的,设置 setDefer(true) 后,通过 Redis 或 MySQL 客户端发起请求,将不再等待服务器返回结果,而是在发送请求之后,立即返回 true。在此之后可以继续发起其他 Redis、MySQL 请求,最后再使用 recv() 方法接收响应内容。
注意事项
如果在多个协程间共用同一个协程客户端,同步阻塞程序不同,协程是并发处理请求的,因此同一时间可能会有很多个请求在并行处理,一旦共用客户端连接,就会导致不同协程之间发生数据错乱。
协程使得原有的异步逻辑同步化,但是在协程的切换是隐式发生的,所以在协程切换的前后不能保证全局变量以及static变量的一致性。
总结
技术无止境,协程的使用需要结合实际业务进行具象分析,才能合理的发挥技术特点。
要定期抽出时间来充实自己,这样才能更好的拓展技术视野的宽度,时代在不断的进步,尤其是IT类的行业发展最为迅速,如果不去学习的话就很容易落后的。
最后
如果你觉得这篇文章对你有点用的话,麻烦请给我们的开源项目点点star:http://github.crmeb.net/u/defu不胜感激 !

免费获取源码地址:http://www.crmeb.com

PHP学习手册:https://doc.crmeb.com

技术交流论坛:https://q.crmeb.com

点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
4年前
java线程笔记
线程个人理解:线程是一种运行单元,是进程内的拆分(就像一个房子,里面可以有电视在播放、人在吃饭),不同的线程可以同时干不同的事情。其他:进程:进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。协程:协程是比线程的更小的一种程序的拆分,和
风斗 风斗
4年前
Kotlin 协程中,关于 runBlocking, launch ,withContext ,async,doAsync 之间的简单区别
引入大佬的话,Kotlin的协程,本质上是一个线程框架,它可以方便的切换线程的上下文(如主线程切换到子线程/子线程切回主线程)。而平时我们要想在AndroidStudio使用协程,先要在gradle引入协程依赖:implementation"org.jetbrains.kotlinx:kotlinxcoroutinescore:1.3.3"
Stella981 Stella981
4年前
Gevent简明教程
1、前述进程线程协程异步并发编程(不是并行)目前有四种方式:多进程、多线程、协程和异步。多进程编程在python中有类似C的os.fork,更高层封装的有multiprocessing标准库多线程编程python中有Thread和threading异步编程在linux下主要有三种实现selec
Stella981 Stella981
4年前
Goroutine(协程)为何能处理大并发?
简单来说:协程十分轻量,可以在一个进程中执行有数以十万计的协程,依旧保持高性能。进程、线程、协程的关系和区别:进程拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系统调度。线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程亦由操作系统调度(标准线程是的)。协程和线程一样共享堆
Wesley13 Wesley13
4年前
Go 并发
Go并发并发指的是同时处理多个任务的能力。并行指的是并行处理多个任务的能力。并行不一定加快运行速度,因为并行组件之间可能需要互相通信。Go中使用协程,信道来处理并发。协程Go中主要通过协程实现并发。协程是与其他函数或方法一起并发运行的函数或方法,协程可以看作是轻量级线程,但是创建成本更小,我们经常
Stella981 Stella981
4年前
Go实现FastCgi Proxy Client 系列(三)优化篇
墨迹一点个人琐碎最近比较忙,以致于很久都没有写blog了,但是,golang的水平自认为是总算入门了。协程的个人理解网上的说法一般都是协程是轻量级线程。我个人认为协程的好处1.小2.无需在用户态和内核态切换(完全在用户态)3.无需线程上下文切换的开销(因为之上的好处)4.编码简单(原
Easter79 Easter79
4年前
Swoole2.0内置协程并发测试
Swoole2.0是一个革命性的版本,它内置了协程的支持。与Go语言协程不同,Swoole协程完全不需要开发者添加任何额外的关键词,直接以过去最传统的同步阻塞模式编写代码,底层自动进行协程调度实现异步IO。使并发编程变得非常简单。最新的版本中,内置协程已支持PHP7,同时兼具了性能和并发能力,Swoole的强大超乎想象。本文基于Github最新的Sw
Android Kotlin 协程初探 | 京东物流技术团队
1它是什么(协程和Kotlin协程)1.1协程是什么维基百科:协程,英文Coroutine\2为什么选择它(协程解决什么问题)异步场景举例:1.第一步:接口获取当前用户token及用户信息2.第二步:将用户的昵称展示界面上3.第三步:然后再通过这个toke
组合苔藓
组合苔藓
Lv1
不知何岁月,得与尔同归?
文章
3
粉丝
0
获赞
0