PHP 如何实现异步

对于在短时间内需要重复执行某一简单功能的系统而言,异步是优化性能的必经之路。
实现异步的方式有两种:
1、模拟 HTTP 请求,这种方式每次都要经过三次握手,更适用于不同服务器之间的异步请求。
2、通过 CLI 与操作系统交互来实现。
一、模拟 HTTP 请求,每次执行的请求较慢,但因为异步,性能也会有极大的优化。
HTTP协议维基百科:http://zh.wikipedia.org/wiki/超文本传输协议
模拟 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."
";
}
//exit('这里是子进程');
}

process.php 代码:
file_put_contents('/tmp/process.log', "start
\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;

posted @ 2016-05-08 16:43  菁武  阅读(830)  评论(0编辑  收藏  举报