Swoole协程并发调用

作者: 温新

分类: 【高性能PHP】

阅读: 2331

时间: 2021-04-24 15:12:45

Swoole协程并发调用实现原理:

  • onRequest中需要并发两个http请求,可使用go函数创建 2 个子协程,并发地请求多个URL
  • 并创建一个chan,使用use必报引用语法,传递给子协程;
  • 主协程循环调用chan-pop,等待子协程完成任务,yield进入挂起状态;
  • 并发的两个子协程其中某个完成请求时,调用chan-push将数据推送给主协程;
  • 子协程完成URL请求后退出,主协程从挂起状态中恢复,继续向下执行调用$response-end发送响应结果。

第一步:编写代码

文件:d14.php

<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(152, 26, 26)"><?</span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">php</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">use</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Swoole\Coroutine\MySQL</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">use</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Swoole\Coroutine\Redis</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 创建HTTP服务器</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 85, 170)">$serv</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">new</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Swoole\Http\Server</span>(<span style="box-sizing: border-box;color: rgb(170, 17, 17)">"127.0.0.1"</span>, <span style="box-sizing: border-box;color: rgb(17, 102, 68)">9503</span>, <span style="box-sizing: border-box;color: rgb(0, 0, 0)">SWOOLE_BASE</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 监听</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 85, 170)">$serv</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">on</span>(<span style="box-sizing: border-box;color: rgb(170, 17, 17)">'Request'</span>, <span style="box-sizing: border-box;color: rgb(119, 0, 136)">function</span> (<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$res</span>, <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$resp</span>) {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 创建通道</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$chan</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">new</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">chan</span>(<span style="box-sizing: border-box;color: rgb(17, 102, 68)">2</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 创建协程</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">go</span>(<span style="box-sizing: border-box;color: rgb(119, 0, 136)">function</span> () <span style="box-sizing: border-box;color: rgb(119, 0, 136)">use</span> (<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$chan</span>) {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">  <span style="box-sizing: border-box;color: rgb(51, 0, 170)">var_dump</span>(<span style="box-sizing: border-box;color: rgb(51, 0, 170)">time</span>());</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">  <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 连接mysql</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">  <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$mysql</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">new</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">MySQL</span>();</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">  <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$mysql</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">connect</span>([</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(170, 17, 17)">'host'</span>     <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=></span> <span style="box-sizing: border-box;color: rgb(170, 17, 17)">'127.0.0.1'</span>,</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(170, 17, 17)">'user'</span>     <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=></span> <span style="box-sizing: border-box;color: rgb(170, 17, 17)">'root'</span>,</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(170, 17, 17)">'password'</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=></span> <span style="box-sizing: border-box;color: rgb(170, 17, 17)">'123456'</span>,</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(170, 17, 17)">'database'</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=></span> <span style="box-sizing: border-box;color: rgb(170, 17, 17)">'test'</span>,</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">     ]);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">     <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$result</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$mysql</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">query</span>(<span style="box-sizing: border-box;color: rgb(170, 17, 17)">'select sleep(3)'</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">     <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 将结果推送给主协程</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">  <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$chan</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">push</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$result</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> });</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">go</span>(<span style="box-sizing: border-box;color: rgb(119, 0, 136)">function</span> () <span style="box-sizing: border-box;color: rgb(119, 0, 136)">use</span> (<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$chan</span>) {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">  <span style="box-sizing: border-box;color: rgb(51, 0, 170)">var_dump</span>(<span style="box-sizing: border-box;color: rgb(51, 0, 170)">time</span>());</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">  <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$redis1</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">new</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Redis</span>();</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">     <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$redis1</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">connect</span>(<span style="box-sizing: border-box;color: rgb(170, 17, 17)">'127.0.0.1'</span>, <span style="box-sizing: border-box;color: rgb(17, 102, 68)">6379</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">     <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$result</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$redis1</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">set</span>(<span style="box-sizing: border-box;color: rgb(170, 17, 17)">'hello'</span>,<span style="box-sizing: border-box;color: rgb(170, 17, 17)">'swoole'</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">     <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$chan</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">push</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$result</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> });</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">go</span>(<span style="box-sizing: border-box;color: rgb(119, 0, 136)">function</span> () <span style="box-sizing: border-box;color: rgb(119, 0, 136)">use</span> (<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$chan</span>) {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">  <span style="box-sizing: border-box;color: rgb(51, 0, 170)">var_dump</span>(<span style="box-sizing: border-box;color: rgb(51, 0, 170)">time</span>());</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">  <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$redis2</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">new</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Redis</span>();</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">     <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$redis2</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">connect</span>(<span style="box-sizing: border-box;color: rgb(170, 17, 17)">'127.0.0.1'</span>, <span style="box-sizing: border-box;color: rgb(17, 102, 68)">6379</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">     <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$result</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$redis2</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">get</span>(<span style="box-sizing: border-box;color: rgb(170, 17, 17)">'hello'</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">     <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$chan</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">push</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$result</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> });</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 从通道中读取数据并存入数组</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$results</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> [];</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">for</span> (<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$i</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(17, 102, 68)">0</span>; <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$i</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)"><</span> <span style="box-sizing: border-box;color: rgb(17, 102, 68)">3</span>; <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$i</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">++</span>) {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">  <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$results</span>[] <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$chan</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">pop</span>();</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 响应请求</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$resp</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(51, 0, 170)">end</span>(<span style="box-sizing: border-box;color: rgb(51, 0, 170)">json_encode</span>([</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">  <span style="box-sizing: border-box;color: rgb(170, 17, 17)">'data'</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=></span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$results</span>,</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">  <span style="box-sizing: border-box;color: rgb(170, 17, 17)">'time'</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=></span> <span style="box-sizing: border-box;color: rgb(51, 0, 170)">time</span>()</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> ]));</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">});</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 85, 170)">$serv</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">start</span>();</span>

第二步:运行http服务器

php d14.php

第三步:浏览器中访问

<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 0, 0)">http</span>:<span style="box-sizing: border-box;color: rgb(170, 85, 0)">//192.168.172.130:9503/</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 页面输出结果</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">{<span style="box-sizing: border-box;color: rgb(170, 17, 17)">"data"</span>:[<span style="box-sizing: border-box;color: rgb(170, 17, 17)">"swoole"</span>,<span style="box-sizing: border-box;color: rgb(34, 17, 153)">true</span>,[{<span style="box-sizing: border-box;color: rgb(170, 17, 17)">"sleep(3)"</span>:<span style="box-sizing: border-box;color: rgb(170, 17, 17)">"0"</span>}]],<span style="box-sizing: border-box;color: rgb(170, 17, 17)">"time"</span>:<span style="box-sizing: border-box;color: rgb(17, 102, 68)">1619270058</span>}</span>

第四步:查看http服务器

<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 0, 0)">int</span>(<span style="box-sizing: border-box;color: rgb(17, 102, 68)">1619270058</span>)</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 0, 0)">int</span>(<span style="box-sizing: border-box;color: rgb(17, 102, 68)">1619270058</span>)</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 0, 0)">int</span>(<span style="box-sizing: border-box;color: rgb(17, 102, 68)">1619270058</span>)</span>

可以看到打印三个客户端请求时间是一致的,说明它们是并发执行的。

请登录后再评论