四十、Swoole 基础学习笔记 - Swoole 一键协程化(Swoole 基础系列完)

作者: 温新

分类: 【Swoole 系列】

阅读: 1034

时间: 2023-03-13 12:37:35

hi,我是温新,一名PHPer

文章基于 Swoole 5.0.1 版本编写。

学习目标:学习一键协程化

说明:本篇文章结合官方文档编写及参考网络资料编写,虽非全部原创,但也是结合了自己的理解,若转载请附带本文 URL,编写不易,持续编写更不易,谢谢!

Swoole 系列代码已上传至 Github:https://github.com/ziruchu/Swoole

协程化客户端(MySQL、Redis)官方已经不推荐使用了。推荐使用 一键协程化 来操作。为什么不推荐使用 MySQL 等协程客户端,官方已经文档已经有了很详细的说明。

一键协程化

Swoole 开发组采用Hook 原生 PHP 函数的方式实现协程客户端,通过一行代码就可以让原来的同步 IO 的代码变成可以协程调度异步 IO,即一键协程化。

一键协程化有什么好处?

1、一键协程化对我们编写代码没有什么改变,以前怎么写,现在还是怎么写;

2、只有在一些涉及 IO 操作时才会协程调度;

3、经使用 MySQL 等协程客户端,可以使用原生的 API 操作。

一键协程案例

<span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important"><?</span><span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">php</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(98, 151, 85) !important">// 40-coroutine.php</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(98, 151, 85) !important">// 开启协程调度</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">Swoole\Runtime</span>::<span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">enableCoroutine</span>();</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(98, 151, 85) !important">// 案例一</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">for</span> (<span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$c</span> <span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">=</span> <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">1000</span>; <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$c</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">--</span>;) {</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">go</span>(<span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">function</span> () {<span style="box-sizing: border-box;color: rgb(98, 151, 85) !important">//创建100个协程</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$redis</span> <span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">=</span> <span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">new</span> <span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">Redis</span>();</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$redis</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">-></span><span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">connect</span>(<span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">'127.0.0.1'</span>, <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">6379</span>);<span style="box-sizing: border-box;color: rgb(98, 151, 85) !important">//此处产生协程调度,cpu切到下一个协程,不会阻塞进程</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$redis</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">-></span><span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">set</span>(<span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">'name'</span>, <span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">'王美丽'</span>);</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">echo</span> <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$redis</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">-></span><span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">get</span>(<span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">'name'</span>);<span style="box-sizing: border-box;color: rgb(98, 151, 85) !important">//此处产生协程调度,cpu切到下一个协程,不会阻塞进程</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    </span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    });</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">}</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(98, 151, 85) !important">// 案例二</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">go</span>(<span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">function</span> () {</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(98, 151, 85) !important">// 使用原生数据库方式操作</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$dsn</span> <span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">=</span> <span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">"mysql:host=127.0.0.1;dbname=test1"</span>;</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$pdo</span> <span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">=</span> <span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">new</span> <span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">PDO</span>(<span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$dsn</span>, <span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">'test'</span>, <span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">'test'</span>);</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$statement</span> <span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">=</span> <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$pdo</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">-></span><span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">query</span>(<span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">"select * from test7   "</span>);</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$row</span> <span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">=</span> <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$statement</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">-></span><span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">fetch</span>(<span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">PDO</span>::<span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">FETCH_ASSOC</span>);</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(232, 191, 106) !important">print_r</span>(<span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$row</span>);</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">});</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(98, 151, 85) !important">// 案例三</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">go</span>(<span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">function</span> () {</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">echo</span> <span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">'我会先输出'</span> . <span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">PHP_EOL</span>;</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">});</span>

这个案例中,开启了一键协程化,案例三会第一个输出,案例一和案例二谁先谁后不一定。

输出结果

<span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$php</span> <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">40</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">-</span><span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">coroutine</span>.<span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">php</span> </span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">我会先输出</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">王美丽王美丽</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">Array</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">(</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    [<span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">a</span>] <span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">=></span> <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">1</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    [<span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">b</span>] <span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">=></span> <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">1</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">)</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">王美丽</span></span>

不使用一键协程化

<span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important"><?</span><span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">php</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(98, 151, 85) !important">// 40-coroutine-1.php</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(98, 151, 85) !important">// 案例一</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">for</span> (<span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$c</span> <span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">=</span> <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">1000</span>; <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$c</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">--</span>;) {</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">go</span>(<span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">function</span> () {<span style="box-sizing: border-box;color: rgb(98, 151, 85) !important">//创建100个协程</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$redis</span> <span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">=</span> <span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">new</span> <span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">Redis</span>();</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$redis</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">-></span><span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">connect</span>(<span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">'127.0.0.1'</span>, <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">6379</span>);<span style="box-sizing: border-box;color: rgb(98, 151, 85) !important">//此处产生协程调度,cpu切到下一个协程,不会阻塞进程</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$redis</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">-></span><span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">set</span>(<span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">'name'</span>, <span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">'王美丽'</span>);</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">echo</span> <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$redis</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">-></span><span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">get</span>(<span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">'name'</span>);<span style="box-sizing: border-box;color: rgb(98, 151, 85) !important">//此处产生协程调度,cpu切到下一个协程,不会阻塞进程</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    </span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    });</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">}</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(98, 151, 85) !important">// 案例二</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">go</span>(<span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">function</span> () {</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(98, 151, 85) !important">// 使用原生数据库方式操作</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$dsn</span> <span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">=</span> <span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">"mysql:host=127.0.0.1;dbname=test1"</span>;</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$pdo</span> <span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">=</span> <span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">new</span> <span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">PDO</span>(<span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$dsn</span>, <span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">'tset'</span>, <span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">'test'</span>);</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$statement</span> <span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">=</span> <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$pdo</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">-></span><span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">query</span>(<span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">"select * from test7"</span>);</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$row</span> <span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">=</span> <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$statement</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">-></span><span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">fetch</span>(<span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">PDO</span>::<span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">FETCH_ASSOC</span>);</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(232, 191, 106) !important">print_r</span>(<span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$row</span>);</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">});</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(98, 151, 85) !important">// 案例三</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">go</span>(<span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">function</span> () {</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">echo</span> <span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">'我会先输出吗?'</span> . <span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">PHP_EOL</span>;</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">});</span>

不使用一键协程,程序在运行过程中,只有案例一运行结束,再运行案例二,最后运行案例三。一定要动手演示哦!

Swoole 基础系列到这里就完结了。很遗憾的是,遗留下事件,关于这面方面的知识我会去补充学习。

关于事件,如果你有什么好的文章或易懂的书籍,希望推荐一下,谢谢!

Swoole 基础系列已经结束,但这仅仅只是开始。新规划开启!

嗨,Swoole 基础系列结束;你好 Hyperf 3.0!

请登录后再评论