PHP 如何实现异步

 

对于在短时间内需要重复执行某一简单功能的系统而言,异步是优化性能的必经之路。

实现异步的方式有两种:

1、模拟 HTTP 请求,这种方式每次都要经过三次握手,更适用于不同服务器之间的异步请求。

2、通过 CLI 与操作系统交互来实现。

一、模拟 HTTP 请求,每次执行的请求较慢,但因为异步,性能也会有极大的优化。

HTTP协议维基百科:http://zh.wikipedia.org/wiki/%E8%B6%85%E6%96%87%E6%9C%AC%E4%BC%A0%E8%BE%93%E5%8D%8F%E8%AE%AE

模拟 HTTP 请求有两种方式:CURL 与 SOCKET

CURL 实例如下:

$handle = curl_init();

curl_setopt($handle, CURLOPT_URL, 'http://www.ifeng.com');

curl_setopt($handle, CURLOPT_HEADER, false);

curl_setopt($handle, CURLOPT_BINARYTRANSFER, true);

curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);

$content = curl_exec($handle);

var_dump($content);

 

CURL 可模拟所有的浏览器操作,也可进行加密传输。

 

socket 实例如下:

$host = 'www.ifeng.com';

$path = '/index.shtml';

$params = 'a=1&b=2&c=3';

 

$errorNo = null;

$errorMessage = '';

$timeOut = 30;

 

$fp = @fsockopen($host, 80, $errorNo, $errorMessage, $timeOut);

if(!$fp) {

exit('scoket 创建失败:'.$errorMessage);

}

 

$request = '';

$request .= "POST ".$path." HTTP/1.1\r\n";

$request .= "Host: ".$host."\r\n";

$request .= "Connection: Close\r\n";

$request .= "Content-Type: application/x-www-form-urlencoded\r\n";

$request .= "Content-length: ".strlen($params)."\r\n\r\n";

$request .= $params;

 

fputs($fp, $request);

$response = '';

while(!feof($fp)) {

$response .= fgets($fp, 128);

}

fclose($fp);

 

 

二、通过 CLI 在命令行与操作系统进行交互,此种方式只适用于请求自己系统的资源

通过 CLI 也有多种实现方式,大致分为两类:异步与多进程

异步与多进程在原理上是一致的,都是让操作系统产生新的进程。

异步在于进程产生,执行完成后即消息,无法获知进程的状态。

多进程在于可以获取进程执行的状态,并控制杀死产生的子进程。

 

PHP没有自带的多进程处理机制,只能通过扩展来实现,如:pcntl 扩展

PHP 可以通过 exec,system,passthru,popen 等方式来实现。

 

PCNTL 实例如下:

$pid = pcntl_fork();

//echo $pid."<br/>";

if($pid == -1) {

exit('创建进程出错');

} elseif($pid) {

exit('这里是父进程');

} else {

//这里可以不用异步

$phpShell = '/usr/local/php5.3/bin/php -f ';

$phpFile = 'process.php';

$processes = array();

for($i = 0; $i < 500; $i++) {

system($phpShell.$phpFile, $status);

$processes[$i] = $status;

echo $i."<br/>";

}

//exit('这里是子进程');

}

 

process.php 代码:

file_put_contents('/tmp/process.log', "start<br/>\r\n", FILE_APPEND);

 

PHP异步实例代码:

//判断OS

$isWin = false;

if(strpos(strtoupper(PHP_OS), 'WIN') !== false) {

$isWin = true;

}

//进程数量控制

if($isWin) {

$command = 'tasklist | find "php.exe" /c';

} else {

$command = "ps -ef | grep 'bin/php -f' | wc -l";

}

$count = 200;

$limit = 20;

$flag = true;

while($flag) {

if($count <= 0) {

break;

}

$handler = popen($command, 'r');

$number = fread($handler, 512);

echo $number."\r\n<br/>";

pclose($handler);

if($number > $limit) {

//sleep(1);

continue;

}

 

for($i = 0; $i < 20; $i++) {

$command = "/usr/local/php5.3/bin/php -f process.php >> /tmp/process.log &";

$handler = popen($command, 'r');

if(!$handler) {

echo "命令执行失败\r\n";

//exit('命令执行失败');

}

pclose($handler);

}

$count = $count - $limit;

}

exit;

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章