• swoole 协程用法笔记


    协程方法一览

    协程方法简明笔记:

    • Coroutine::set 协程设置

      • max_coroutine
    • Coroutine::stats 协程状态

    • Coroutine::list 遍历当前进程中的所有协程

    • Coroutine::getBackTrace 查看协程调用栈

      • 别名 Coroutine::listCoroutines()
    • Coroutine::create 创建协程

      • 短名 go()
      • 协程开销: 推荐使用 php>=7.2, 创建初始分配的栈内存更小, 并且会自动扩容
    • Coroutine::defer 类似 go 的 defer, PHP 有析构函数(__destruct())和自动回收机制, defer 的使用范围没那么大

      • 短名 defer()
    • CoroutineChannel 类似 go 的 chan, 所有操作均为内存操作, 进程间内存隔离

      • 短名 chan()
      • 初始化是需要设置容量(capacity), 通道 空/满 会影响到后续的 push / pop
      • 必须在 swoole server 的 onWorkerStart 之后创建
    • Coroutine::getCid 当前协程id, 即 cid

    • Coroutine::exist

    • Coroutine::getPcid 获取父协程cid

      • 协程的嵌套会带来初始的先后顺序(父子关系), 最终执行还是要看协程的调度(没有稳定的父子关系)
    • Coroutine::getContext

    • Coroutine::yield 让出当前协程的执行权, 需要配合 resume 使用, 由其他协程唤醒

      • 别名 Coroutine::suspend
    • Coroutine::resume 唤醒其他协程

    • Coroutine::exec 协程版 shell_exec()

    • Coroutine::gethostbyname DNS查询, todo -> http client 是否需要

    • Coroutine::getaddrinfo

    • Coroutine::statvfs 获取文件系统信息(目前还不知道使用场景)

    • CoroutineClient

    • CoroutineHttpClient

    • CoroutineHttp2Client

    • CoroutineSocket

    • CoroutinePostgreSQL

      • 安装 swoole 时, 需要加编译参数 --enable-coroutine-postgresql
      • 系统需要安装 libpg 库

    开启协程 runtime 后(SwooleRuntime::enableCoroutine()), 可以不再使用:

    • Coroutine::fread
    • Coroutine::fgets
    • Coroutine::fwrite
    • Coroutine::sleep
    • Coroutine::readFile
    • Coroutine::writeFile
    • CoroutineRedis 使用 ext-redis(phpredis) / predis
    • CoroutineMySQL 使用 mysqlnd 模式的 pdo、mysqli 扩展

    阻塞代码检验

    swoole 中使用协程的 2 个要点:

    • 开协程: 这个容易, go() 一下就行了
    • 协程中执行 非阻塞代码: 除了看官方文档, 下面提供一个简单的检测 demo
    go(function () {
        sleep(1); // 未开启协程 runtime, 此处会阻塞, 输出为 go -> main
        echo "go 
    ";
    });
    echo "main 
    ";
    

    输出为: go -> main

    SwooleRuntime::enableCoroutine();
    
    go(function () {
        sleep(1); // 开启协程 runtime, 此处为阻塞, 输出为 main -> go
        echo "go 
    ";
    });
    echo "main 
    ";
    

    输出为: main -> go, 发生了协程调度.

    使用时将 sleep(1) 替换为需要检测的代码即可.

    对短名称的个人看法

    • 建议关闭, 全部使用 SwooleCoroutine 命名空间保持一致性, 按需封装常用的几个, 比如 go() chan() defer()
    • ini 配置: swoole.use_shortname = 'Off'
    if (! function_exists('go')) {
        function go(callable $callable)
        {
            HyperfUtilsCoroutine::create($callable);
        }
    }
    
    if (! function_exists('defer')) {
        function defer(callable $callable): void
        {
            HyperfUtilsCoroutine::defer($callable);
        }
    }
    

    其他

    • swoole 协程中比较重要的参数设置 max_coroutine, 更科学方式(看是否有需要): 压测后查看内存占用, 进而进行调整
    • wiki - 协程编程须知: 使用协程的注意事项
    • 协程 go+chan+defer: chan可以用在协程间交互, defer使用场景有待收集
    • 实现 defer: __destruct()
    • 实现 waitgroup: chan+count计数, 可以进一步封装成更方便的写法
    • 版本更新记录: 仔细看看, 就能体会到开发组在php 协程上的努力

    并发调用

    官方提供了 2 种方式:

    • setDefer 机制: 延迟收包, 多个请求并发收取相应结果; 确保协程组件支持 setDefer 机制(绝大部分协程组件都支持)
    • 子协程 + chan: 每个请求在子协程中执行, 通过 chan 实现请求收包时的协程调度

    个人不建议使用, 并发调用可以达到更好的性能, 但是不符合常用的编程习惯, 多个请求需要同时完成, 推荐使用 waitGroup, 在此基础上, 还可以封装成更简单的写法

    class WaitGroup
    {
        /**
         * @var int
         */
        private $counter = 0;
    
        /**
         * @var SwooleChannel
         */
        private $channel;
    
        public function __construct()
        {
            $this->channel = new chan();
        }
    
        public function add(int $incr = 1): void
        {
            $this->counter += $incr;
        }
    
        public function done(): void
        {
            $this->channel->push(true);
        }
    
        public function wait(): void
        {
            while ($this->counter--) {
                $this->channel->pop();
            }
        }
    }


    作者:daydaygo
    链接:https://www.jianshu.com/p/28e882352da5
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 相关阅读:
    js json与字符串相互转换
    Web 加入favicon
    JS 深拷贝
    C# 读取配置文件
    设计模式之抽象工厂模式
    设计模式之工厂方法的隐藏
    设计模式之工厂方法的重载
    设计模式之工厂方法配置文件与反射
    C#设计模式之工厂方法模式
    jq解析json文件
  • 原文地址:https://www.cnblogs.com/xiami2046/p/13556959.html
Copyright © 2020-2023  润新知