利用curl 多线程 模拟 并发的详解


Posted in PHP onJune 14, 2013

首先,先了解下 php中的curl多线程函数:

# curl_multi_add_handle
# curl_multi_close
# curl_multi_exec
# curl_multi_getcontent
# curl_multi_info_read
# curl_multi_init
# curl_multi_remove_handle
# curl_multi_select

一般来说,想到要用这些函数时,目的显然应该是要同时请求多个url,而不是一个一个依次请求,否则不如自己循环去调curl_exec好了。
步骤总结如下:
第一步:调用curl_multi_init
第二步:循环调用curl_multi_add_handle
这一步需要注意的是,curl_multi_add_handle的第二个参数是由curl_init而来的子handle。
第三步:持续调用curl_multi_exec
第四步:根据需要循环调用curl_multi_getcontent获取结果
第五步:调用curl_multi_remove_handle,并为每个字handle调用curl_close
第六步:调用curl_multi_close
这里有一个网上找的简单例子,其作者称为dirty的例子,(稍后我会说明为何dirty):
/*
Here's a quick and dirty example for curl-multi from PHP, tested on PHP 5.0.0RC1 CLI / FreeBSD 5.2.1
*/
$connomains = array(
"http://www.cnn.com/",
"http://www.canada.com/",
"http://www.yahoo.com/"
);
$mh = curl_multi_init();
foreach ($connomains as $i => $url) {
     $conn[$i]=curl_init($url);
      curl_setopt($conn[$i],CURLOPT_RETURNTRANSFER,1);
      curl_multi_add_handle ($mh,$conn[$i]);
}
do { $n=curl_multi_exec($mh,$active); } while ($active);
foreach ($connomains as $i => $url) {
      $res[$i]=curl_multi_getcontent($conn[$i]);
      curl_close($conn[$i]);
}
print_r($res);

整个使用过程差不多就是这样,但是,这个简单代码有个致命弱点,就是在do循环的那段,在整个url请求期间是个死循环,它会轻易导致CPU占用100%。

现在我们来改进它,这里要用到一个几乎没有任何文档的函数curl_multi_select了,虽然C的curl库对select有说明,但是,php里的接口和用法确与C中有不同。
把上面do的那段改成下面这样:

do {
                        $mrc = curl_multi_exec($mh,$active);
                } while ($mrc == CURLM_CALL_MULTI_PERFORM);
                while ($active and $mrc == CURLM_OK) {
                        if (curl_multi_select($mh) != -1) {
                                do {
                                        $mrc = curl_multi_exec($mh, $active);
                                } while ($mrc == CURLM_CALL_MULTI_PERFORM);
                        }
                }

因为$active要等全部url数据接受完毕才变成false,所以这里用到了curl_multi_exec的返回值判断是否还有数据,当有数据的时候就不停调用curl_multi_exec,暂时没有数据就进入select阶段,新数据一来就可以被唤醒继续执行。这里的好处就是CPU的无谓消耗没有了。

另外:还有一些细节的地方可能有时候要遇到:
控制每一个请求的超时时间,在curl_multi_add_handle之前通过curl_setopt去做:
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
判断是否超时了或者其他错误,在curl_multi_getcontent之前用:curl_error($conn[$i]);

这里我只是简单使用上述的dirty的例子(足够用了,并未发现cpu使用100%的情况)。
对“看点”(kandian.com)某一接口模拟并发,功能是向 memcache中读数据并写入数据。因为保密关系,相关数据及结果就不贴出了。

模拟了3次,第一次10线程同时请求1000次,第二次,100线程同时请求1000次,第三次,1000线程同时请求100次(已经相当费劲了,不敢在设置超过1000的多线程)。
看来curl多线程模拟并发还是有一定局限的。

另外还怀疑,可能会因为多线程延迟带来结果的大误差,对比数据发现。在初始化和set所用时间出入不大,差别处在get方法,因此可简单排除这点~~~

 

PHP 相关文章推荐
php 抽象类的简单应用
Sep 06 PHP
解析在zend Farmework下如何创立一个FORM表单
Jun 28 PHP
PHP调用C#开发的dll类库方法
Jul 28 PHP
php对象在内存中的存在形式分析
Feb 03 PHP
PHP实现动态web服务器方法
Jul 29 PHP
PHP框架Laravel学习心得体会
Oct 28 PHP
PHP图形操作之Jpgraph学习笔记
Dec 25 PHP
thinkphp实现分页显示功能
Dec 03 PHP
php实现的统计字数函数定义与使用示例
Jul 26 PHP
PHP实现QQ、微信和支付宝三合一收款码实例代码
Feb 19 PHP
PHP ajax+jQuery 实现批量删除功能实例代码小结
Dec 06 PHP
Thinkphp5.0框架视图view的模板布局用法分析
Oct 12 PHP
修改php.ini不生效问题解决方法(上传大于8M的文件)
Jun 14 #PHP
与文件上传有关的php配置参数总结
Jun 14 #PHP
解决File size limit exceeded 错误的方法
Jun 14 #PHP
使用PHP计算两个路径的相对路径
Jun 14 #PHP
深入解析PHP的引用计数机制
Jun 14 #PHP
深入解析PHP垃圾回收机制对内存泄露的处理
Jun 14 #PHP
Mysql的Root密码忘记,查看或修改的解决方法(图文介绍)
Jun 14 #PHP
You might like
php,ajax实现分页
2008/03/27 PHP
不使用php api函数实现数组的交换排序示例
2014/04/13 PHP
PHP获取短链接跳转后的真实地址和响应头信息的方法
2014/07/25 PHP
thinkphp数据查询和遍历数组实例
2014/11/28 PHP
详解php中空字符串和0之间的关系
2016/10/23 PHP
PHP二维数组去重算法
2016/12/17 PHP
PHPExcel中文帮助手册|PHPExcel使用方法(分享)
2017/06/09 PHP
Laravel5.1 框架响应基本用法实例分析
2020/01/04 PHP
javascript知识点收藏
2007/02/22 Javascript
如何使用jquery动态加载js,css文件实现代码
2013/04/03 Javascript
JS使用正则表达式除去字符串中重复字符的方法
2015/11/05 Javascript
Javascript中的数组常用方法解析
2016/06/17 Javascript
NodeJs——入门必看攻略
2016/06/27 NodeJs
基于jQuery实现左侧菜单栏可折叠功能
2016/12/27 Javascript
在百度搜索结果中去除掉一些网站的资料(通过js控制不让显示)
2017/05/02 Javascript
nodejs集成sqlite使用示例
2017/06/05 NodeJs
JS基于正则实现数字千分位用逗号分隔的方法
2017/06/16 Javascript
ES6使用Set数据结构实现数组的交集、并集、差集功能示例
2017/10/31 Javascript
vue-cli项目优化方法- 缩短首屏加载时间
2018/04/01 Javascript
vue-cli3环境变量与分环境打包的方法示例
2019/02/18 Javascript
详解超简单的react服务器渲染(ssr)入坑指南
2019/02/28 Javascript
ES6中let、const的区别及变量的解构赋值操作方法实例分析
2019/10/15 Javascript
js实现贪吃蛇小游戏(加墙)
2020/07/31 Javascript
PHP读取远程txt文档到数组并实现遍历
2020/08/25 Javascript
python docx 中文字体设置的操作方法
2018/05/08 Python
解决python3 json数据包含中文的读写问题
2018/05/10 Python
Django中的forms组件实例详解
2018/11/08 Python
pycharm运行程序时在Python console窗口中运行的方法
2018/12/03 Python
Python之修改图片像素值的方法
2019/07/03 Python
python opencv调用笔记本摄像头
2019/08/28 Python
Java面试中常遇到的问题,也是需要注意的几点
2013/08/30 面试题
中医药大学市场营销专业自荐信
2013/09/29 职场文书
九年级英语教学反思
2014/01/31 职场文书
电台广播稿范文
2015/08/19 职场文书
党员公开承诺书2016
2016/03/24 职场文书
不想升级Win11?教你彻底锁定老版Windows系统的方法(附下载地址)
2022/09/23 数码科技