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 相关文章推荐
php5 and xml示例
Nov 22 PHP
小谈php正则提取图片地址
Mar 27 PHP
Codeigniter出现错误提示Error with CACHE directory的解决方案
Jun 12 PHP
PHP实现PDO的mysql数据库操作类
Dec 12 PHP
PHP 错误处理机制
Jul 06 PHP
Laravel 中获取上一篇和下一篇数据
Jul 27 PHP
php提取身份证号码中的生日日期以及验证是否为成年人的函数
Sep 29 PHP
PHP中substr_count()函数获取子字符串出现次数的方法
Jan 07 PHP
PHP快速生成各种信息提示框的方法
Feb 03 PHP
总结PHP删除字符串最后一个字符的三种方法
Aug 30 PHP
PHP 命名空间和自动加载原理与用法实例分析
Apr 29 PHP
PHP实现抽奖功能实例代码
Jun 30 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
yii2分页之实现跳转到具体某页的实例代码
2016/06/02 PHP
PHP实现适用于文件内容操作的分页类
2016/06/15 PHP
如何离线执行php任务
2017/02/21 PHP
Locate a File Using a File Open Dialog Box
2007/06/18 Javascript
深入理解javaScript中的事件驱动
2013/05/21 Javascript
复选框全选与全不选操作实现思路
2013/08/18 Javascript
jquery中常用的SET和GET$(”#msg”).html循环介绍
2013/10/09 Javascript
JavaScript function 的 length 属性使用介绍
2014/09/15 Javascript
浅谈jQuery中 wrap() wrapAll() 与 wrapInner()的差异
2014/11/12 Javascript
JavaScript函数作用域链分析
2015/02/13 Javascript
10条建议帮助你创建更好的jQuery插件
2015/05/18 Javascript
轻松实现jquery手风琴效果
2016/01/14 Javascript
Bootstrap基本插件学习笔记之Popover提示框(19)
2016/12/08 Javascript
一步步教你利用webpack如何搭一个vue脚手架(超详细讲解和注释)
2018/01/08 Javascript
nginx+vue.js实现前后端分离的示例代码
2018/02/12 Javascript
Cookbook组件形式:优化 Vue 组件的运行时性能
2018/11/25 Javascript
基于element-ui组件手动实现单选和上传功能
2018/12/06 Javascript
微信小程序实现Swiper轮播图效果
2019/11/22 Javascript
基于原生JS封装的Modal对话框插件的示例代码
2020/09/09 Javascript
Python 调用DLL操作抄表机
2009/01/12 Python
对Python中DataFrame选择某列值为XX的行实例详解
2019/01/29 Python
Python实现的对本地host127.0.0.1主机进行扫描端口功能示例
2019/02/15 Python
python常用函数与用法示例
2019/07/02 Python
利用python实现短信和电话提醒功能的例子
2019/08/08 Python
Python常用base64 md5 aes des crc32加密解密方法汇总
2020/11/06 Python
pytorch简介
2020/11/11 Python
Selenium关闭INFO:CONSOLE提示的解决
2020/12/07 Python
新西兰演唱会和体育门票网站:Ticketmaster新西兰
2017/10/07 全球购物
Blue Nile中国官网:全球知名的钻石和珠宝网络零售商
2020/03/22 全球购物
2015入党自荐书范文
2015/03/05 职场文书
公积金具结保证书
2015/05/11 职场文书
行为规范主题班会
2015/08/13 职场文书
导游词之无锡梅园
2019/11/28 职场文书
吃通javascript正则表达式
2021/04/21 Javascript
pytorch 梯度NAN异常值的解决方案
2021/06/05 Python
前端与RabbitMQ实时消息推送未读消息小红点实现示例
2022/07/23 Java/Android