详解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 和 MySQL 开发的 8 个技巧
Jan 02 PHP
libmysql.dll与php.ini是否真的要拷贝到c:\windows目录下呢
Mar 15 PHP
Windows下安装Memcached的步骤说明
Apr 25 PHP
php中如何使对象可以像数组一样进行foreach循环
Aug 09 PHP
php生成数组的使用示例 php全组合算法
Jan 16 PHP
php的array数组和使用实例简明教程(容易理解)
Mar 20 PHP
PHP 5.3和PHP 5.4出现FastCGI Error解决方法
Feb 12 PHP
Zend Framework动作助手Url用法详解
Mar 05 PHP
php gd等比例缩放压缩图片函数
Jun 12 PHP
Windows下PHP开发环境搭建教程(Apache+PHP+MySQL)
Jun 13 PHP
Laravel 批量更新多条数据的示例
Nov 27 PHP
php适配器模式简单应用示例
Oct 23 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操作数组的一些函数整理介绍
2011/07/17 PHP
php 使用GD库为页面增加水印示例代码
2014/03/24 PHP
如何在HTML 中嵌入 PHP 代码
2015/05/13 PHP
解读PHP的Yii框架中请求与响应的处理流程
2016/03/17 PHP
PHP7.3.10编译安装教程
2019/10/08 PHP
javascript 打印内容方法小结
2009/11/04 Javascript
JQuery Tips(2) 关于$()包装集你不知道的
2009/12/14 Javascript
用原生js做个简单的滑动效果的回到顶部
2014/10/15 Javascript
Javascript基础教程之数据类型转换
2015/01/18 Javascript
认识Knockout及如何使用Knockout绑定上下文
2015/12/25 Javascript
jstree创建无限分级树的方法【基于ajax动态创建子节点】
2016/10/25 Javascript
详解微信小程序开发之城市选择器 城市切换
2017/01/17 Javascript
JavaScript中的遍历详解(多种遍历)
2017/04/07 Javascript
Angular2.0实现modal对话框的方法示例
2018/02/18 Javascript
Vue 页面切换效果之 BubbleTransition(推荐)
2018/04/08 Javascript
vue自定义filters过滤器
2018/04/26 Javascript
解决layui前端框架 form表单,table表等内置控件不显示的问题
2018/08/19 Javascript
vue swipe自定义组件实现轮播效果
2019/07/03 Javascript
vue+element导航栏高亮显示的解决方式
2019/11/12 Javascript
何时/使用 Vue3 render 函数的教程详解
2020/07/25 Javascript
vue中v-model对select的绑定操作
2020/08/31 Javascript
python实现bucket排序算法实例分析
2015/05/04 Python
详解Python中用于计算指数的exp()方法
2015/05/14 Python
Python命令行解析模块详解
2018/02/01 Python
Python简单获取网卡名称及其IP地址的方法【基于psutil模块】
2018/05/24 Python
python调用java的jar包方法
2018/12/15 Python
python爬取指定微信公众号文章
2018/12/20 Python
python微信聊天机器人改进版(定时或触发抓取天气预报、励志语录等,向好友推送)
2019/04/25 Python
Python创建自己的加密货币的示例
2021/03/01 Python
职称自我鉴定
2013/10/15 职场文书
学校花圃的标语
2014/06/18 职场文书
2014年挂职干部工作总结
2014/12/06 职场文书
地陪导游欢迎词
2015/01/26 职场文书
档案接收函格式
2015/01/30 职场文书
2015年度党员自我评价范文
2015/03/03 职场文书
「地球外少年少女」BD发售宣传CM公开
2022/03/21 日漫