在php中,没有多线程让编程变得简单。但在一些需要并发提升性能的场景下,显得有些无能为力,比如发起一些http请求。
但好在curl扩展可以让我们“并发”去请求网络资源。利用这个特点,我们能做很多有趣的事情。
最基础的,并发请求网络资源,提升处理速度。
并发访问代码
<?php class ConcurrencyHTTP { private $_requests; private $_callbacks; private $_currentIndex = 0; public function get($url, $header = array(), $timeout = 30) { $this->_requests[$this->_currentIndex++] = array( "url" => $url, "method" => "GET", "timeout" => $timeout, "header" => $header ); return $this; } public function post($url, $body, $header = array(), $timeout = 30) { $this->_requests[$this->_currentIndex++] = array( "url" => $url, "method" => "GET", "body" => $body, "timeout" => $timeout, "header" => $header ); return $this; } public function callback(callable $callback) { $currentIndex = $this->_currentIndex - 1; $this->_callbacks[$currentIndex] = $callback; return $this; } public function exec() { foreach ($this->_requests as $req) { $options = array( CURLOPT_HEADER => $req["header"], CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => $req["timeout"], CURLOPT_URL => $req["url"], ); if ($req["method"] == "POST") { $options[CURLOPT_POST] = true; if (is_array($req["body"])) { $options[CURLOPT_POSTFIELDS] = http_build_query($req['body']); } else { $options[CURLOPT_POSTFIELDS] = $req['body']; } } $ch = curl_init(); curl_setopt_array($ch, $options); $handles[] = $ch; } $mh = curl_multi_init(); foreach ($handles as $ch) { curl_multi_add_handle($mh, $ch); } $running = null; $finished = 0; do { curl_multi_exec($mh, $running); curl_multi_select($mh); while ($info = curl_multi_info_read($mh)) { $ch = $info['handle']; if ($info['result'] != CURLM_OK) { $code = $info['result']; $data = curl_error($ch); } else { $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); $data = curl_multi_getcontent($ch); } $index = array_search($ch, $handles, true); $this->_callbacks[$index]($data, $code); curl_multi_remove_handle($mh, $ch); curl_close($ch); $finished++; } } while ($running > 0); curl_multi_close($mh); } }
调用很简单,直接链式调用get和callback即可。get用于组装请求数据,callback用户设置数据到来时的回调函数。
$concurrency = new ConcurrencyHTTP(); $concurrency->get("http://baidu.com") ->callback(function($content, $code) { echo $content; echo $code; }) ->get("http://imhuchao.com") ->callback(function($content, $code) { echo $content; echo $code; }) ->exec();
在某些情况下,如果同一个服务我们有多个节点,我们可能需要取回响应速度比较快的节点。
获取最快的节点
上面的代码稍微改改就能实现,我们改动exec方法,增加一个fastestOne参数。当有数据返回时立即结束。改动结果如下:
public function exec($fastestOne = false) { foreach ($this->_requests as $req) { $options = array( CURLOPT_HEADER => $req["header"], CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => $req["timeout"], CURLOPT_URL => $req["url"], ); if ($req["method"] == "POST") { $options[CURLOPT_POST] = true; if (is_array($req["body"])) { $options[CURLOPT_POSTFIELDS] = http_build_query($req['body']); } else { $options[CURLOPT_POSTFIELDS] = $req['body']; } } $ch = curl_init(); curl_setopt_array($ch, $options); $handles[] = $ch; } $mh = curl_multi_init(); foreach ($handles as $ch) { curl_multi_add_handle($mh, $ch); } $running = null; $finished = 0; do { curl_multi_exec($mh, $running); curl_multi_select($mh); while ($info = curl_multi_info_read($mh)) { $ch = $info['handle']; if ($info['result'] != CURLM_OK) { $httpCode = $info['result']; $httpBody = curl_error($ch); } else { $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $httpBody = curl_multi_getcontent($ch); } $index = array_search($ch, $handles, true); $this->_callbacks[$index]($httpBody, $httpCode); curl_multi_remove_handle($mh, $ch); curl_close($ch); $finished++; } // 当有返回结果时,break跳出循环,不再等待其他结果 if ($fastestOne && $finished > 0) { break; } } while ($running > 0); curl_multi_close($mh); }
你可能还喜欢下面这些文章
shell中的if语法是最让我头疼的语法之一,它的判断就向使用USB插头一样——拿起来插入不行,翻转再插入还不行,再翻转插入行了!为了搞清楚这部分语言,我收集了一些文章关于if条件判断的用法,希望对你也有些帮助。一、基本语法if [ command ]; then 符合该条件执行的语句fiif [ command ];then 符合该条件执行的语句elif [ command ];then 符合该条件执行的语句else 符合该条件执行的语句fi语法说明bash shell会按顺序执行if语句,如果command执行后且它的返回状态是0,则会执行符合该条件执行的语
一、基本位操作|或&与~取反^异或<<左移>>右移二、位操作的常见用法1.获取某位的值#define BitGet(Number,pos) ((Number)|= 1<<(pos)) //把某位置1#define BitGet(Number,pos) ((Number) &= ~(1<<(pos)) //把某位置0#define BitGet(Number,pos) ((Number) >> (pos)&1)) //用宏得到某数的某位#define BitGet(Number,pos) ((Number) ^=
基于信息熵原理分词这个概念很早了,用php实现了个,一气呵成,代码自然是,反正我也没有二次检查,呵呵。不过耗费内存是真的,真的很消耗内存!写这个的好处就是我明白了很多东西…代码如下<?php/** * 基于信息熵的无词典分词*/class partword{ /** * 词语最大长度 */ public $maxwordlen = 5; /** * 需要进行分词的文字 */ public $text; /** * 字符串长度 */ private $len; /** * 切分的单个文字
一个将网页里面的(图片,链接地址)相对路径转化为绝对路径的php实现方法
抓取网页的时候有时候会需要下载里面的图片或者其他附件,但有的网页里面用的是相对路径,这时候就要转化为绝对路径。 /*** url补全,相对url转化为绝对url* 作用是补全url*/function url2abs($srcurl,$baseurl){ $srcinfo = parse_url($srcurl); //print_r($srcinfo); if(isset($srcinfo[‘scheme’])) { return $srcurl; } $baseinfo = parse_url($baseurl); $url = $baseinfo[‘sc
输入opensslj你如openssl交互界面OpenSSL>生成rsa私钥OpenSSL> genrsa -out private_key 1024Generating RSA private key, 1024 bit long modulus………………….++++++…………++++++e is 65537 (0x10001)生成公钥OpenSSL> rsa -in private_key -pubout -out public_keywriting RSA key
赞赏微信赞赏
支付宝赞赏