PHP coordination: Go+Chan+Defer

  coroutine, golang, php, swoole

Swoole4ForPHPLanguage provides a powerfulCSPCollaborative programming mode. The bottom layer provides3Key words, can easily realize all kinds of functions.

  • Swoole4ProvidedPHP coordinationGrammar is borrowed fromGolangIn this directionGODevelopment team pays tribute
  • PHP+SwooleThe coordination process can be linked withGolangThey complement each other very well.GolangStatic language, rigorous and powerful with good performance.PHP+Swoole: Dynamic language, flexible, simple and easy to use

This article is based onSwoole-4.2.9AndPHP-7.2.9Version

Key words

  • go: Create a Concorde
  • chan: Create a Channel
  • defer: Delayed task, executed when the coordination process exits, first in and then out

This ..3All of the underlying implementations of the functions areMemory operation, there is no anyIOResource consumption. Just like …PHPTheArrayThe same is very cheap. Can be used directly if necessary. This is related tosocketAndfileDifferent operations require the latter to apply to the operating system for ports and file descriptors, which may cause blocking in reading and writing.IOWait.

Concorde concurrency

UsegoFunctions allow a function to execute concurrently. During programming, if a piece of logic can be executed concurrently, it can be placed in thegoIt will be carried out in the coordination process.

Sequential execution

function test1()
 {
 sleep(1);
 echo "b";
 }
 
 function test2()
 {
 sleep(2);
 echo "c";
 }
 
 test1();
 test2();

Results of implementation:

htf@LAPTOP-0K15EFQI:~$ time php  b1.php
 bc
 real    0m3.080s
 user    0m0.016s
 sys     0m0.063s
 htf@LAPTOP-0K15EFQI:~$

In the above code,test1Andtest2It will be executed sequentially and needs to be3It takes 2 seconds to complete the execution.

Concurrent execution

UsegoCreating a coordination process allowstest1Andtest2The two functions become executed concurrently.

Swoole\Runtime::enableCoroutine();
 
 go(function ()
 {
 sleep(1);
 echo "b";
 });
 
 go(function ()
 {
 sleep(2);
 echo "c";
 });

Swoole\Runtime::enableCoroutine()The role is toPHPProvidedstreamsleeppdomysqliredisFunctions such as synchronous blocking are switched to asynchronous coordinated processing.IO

Results of implementation:

bchtf@LAPTOP-0K15EFQI:~$ time php  co.php
 bc
 real    0m2.076s
 user    0m0.000s
 sys     0m0.078s
 htf@LAPTOP-0K15EFQI:~$

As you can see, it’s only used here2The execution was completed in seconds.

  • Sequential execution time is equal to the sum of all task execution time:t1+t2+t3 ...
  • The concurrent execution time is equal to the maximum value of the execution time of all tasks:max(t1, t2, t3, ...)

Coordinated communication

i’ve got itgoAfter keywords, concurrent programming is much simpler. At the same time, it brings new problems, if any2One coordination process is executed concurrently, and the other coordination process depends on the execution results of the two coordination processes. What if this problem is solved?

The answer is to use channels (Channel), atSwoole4Use in coordinationnew chanYou can create a channel. Channels can be understood as queues with coordinated scheduling. It has two interfacespushAndpop

  • push: Writes content to the channel. If it is full, it will enter a waiting state and recover automatically when there is space.
  • pop: reads the content from the channel. if it is empty, it will enter the waiting state and automatically recover when there is data

The use of channels can be easily realizedConcurrent management.

$chan = new chan(2);
 
 # Concorde 1
 go (function () use ($chan) {
 $result = [];
 for ($i = 0;   $i < 2;  $i++)
 {
 $result += $chan->pop();
 }
 var_dump($result);
 });
 
 # Concorde 2
 go(function () use ($chan) {
 $cli = new Swoole\Coroutine\Http\Client('www.qq.com', 80);
 $cli->set(['timeout' => 10]);
 $cli->setHeaders([
 'Host' => "www.qq.com",
 "User-Agent" => 'Chrome/49.0.2587.3',
 'Accept' => 'text/html,application/xhtml+xml,application/xml',
 'Accept-Encoding' => 'gzip',
 ]);
 $ret = $cli->get('/');
 // $cli->body response content is too large, here use Http status code as test
 $chan->push(['www.qq.com' => $cli->statusCode]);
 });
 
 # Concorde 3
 go(function () use ($chan) {
 $cli = new Swoole\Coroutine\Http\Client('www.163.com', 80);
 $cli->set(['timeout' => 10]);
 $cli->setHeaders([
 'Host' => "www.163.com",
 "User-Agent" => 'Chrome/49.0.2587.3',
 'Accept' => 'text/html,application/xhtml+xml,application/xml',
 'Accept-Encoding' => 'gzip',
 ]);
 $ret = $cli->get('/');
 // $cli->body response content is too large, here use Http status code as test
 $chan->push(['www.163.com' => $cli->statusCode]);
 });

Results of implementation:

htf@LAPTOP-0K15EFQI:~/swoole-src/examples/5.0$ time php  co2.php
 array(2) {
 ["www.qq.com"]=>
 int(302)
 ["www.163.com"]=>
 int(200)
 }
 
 real    0m0.268s
 user    0m0.016s
 sys     0m0.109s
 htf@LAPTOP-0K15EFQI:~/swoole-src/examples/5.0$

Used heregoCreated3A journey2And coordination3Request separatelyqq.comAnd163.comHome page. coroutine1Need to getHttpThe result of the request. It is used here.chanTo achieve concurrent management.

  • coroutine1The channel is cycled twice.popBecause the queue is empty, it will enter a wait state
  • coroutine2And coordination3After the execution is completed, the meeting willpushData1Once the results are obtained, continue to execute downwards.

Delayed task

In coordination programming, it may be necessary to automatically carry out some tasks and clean up when coordination exits. similarlyPHPTheregister_shutdown_functionInSwoole4Can be used indeferImplementation.

Swoole\Runtime::enableCoroutine();
 
 go(function () {
 echo "a";
 defer(function () {
 echo "~a";
 });
 echo "b";
 defer(function () {
 echo "~b";
 });
 sleep(1);
 echo "c";
 });

Results of implementation:

htf@LAPTOP-0K15EFQI:~/swoole-src/examples/5.0$ time php  defer.php
 abc~b~a
 real    0m1.068s
 user    0m0.016s
 sys     0m0.047s
 htf@LAPTOP-0K15EFQI:~/swoole-src/examples/5.0$

Conclusion

Swoole4ProvidedGo + Chan + DeferForPHPHas brought a brand newCSPConcurrent programming mode. Flexible useSwoole4The features provided can solve the design and development of various complicated functions in the work.