PHP使用curl_multi_select解决curl_multi网页假死问题的方法


Posted in PHP onAugust 15, 2018

本文实例讲述了PHP使用curl_multi_select解决curl_multi网页假死问题的方法。分享给大家供大家参考,具体如下:

curl_multi可以批处理事务,给网页编程带来很大的方便。不过在使用curl_multi的过程中,我们会遇到一个比较头疼的问题,那就是当并发处理的事务数量过多的时候,就会出现CPU过高,网页假死的现象,这是不可以忽视的。

今天,通过查询相关资料和测试,终于找到了一个解决问题的方法。

正常情况下,我们是这样使用curl_multi的。

实例代码:

$connomains = array(
"//3water.com/",
"http://www.163.com/",
"http://www.sina.com.cn/"
);
$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占用很高,网页出现假死状态。

经过测试发现,我们可以巧妙使用curl_multi_select()函数来解决这个问题。

方法如下:

do { $n=curl_multi_exec($mh,$active); } while ($active);

改为

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]);

了解multi接口

当程序需要进行多次curl并发请求的时候,curl提供的multi接口就派上用场了。流畅大致是这样的:

1)、curl_multi _init初始化一个multi curl对象,为了同时进行多个curl的并发访问,我们需要初始化多个easy curl对象,使用curl_easy_setopt进行相关设置。

2)、调用curl_multi _add_handle把easy curl对象添加到multi curl对象中。

3)、添加完毕后执行curl_multi_perform方法进行并发的访问。

4)、访问结束后curl_multi_remove_handle移除相关easy curl对象,curl_easy_cleanup清除easy curl对象。

5)、最后curl_multi_cleanup清除multi curl对象。

一个简单明了的PHP使用curl_multi_add_handle并行处理实例

<?php
// 创建一对cURL资源
$ch1 = curl_init();
$ch2 = curl_init();
// 设置URL和相应的选项
curl_setopt($ch1, CURLOPT_URL, "//3water.com/");
curl_setopt($ch1, CURLOPT_HEADER, 0);
curl_setopt($ch2, CURLOPT_URL, "http://www.baidu.com/");
curl_setopt($ch2, CURLOPT_HEADER, 0);
// 创建批处理cURL句柄
$mh = curl_multi_init();
// 增加2个句柄
curl_multi_add_handle($mh,$ch1);
curl_multi_add_handle($mh,$ch2);
$running=null;
// 执行批处理句柄
do {
  curl_multi_exec($mh,$running);
} while($running > 0);
// 关闭全部句柄
curl_multi_remove_handle($mh, $ch1);
curl_multi_remove_handle($mh, $ch2);
curl_multi_close($mh);
?>

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
PHP面向对象编程快速入门
Dec 14 PHP
PHP中冒号、endif、endwhile、endfor使用介绍
Apr 28 PHP
linux系统上支持php的 iconv()函数的方法
Oct 01 PHP
ci检测是ajax还是页面post提交数据的方法
Nov 10 PHP
php动态变量定义及使用
Jun 10 PHP
php获取本机真实IP地址实例代码
Mar 31 PHP
php用户登录之cookie信息安全分析
May 13 PHP
php中json_encode不兼容JSON_UNESCAPED_UNICODE的解决方案
May 31 PHP
Laravel中使用Queue的最基本操作教程
Dec 27 PHP
laravel 之 Eloquent 模型修改器和序列化示例
Oct 17 PHP
PHP实现获取文件mime类型多种方法解析
May 28 PHP
PHP实现rar解压读取扩展包小结
Jun 03 PHP
php+croppic.js实现剪切上传图片功能
Aug 14 #PHP
PHP设计模式之委托模式定义与用法简单示例
Aug 13 #PHP
PHP设计模式之建造者模式定义与用法简单示例
Aug 13 #PHP
PHP设计模式之装饰器模式定义与用法简单示例
Aug 13 #PHP
PHP实现的ID混淆算法类与用法示例
Aug 10 #PHP
PHP+ajax实现二级联动菜单功能示例
Aug 10 #PHP
PHP实现十进制数字与二十六进制字母串相互转换操作示例
Aug 10 #PHP
You might like
索尼SONY SRF-S83/84电路分析和打磨
2021/03/02 无线电
PHP 获取远程网页内容的代码(fopen,curl已测)
2011/06/06 PHP
php面向对象中的魔术方法中文说明
2014/03/04 PHP
配置php.ini实现PHP文件上传功能
2014/11/27 PHP
PHP中preg_match函数正则匹配的字符串长度问题
2015/05/27 PHP
prototype 源码中文说明之 prototype.js
2006/09/22 Javascript
JavaScript中yield实用简洁实现方式
2010/06/12 Javascript
IE6浏览器下resize事件被执行了多次解决方法
2012/12/11 Javascript
js判读浏览器是否支持html5的canvas的代码
2013/11/18 Javascript
全面解析Bootstrap中form、navbar的使用方法
2016/05/30 Javascript
jQuery文字横向滚动效果的实现代码
2016/05/31 Javascript
javaScript给元素添加多个class的简单实现
2016/07/20 Javascript
jquery 追加元素append、prepend、before、after用法与区别分析
2016/12/02 Javascript
用户管理的设计_jquery的ajax实现二级联动效果
2017/07/13 jQuery
在vue项目中使用md5加密的方法
2018/09/14 Javascript
Element-ui中元素滚动时el-option超出元素区域的问题
2019/05/30 Javascript
解决Vue watch里调用方法的坑
2020/11/07 Javascript
[46:04]Liquid vs VP Supermajor决赛 BO 第四场 6.10
2018/07/05 DOTA
[03:11]TI9战队档案 - Alliance
2019/08/20 DOTA
Python合并多个Excel数据的方法
2018/07/16 Python
python实现一组典型数据格式转换
2018/12/15 Python
Python3.5字符串常用操作实例详解
2019/05/01 Python
简单了解Python3里的一些新特性
2019/07/13 Python
使用Python实现画一个中国地图
2019/11/23 Python
详解Python3中的 input() 函数
2020/03/18 Python
Python实现发票自动校核微信机器人的方法
2020/05/22 Python
PyTorch安装与基本使用详解
2020/08/31 Python
Python Pandas list列表数据列拆分成多行的方法实现
2020/12/14 Python
HTML5新表单元素_动力节点Java学院整理
2017/07/12 HTML / CSS
美国流行背包品牌:JanSport(杰斯伯)
2018/03/02 全球购物
干部鉴定材料
2014/05/18 职场文书
疾病防治方案
2014/05/31 职场文书
汉语言文学专业自荐信
2014/06/11 职场文书
护士个人总结范文
2015/02/13 职场文书
建筑技术负责人岗位职责
2015/04/13 职场文书
简单介绍Python的第三方库yaml
2021/06/18 Python