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;

 

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