详解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 MSSQL 存储过程的方法
Dec 24 PHP
PHP 判断常量,变量和函数是否存在
Apr 26 PHP
php session 错误
May 21 PHP
session在php5.3中的变化 session_is_registered() is deprecated in
Nov 12 PHP
php中Socket创建与监听实现方法
Jan 05 PHP
PHP经典面试题集锦
Mar 19 PHP
php微信公众平台开发类实例
Apr 01 PHP
PHP获取文件行数的方法
Jun 10 PHP
php微信高级接口群发 多客服
Jun 23 PHP
PHP CURL采集百度搜寻结果图片不显示问题的解决方法
Feb 03 PHP
实例解析php的数据类型
Oct 24 PHP
基于PHP实现堆排序原理及实例详解
Jun 19 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
基于AppServ,XAMPP,WAMP配置php.ini去掉警告信息(NOTICE)的方法详解
2013/05/07 PHP
深入解析php中的foreach问题
2013/06/30 PHP
PHP中判断变量为空的几种方法分享
2013/08/26 PHP
C#使用PHP服务端的Web Service通信实例
2014/04/08 PHP
[推荐]javascript 面向对象技术基础教程
2009/03/03 Javascript
AlertBox 弹出层信息提示框效果实现步骤
2010/10/11 Javascript
浅谈关于JavaScript的语言特性分析
2013/04/11 Javascript
JavaScript中几个重要的属性(this、constructor、prototype)介绍
2013/05/19 Javascript
js判断url是否有效的两种方法
2014/03/04 Javascript
浅谈jQuery中setInterval()方法
2015/07/07 Javascript
jQuery中通过ajax调用webservice传递数组参数的问题实例详解
2016/05/20 Javascript
JS中作用域和变量提升(hoisting)的深入理解
2016/10/31 Javascript
JS刷新父窗口的几种方式小结(推荐)
2016/11/09 Javascript
Bootstrap CSS组件之下拉菜单(dropdown)
2016/12/17 Javascript
在页面中引入js的两种方法(推荐)
2017/08/29 Javascript
JS控制鼠标拒绝点击某一按钮的实例
2017/12/29 Javascript
JS中Map和ForEach的区别
2018/02/05 Javascript
vue-router beforeEach跳转路由验证用户登录状态
2018/12/26 Javascript
js实现上下左右键盘控制div移动
2020/01/16 Javascript
详解element-ui 表单校验 Rules 配置 常用黑科技
2020/07/11 Javascript
python进阶教程之文本文件的读取和写入
2014/08/29 Python
Python实现Mysql数据库连接池实例详解
2017/04/11 Python
Python hashlib模块用法实例分析
2018/06/12 Python
使用python判断你是青少年还是老年人
2018/11/29 Python
Python PO设计模式的具体使用
2019/08/16 Python
美国女鞋品牌:naturalizer(娜然)
2016/08/01 全球购物
意大利珠宝店:Luxury Zone
2019/01/05 全球购物
通信工程专业个人找工作求职信范文
2013/09/21 职场文书
历史学专业毕业生求职信
2013/09/27 职场文书
大学生专科学习生活的自我评价
2013/12/07 职场文书
毕业证丢失证明
2014/01/15 职场文书
《口技》教学反思
2014/02/21 职场文书
办公用品质量保证书
2015/05/11 职场文书
2015年基层党支部工作总结
2015/05/21 职场文书
golang 如何通过反射创建新对象
2021/04/28 Golang
一文了解JavaScript用Element Traversal新属性遍历子元素
2021/11/27 Javascript