# 协程池 首先要声明的一点是,协程池这个概念是我自己编的。 因为协程的特点,它是单线程下运行的,所以在一个进程内同时实际上只会有一个协程的代码在执行逻辑,但是后面的 IO 操作、协程挂起等待的操作都是同时去做的,比如数据库的大数据读取、写入需要耗时几秒甚至几十秒,这时用基于协程的 MySQL 连接池就完全不是问题。 但是就拿 MySQL 举例,我们 MySQL 使用的是 TCP 连接,而无论是 MySQL 还是 TCP 连接,最大数量都是有限的。我们即使设置了允许最大协程数量非常大,比如上百万,但是也不能让数据库连接池一个池支持上百万的连接。 这时假设高并发进来了怎么办呢?这时就需要框架提出的一个折中方案:协程池了。 顾名思义,协程池是一个容纳协程的区域,而协程里又容纳着各种各样需要阻塞调用被协程调用的 IO 操作,协程池用作限制协程的数量。 ```php use ZM\Utils\CoroutinePool; use ZM\DB\DB; // 传统写法,一旦高并发则可能导致 Too many connections go(funuction(){ DB::rawQuery("INSERT INTO users VALUES(?,?)", ["admin", "password"]); }); // 协程池写法 CoroutinePool::go(function(){ DB::rawQuery("INSERT INTO users VALUES(?,?)", ["admin", "password"]); }, "foo"); ``` 参数:`go(callable $func, $name = "default")` `$name` 为协程池对应的名字,你可以设置多个协程池,用来支持不同的需要限制并发 IO 数量的地方,例如 Redis 和 MySQL 设置不同的名字。`$func` 可为闭包或可调用的方法名称或数组。 ## 配置 默认情况下,直接调用 `CoroutinePool::go()` 时,协程池大小为 30,也就是如果有 30 个协程进入了挂起状态(比如数据库在执行查询语句),那么更多的协程执行时就会阻塞并以协程等待的方式等待,直到现有的 30 个协程中的一部分完成了它的工作。 ## 方法 ### CoroutinePool::go() 将协程放入协程池运行。 如果不写 `$name` 参数,则使用的是默认协程池。 ### CoroutinePool::defaultSize() 设置默认协程池的大小(默认 30) ```php CoroutinePool::defaultSize(64); for($i = 0; $i < 1000; ++$i) { CoroutinePool::go(function(){ DB::rawQuery("SELECT * FROM users"); }); } ``` ### CoroutinePool::setSize() 定义:`setSize($name, int $size)` `$name` 为字符串,是你要用的协程池的名称。 `$size` 为大小,最大不可超过 Swoole 配置文件中指定的最大协程数量。