PHP协程:Go+Chan+Defer

Swoole4提供的Go + Chan + Defer为PHP带来了一种全新的CSP并发编程模式。灵活使用Swoole4提供的各项特性,可以解决工作中各类复杂功能的设计和开发。 2018-12-04 14:00:41 协程编程模式PHP 前端与编译原理——用JS写一个JS解释器 说起编译原理,印象往往只停留在本科时那些枯燥的课程和晦涩的概念。作为前端开发者,编译原理似乎离我们很远,对它的理解很可能仅仅局限于“抽象语法树(AST)”。但这仅仅是个开头而已。编译原理的使用,甚至能让我们利用JS直接写一个能运行JS代码的解释器。 2018-12-04 13:30:28 Javascript编译原理前端 编写你的第一行HTML代码,来帮助蝙蝠侠写一封情书 在你恐慌并处于关键时刻之前,蝙蝠侠说:“我需要你的帮助。我是一个超级极客,但我不懂 HTML。我需要用 HTML 写一封情书,你愿意帮助我吗?”谁会拒绝蝙蝠侠的请求呢,对吧?所以让我们用 HTML 来写一封蝙蝠侠的情书。

Swoole4提供的Go + Chan + Defer为PHP带来了一种全新的CSP并发编程模式。灵活使用Swoole4提供的各项特性,可以解决工作中各类复杂功能的设计和开发。

[[251467]]

Swoole4为PHP语言提供了强大的CSP协程编程模式。底层提供了3个关键词,可以方便地实现各类功能

Swoole4提供的PHP协程语法借鉴自Golang,在此向GO开发组致敬

PHP+Swoole协程可以与Golang很好地互补。Golang:静态语言,严谨强大性能好,PHP+Swoole:动态语言,灵活简单易用

本文基于Swoole-4.2.9和PHP-7.2.9版本

关键词

  • go :创建一个协程
  • chan :创建一个通道
  • defer :延迟任务,在协程退出时执行,先进后出

这3个功能底层实现全部为内存操作,没有任何IO资源消耗。就像PHP的Array一样是非常廉价的。如果有需要就可以直接使用。这与socket和file操作不同,后者需要向操作系统申请端口和文件描述符,读写可能会产生阻塞的IO等待。

协程并发

使用go函数可以让一个函数并发地去执行。在编程过程中,如果某一段逻辑可以并发执行,就可以将它放置到go协程中执行。

顺序执行

  1. functiontest1()
  2. {
  3. sleep(1);
  4. echo"b";
  5. }
  6. functiontest2()
  7. {
  8. sleep(2);
  9. echo"c";
  10. }
  11. test1();
  12. test2();

执行结果:

  1. htf@LAPTOP-0K15EFQI:~$timephpb1.php
  2. bc
  3. real0m3.080s
  4. user0m0.016s
  5. sys0m0.063s
  6. htf@LAPTOP-0K15EFQI:~$

上述代码中,test1和test2会顺序执行,需要3秒才能执行完成。

并发执行

使用go创建协程,可以让test1和test2两个函数变成并发执行。

  1. Swoole\Runtime::enableCoroutine();
  2. go(function()
  3. {
  4. sleep(1);
  5. echo"b";
  6. });
  7. go(function()
  8. {
  9. sleep(2);
  10. echo"c";
  11. });

Swoole\Runtime::enableCoroutine()作用是将PHP提供的stream、sleep、pdo、mysqli、redis等功能从同步阻塞切换为协程的异步IO

执行结果:

  1. bchtf@LAPTOP-0K15EFQI:~$timephpco.php
  2. bc
  3. real0m2.076s
  4. user0m0.000s
  5. sys0m0.078s
  6. htf@LAPTOP-0K15EFQI:~$

可以看到这里只用了2秒就执行完成了。

  • 顺序执行耗时等于所有任务执行耗时的总和 :t1+t2+t3...
  • 并发执行耗时等于所有任务执行耗时的***值 :max(t1, t2, t3, ...)

协程通信

有了go关键词之后,并发编程就简单多了。与此同时又带来了新问题,如果有2个协程并发执行,另外一个协程,需要依赖这两个协程的执行结果,如果解决此问题呢?

答案就是使用通道(Channel),在Swoole4协程中使用new chan就可以创建一个通道。通道可以理解为自带协程调度的队列。它有两个接口push和pop:

  • push:向通道中写入内容,如果已满,它会进入等待状态,有空间时自动恢复
  • pop:从通道中读取内容,如果为空,它会进入等待状态,有数据时自动恢复

使用通道可以很方便地实现并发管理。

  1. $chan=newchan(2);
  2. #协程1
  3. go(function()use($chan){
  4. $result=[];
  5. for($i=0;$i<2;$i++)
  6. {
  7. $result+=$chan->pop();
  8. }
  9. var_dump($result);
  10. });
  11. #协程2
  12. go(function()use($chan){
  13. $cli=newSwoole\Coroutine\Http\Client('www.qq.com',80);
  14. $cli->set(['timeout'=>10]);
  15. $cli->setHeaders([
  16. 'Host'=>"www.qq.com",
  17. "User-Agent"=>'Chrome/49.0.2587.3',
  18. 'Accept'=>'text/html,application/xhtml+xml,application/xml',
  19. 'Accept-Encoding'=>'gzip',
  20. ]);
  21. $ret=$cli->get('/');
  22. //$cli->body响应内容过大,这里用Http状态码作为测试
  23. $chan->push(['www.qq.com'=>$cli->statusCode]);
  24. });
  25. #协程3
  26. go(function()use($chan){
  27. $cli=newSwoole\Coroutine\Http\Client('www.163.com',80);
  28. $cli->set(['timeout'=>10]);
  29. $cli->setHeaders([
  30. 'Host'=>"www.163.com",
  31. "User-Agent"=>'Chrome/49.0.2587.3',
  32. 'Accept'=>'text/html,application/xhtml+xml,application/xml',
  33. 'Accept-Encoding'=>'gzip',
  34. ]);
  35. $ret=$cli->get('/');
  36. //$cli->body响应内容过大,这里用Http状态码作为测试
  37. $chan->push(['www.163.com'=>$cli->statusCode]);
  38. });

执行结果:

  1. htf@LAPTOP-0K15EFQI:~/swoole-src/examples/5.0$timephpco2.php
  2. array(2){
  3. ["www.qq.com"]=>
  4. int(302)
  5. ["www.163.com"]=>
  6. int(200)
  7. }
  8. real0m0.268s
  9. user0m0.016s
  10. sys0m0.109s
  11. htf@LAPTOP-0K15EFQI:~/swoole-src/examples/5.0$

这里使用go创建了3个协程,协程2和协程3分别请求qq.com和163.com主页。协程1需要拿到Http请求的结果。这里使用了chan来实现并发管理。

  • 协程1循环两次对通道进行pop,因为队列为空,它会进入等待状态
  • 协程2和协程3执行完成后,会push数据,协程1拿到了结果,继续向下执行

延迟任务

在协程编程中,可能需要在协程退出时自动实行一些任务,做清理工作。类似于PHP的register_shutdown_function,在Swoole4中可以使用defer实现。

  1. Swoole\Runtime::enableCoroutine();
  2. go(function(){
  3. echo"a";
  4. defer(function(){
  5. echo"~a";
  6. });
  7. echo"b";
  8. defer(function(){
  9. echo"~b";
  10. });
  11. sleep(1);
  12. echo"c";
  13. });

执行结果:

  1. htf@LAPTOP-0K15EFQI:~/swoole-src/examples/5.0$timephpdefer.php
  2. abc~b~a
  3. real0m1.068s
  4. user0m0.016s
  5. sys0m0.047s
  6. htf@LAPTOP-0K15EFQI:~/swoole-src/examples/5.0$

结语

Swoole4提供的Go + Chan + Defer为PHP带来了一种全新的CSP并发编程模式。灵活使用Swoole4提供的各项特性,可以解决工作中各类复杂功能的设计和开发。

©本文为清一色官方代发,观点仅代表作者本人,与清一色无关。清一色对文中陈述、观点判断保持中立,不对所包含内容的准确性、可靠性或完整性提供任何明示或暗示的保证。本文不作为投资理财建议,请读者仅作参考,并请自行承担全部责任。文中部分文字/图片/视频/音频等来源于网络,如侵犯到著作权人的权利,请与我们联系(微信/QQ:1074760229)。转载请注明出处:清一色财经

(0)
打赏 微信扫码打赏 微信扫码打赏 支付宝扫码打赏 支付宝扫码打赏
清一色的头像清一色管理团队
上一篇 2023年5月7日 18:01
下一篇 2023年5月7日 18:01

相关推荐

发表评论

登录后才能评论

联系我们

在线咨询:1643011589-QQbutton

手机:13798586780

QQ/微信:1074760229

QQ群:551893940

工作时间:工作日9:00-18:00,节假日休息

关注微信