个人理解在项目中使用消息队列一般是有如下几个原因:
1.把瞬间服务器的请求处理换成异步处理,缓解服务器的压力
2.实现数据顺序排列获取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <?php
$redis = new Redis(); $redis->connect('127.0.0.1',6379); for($i=0;$i<50;$i++){ try{ $redis->LPUSH('click',rand(1000,5000)); }catch(Exception $e){ echo $e->getMessage(); } }
|
在后台进行数据处理 守护进程 去处理数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <?php
$redis = new Redis(); $redis->pconnect('127.0.0.1',6379); while(true){ try{ $value = $redis->LPOP('click'); if(!$value){ break; } var_dump($value)."\n";
}catch(Exception $e){ echo $e->getMessage(); } }
|
1 2 3
| $.get("doAsync.php", { name: 'raykaeso',job:'PHP Programmer'});
|
1 2 3
| <?php pclose(popen('php /var/www/doAsync.php &', 'r'));
|
设置curl的超时时间 CURLOPT_TIMEOUT 为1 (最小为1),因此客户端需要等待1秒,curl请求地址必须为绝对路径
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <?php
$param = array( 'name'=>'raykaeso', 'job'=>'PHP Programmer' ); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL,"http://www.example.com/doAsync.php"); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($param)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_HEADER, false); curl_setopt($ch, CURLOPT_TIMEOUT, 1); curl_exec($ch); curl_close($ch);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <?php function doRequest($url, $param=array(),$timeout =10){ $urlParmas = parse_url($url); $host = $urlParmas['host']; $path = $urlParmas['path']; $port = isset($urlParmas['port'])? $urlParmas['port'] :80; $errno = 0; $errstr = '';
$fp = fsockopen($host, $port, $errno, $errstr, $timeout); $query = isset($param)? http_build_query($param) : ''; $out = "POST ".$path." HTTP/1.1\r\n"; $out .= "host:".$host."\r\n"; $out .= "content-length:".strlen($query)."\r\n"; $out .= "content-type:application/x-www-form-urlencoded\r\n"; $out .= "connection:close\r\n\r\n"; $out .= $query;
fputs($fp, $out); fclose($fp); } $url = 'http://www.example.com/doAsync.php'; $param = array( 'name'=>'raykaeso', 'job'=>'PHP Programmer' ); doRequest($url, $param);
|
注意:
1、如果使用Apache作为Web服务器,让PHP支持异步首先必须得在Apache配置文件httpd.conf配置enablesendfile on。
2、在异步执行的PHP文件中建议加上一下两个配置:
1 2 3 4
| ignore_user_abort(true); set_time_limit(0);
|
最后,引入 鸟哥 的 经典 fsockopen 分装 代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| <?php
function triggerRequest($url, $post_data = array(), $cookie = array()){ $method = "GET"; $url_array = parse_url($url); $port = isset($url_array['port'])? $url_array['port'] : 80; $fp = fsockopen($url_array['host'], $port, $errno, $errstr, 30); if (!$fp) …{ return FALSE; } $getPath = $url_array['path'] ."?". $url_array['query']; if(!empty($post_data))…{ $method = "POST"; } $header = $method . " " . $getPath; $header .= " HTTP/1.1\r\n"; $header .= "Host: ". $url_array['host'] . "\r\n ";
$header .= "Connection:Close\r\n"; if(!empty($cookie))…{ $_cookie = strval(NULL); foreach($cookie as $k => $v){ $_cookie .= $k."=".$v."; "; } $cookie_str = "Cookie: " . base64_encode($_cookie) ." \r\n"; $header .= $cookie_str; } if(!empty($post_data)){ $_post = strval(NULL); foreach($post_data as $k => $v)…{ $_post .= $k."=".$v."&"; } $post_str = "Content-Type: application/x-www-form-urlencoded\r\n"; $post_str .= "Content-Length: ". strlen($_post) ." \r\n"; $post_str .= $_post."\r\n\r\n "; $header .= $post_str; } fwrite($fp, $header); fclose($fp); return true; }
|