This is a creation in Article, where the information may have evolved or changed.
Concurrency in PHP programming
Weekend to Beijing noodles Two companies, know a few technical cattle people, interview a lot of chat, feeling harvest quite abundant. Recognize the shortcomings of their own, but also to strengthen their confidence in computer learning. This article is a summary of one of the interview questions.
One of the questions in the interview was not answered very well, with the title: 3 HTTP requests concurrently, as long as one of the requests has the result, it returns and interrupts the other two.
At that time to consider the content of some deviation from the original intention, has been considering how to interrupt the HTTP request, presumably client->recv() before to determine whether the result has been generated, so the answer is to use the socket to send an HTTP request, the socket joined Libevent loop monitoring, in Callbac K to determine whether the results have been obtained, if the results have been obtained, return directly.
Later, the more I said, the more I felt wrong, since the result has been recv, it can not be considered as interrupting HTTP requests. Besides, I never used libevent. Later said also said two kinds of implementation, one is used curl_multi_init , and the other is implemented with Golang concurrency.
Golang's version was forgotten at close the time, and the results were not quite in line with test instructions.
This question did not answer up, the examiner also did not embarrass me. But the mind has been thinking, until the end of the interview to go downstairs a little understand what the meaning, may test is concurrent, process threading application. So summarize this article and talk about concurrency in PHP.
This article summarizes about PHP programming in five kinds of concurrency, the final Golang implementation is purely boring, can be ignored. If available, a libevent version will be added.
Curl_multi_init
The document says allows the processing of multiple CURL handles asynchronously. is really asynchronous. What you need to understand here is the select method, as explained in the documentation, Blocks until there is activity on any of the Curl_multi connections. . Understand the common asynchronous model should be able to understand, select, Epoll, are very famous, here quoted a very good article, interested to see the explanation.
<?php//build the individual requests as above, but does not execute them$ch_1 = Curl_init (' http:/ /www.baidu.com/'); $ch _2 = Curl_init (' http://www.baidu.com/'); curl_setopt ($ch _1, Curlopt_returntransfer, true); curl _setopt ($ch _2, Curlopt_returntransfer, true);//Build the Multi-curl handle, adding both $ch $mh = Curl_multi_init (); curl_ Multi_add_handle ($MH, $ch _1); Curl_multi_add_handle ($MH, $ch _2);/execute all queries simultaneously, and continue when All is complete$running = null;do {curl_multi_exec ($MH, $running); $ch = Curl_multi_select ($MH); if ($ch!== 0) {$info = Curl_multi_info_read ($MH); if ($info) {var_dump ($info); $response _1 = curl_multi_getcontent ($info [' handle ']); echo "$response _1 \ n"; Break }}} while ($running > 0);//close the Handlescurl_multi_remove_handle ($MH, $ch _1); Curl_multi_remove_handle ($MH, $ch _ 2); Curl_multi_close ($MH);
What I am setting here is that the select gets the result, exits the loop, and deletes it curl resource , thus achieving the purpose of canceling the HTTP request.
Swoole_client
swoole_clientProvides an asynchronous pattern, I forgot this. The sleep method here requires that the Swoole version is greater than or equal to 1.7.21, I have not risen to this version, so the direct exit can also.
<?php$client = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC);//设置事件回调函数$client->on("connect", function($cli) { $req = "GET / HTTP/1.1\r\n Host: www.baidu.com\r\n Connection: keep-alive\r\n Cache-Control: no-cache\r\n Pragma: no-cache\r\n\r\n"; for ($i=0; $i < 3; $i++) { $cli->send($req); }});$client->on("receive", function($cli, $data){ echo "Received: ".$data."\n"; exit(0); $cli->sleep(); // swoole >= 1.7.21});$client->on("error", function($cli){ echo "Connect failed\n";});$client->on("close", function($cli){ echo "Connection close\n";});//发起网络连接$client->connect('183.207.95.145', 80, 1);
Process
Ah, unexpectedly forget swoole_process, here will not pcntl module. But after writing the discovery, this is actually not the interruption of the request, but which first to read which, ignoring the back of the return value.
<?php$workers = [];$worker_num = 3;//创建的进程数$finished = false;$lock = new swoole_lock(SWOOLE_MUTEX);for($i=0;$i<$worker_num ; $i++){ $process = new swoole_process('process'); //$process->useQueue(); $pid = $process->start(); $workers[$pid] = $process;}foreach($workers as $pid => $process){ //子进程也会包含此事件 swoole_event_add($process->pipe, function ($pipe) use($process, $lock, &$finished) { $lock->lock(); if(!$finished){ $finished = true; $data = $process->read(); echo "RECV: " . $data.PHP_EOL; } $lock->unlock(); });}function process(swoole_process $process){ $response = 'http response'; $process->write($response); echo $process->pid,"\t",$process->callback .PHP_EOL;}for($i = 0; $i < $worker_num; $i++) { $ret = swoole_process::wait(); $pid = $ret['pid']; echo "Worker Exit, PID=".$pid.PHP_EOL;}
Pthreads
When compiling the Pthreads module, it is suggested that PHP must open zts when compiling, so it seems necessary to use the thread safe version. Wamp PHP is just the TS, directly under a DLL, the instructions in the document copied to the corresponding directory, the win under test. Not fully understood, the article said that PHP pthreads and POSIX pthreads is completely different. The code is a bit rotten, you need to look at the document more, experience.
<?phpclass Foo extends Stackable { public $url; public $response = null; public function __construct(){ $this->url = 'http://www.baidu.com'; } public function run(){}}class Process extends Worker { private $text = ""; public function __construct($text,$object){ $this->text = $text; $this->object = $object; } public function run(){ while (is_null($this->object->response)){ print " Thread {$this->text} is running\n"; $this->object->response = 'http response'; sleep(1); } }}$foo = new Foo();$a = new Process("A",$foo);$a->start();$b = new Process("B",$foo);$b->start();echo $foo->response;
Yield
Yield generates a generator that can break the function and send a message to generator with send.
The version of the co-process will be replenished later. Still in the study.
Golang
With go to achieve relatively simple, go home after check close, deal with panic on OK. The code is as follows:
package mainimport ( "fmt")func main() { var result chan string = make(chan string, 1) for index := 0; index< 3; index++ { go doRequest(result) } res, ok := <-result if ok { fmt.Println("received ", res) }}func doRequest(result chan string) { response := "http response" defer func() { if x := recover(); x != nil { fmt.Println("Unable to send: %v", x) } }() result <- response close(result)}
The above several methods, in addition to curl_multi_* seemingly meet the accident (not sure, to see the source code), the other methods are not interrupted after recv() the operation of the request, if you get response after the subsequent operation, then it is useful, otherwise there is no meaning. Think of the PHP operation may be too granular, guess C/s should be able to solve the problem.
When writing did not notice a problem, some of the way is the return value, some direct printing, so bad, should be used uniformly return worth the request results. Ability is limited, let's do it first.
Finally, to make an advertisement, the garlic is a commitment to high-end computer science education company, if you are interested in programming or the bottom of the computer, you may wish to go to their website to learn.
At the same time, the company has been hiring, if you have confidence in your ability, you can try. The company is very free and open, the main. There are also many cattle, ACM World champion, known to Daniel.
Company Master to do education, internal learning materials must be to force, I only see some of the operating system test questions, involving a wide range of knowledge, can be seen the average technical ability of the company how powerful.
If there are omissions in the article, mistakes, but also ask the gods to point out, help rookie progress, thank you.