详解PHP中curl_multi并发的实现


Posted in PHP onJune 08, 2020

PHP中的curl_multi系列函数可以实现同时请求多个URL来实现并发,而不是像普通curl函数那样请求后会阻塞,直到结果返回才进行下一个请求。因此在批量请求URL时可通过curl_multi系列函数提升程序的运行效率。

curl普通请求

$startTime = microtime(true);
$chArr = [];
$optArr = [
  CURLOPT_URL => 'http://www.httpbin.org/ip',
  CURLOPT_HEADER => 0,
  CURLOPT_RETURNTRANSFER => 1,
];
$result = [];

//创建多个curl资源并执行
for ($i=0; $i<10; $i++) {
  $chArr[$i] = curl_init();
  curl_setopt_array($chArr[$i], $optArr);
  $result[$i] = curl_exec($chArr[$i]);
  curl_close($chArr[$i]);
}

$endTime = microtime(true);
echo sprintf("use time: %.3f s".PHP_EOL, $endTime - $startTime);

use time: 6.080 s

curl_multi并发请求

$startTime = microtime(true);
$chArr = [];
$optArr = [
  CURLOPT_URL => 'http://www.httpbin.org/ip',
  CURLOPT_HEADER => 0,
  CURLOPT_RETURNTRANSFER => 1,
];
$result = [];

//创建多个curl资源
for ($i=0; $i<10; $i++) {
  $chArr[$i] = curl_init();
  curl_setopt_array($chArr[$i], $optArr);
}
//创建批处理curl句柄
$mh = curl_multi_init();
//将单个curl句柄添加到批处理curl句柄中
foreach ($chArr as $ch) {
  curl_multi_add_handle($mh, $ch);
}
//判断操作是否仍在执行的标识的引用
$active = null;
/**
 * 本次循环第一次处理 $mh 批处理中的 $ch 句柄,并将 $mh 批处理的执行状态写入 $active,
 * 当状态值等于 CURLM_CALL_MULTI_PERFORM 时,表明数据还在写入或读取中,执行循环,
 * 当第一次 $ch 句柄的数据写入或读取成功后,状态值变为 CURLM_OK ,跳出本次循环,进入下面的大循环中。
 */
do {
  //处理在批处理栈中的每一个句柄
  $mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
/**
 * 上面这段代码中,是可以直接使用 $active > 0 来作为 while 的条件,如下:
 * do {
 *  $mrc = curl_multi_exec($mh, $active);
 * } while ($active > 0);
 * 此时如果整个批处理句柄没有全部执行完毕时,系统会不停的执行 curl_multi_exec 函数,从而导致系统CPU占用会很高,
 * 因此一般不采用这种方案,可以通过 curl_multi_select 函数来达到没有需要读取的程序就阻塞住的目的。
 */

/**
 * $active 为 true 时,即 $mh 批处理之中还有 $ch 句柄等待处理,
 * $mrc == CURLM_OK,即上一次 $ch 句柄的读取或写入已经执行完毕。
 */
while ($active && $mrc == CURLM_OK) {
  /** 
   * 程序进入阻塞状态,直到批处理中有活动连接(即 $mh 批处理中还有可执行的 $ch 句柄),
   * 这样执行的好处是 $mh 批处理中的 $ch 句柄会在读取或写入数据结束后($mrc == CURLM_OK)进入阻塞阶段,
   * 而不会在整个 $mh 批处理执行时不停地执行 curl_multi_exec 函数,白白浪费CPU资源。
   */
   if (curl_multi_select($mh) != -1) {
    //程序退出阻塞状态继续执行需要处理的 $ch 句柄
    do {
      $mrc = curl_multi_exec($mh, $active);
    } while ($mrc == CURLM_CALL_MULTI_PERFORM);
  }
}

foreach ($chArr as $i=>$ch) {
  //获取某个curl句柄的返回值
  $result[$i] = curl_multi_getcontent($ch);
  //移除批处理句柄中的某个句柄资源
  curl_multi_remove_handle($mh, $ch);
}
//关闭一组curl句柄
curl_multi_close($mh);
$endTime = microtime(true);
echo sprintf("use time: %.3f s".PHP_EOL, $endTime - $startTime);

use time: 0.599 s

通过对比上述程序的运行时间可以得知,使用curl_multi系列函数并发请求要比普通的curl函数依次请求效率高很多。

到此这篇关于详解PHP中curl_multi并发的实现的文章就介绍到这了,更多相关PHP curl_multi并发内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木! 

PHP 相关文章推荐
php getsiteurl()函数
Sep 05 PHP
CentOS安装php v8js教程
Feb 26 PHP
php判断表是否存在的方法
Jun 18 PHP
php通过排列组合实现1到9数字相加都等于20的方法
Aug 03 PHP
教你识别简单的免查杀PHP后门
Sep 13 PHP
win7安装php框架Yii的方法
Jan 25 PHP
使用PHP处理数据库数据如何将数据返回客户端并显示当前状态
Feb 16 PHP
smarty的section嵌套循环用法示例
May 28 PHP
PHP中set_include_path()函数相关用法分析
Jul 18 PHP
浅析PHP中的闭包和匿名函数
Dec 25 PHP
Yii2框架类自动加载机制实例分析
May 02 PHP
PHP http请求超时问题解决方案
Nov 13 PHP
THINKPHP5.1 Config的配置与获取详解
Jun 08 #PHP
ThinkPHP5.1验证码功能实现的示例代码
Jun 08 #PHP
php框架CI(codeigniter)自动加载与自主创建对象操作实例分析
Jun 06 #PHP
CI框架简单分页类用法示例
Jun 06 #PHP
简单的php购物车代码
Jun 05 #PHP
实例化php类时传参的方法分析
Jun 05 #PHP
PHP页面静态化――纯静态与伪静态用法详解
Jun 05 #PHP
You might like
php中使用$_REQUEST需要注意的一个问题
2013/05/02 PHP
利用phpexcel把excel导入数据库和数据库导出excel实现
2014/01/09 PHP
php把session写入数据库示例
2014/02/26 PHP
PHP中file_exists函数不支持中文名的解决方法
2014/07/26 PHP
ThinkPHP提交表单时默认自动转义的解决方法
2014/11/25 PHP
php实现的简单数据库操作Model类
2016/11/16 PHP
js函数使用技巧之 setTimeout(function(){},0)
2009/02/09 Javascript
Jquery+JSon 无刷新分页实现代码
2010/04/01 Javascript
深入理解JavaScript系列(8) S.O.L.I.D五大原则之里氏替换原则LSP
2012/01/15 Javascript
解决window.opener=null;window.close(),只支持IE6不支持IE7,IE8的问题
2014/01/14 Javascript
Firefox中使用outerHTML的2种解决方法
2014/06/07 Javascript
深入探讨javascript中的数据类型
2015/03/04 Javascript
jQuery进行组件开发完整实例
2015/12/15 Javascript
微信小程序 action-sheet底部菜单详解
2016/10/27 Javascript
记一次vue去除#问题处理经过小结
2019/01/24 Javascript
为vue项目自动设置请求状态的配置方法
2019/06/09 Javascript
vue2.x 对象劫持的原理实现
2020/04/19 Javascript
Node.js文本文件BOM头的去除方法
2020/11/22 Javascript
js加减乘除精确运算方法实例代码
2021/01/17 Javascript
[07:57]DOTA2热力大趴狂欢夜 广州站活动回顾
2013/11/27 DOTA
django之session与分页(实例讲解)
2017/11/13 Python
微信小程序跳一跳游戏 python脚本跳一跳刷高分技巧
2018/01/04 Python
ubuntu系统下使用pm2设置nodejs开机自启动的方法
2018/05/12 NodeJs
Django发送邮件和itsdangerous模块的配合使用解析
2019/08/10 Python
Python 一行代码能实现丧心病狂的功能
2020/01/18 Python
CAT鞋英国官网:坚固耐用的靴子和鞋
2016/10/21 全球购物
巴西男士个人护理产品商店:SHOP4MEN
2017/08/07 全球购物
Carter’s OshKosh加拿大:购买婴幼儿服装和童装
2018/11/27 全球购物
Yves Rocher捷克官方网站:植物化妆品的创造者
2019/07/31 全球购物
俄语专业毕业生推荐信
2013/10/28 职场文书
倡议书格式
2014/04/14 职场文书
小学生运动会报道稿
2014/09/12 职场文书
2015年教师节贺卡寄语
2015/03/24 职场文书
golang特有程序结构入门教程
2021/06/02 Python
Java异常处理try catch的基本用法
2021/12/06 Java/Android
业余无线电通联Q语
2022/02/18 无线电