详解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 相关文章推荐
一个MYSQL操作类
Nov 16 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(四)
Jun 23 PHP
php实现的DateDiff和DateAdd时间函数代码分享
Aug 16 PHP
smarty内置函数section的用法
Jan 22 PHP
WIN8.1下搭建PHP5.6环境
Apr 29 PHP
详解js异步文件加载器
Jan 24 PHP
Laravel Memcached缓存驱动的配置与应用方法分析
Oct 08 PHP
PHP strcmp()和strcasecmp()的区别实例
Nov 05 PHP
php 一维数组的循环遍历实现代码
Apr 10 PHP
PHP实现蛇形矩阵,回环矩阵及数字螺旋矩阵的方法分析
May 29 PHP
PHP Include文件实例讲解
Feb 15 PHP
Laravel数据库读写分离配置的方法
Oct 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 文件上传模型,支持多文件上传
2009/08/13 PHP
使用Thinkphp框架开发移动端接口
2015/08/05 PHP
9个比较实用的php代码片段
2016/03/15 PHP
提交表单后 PHP获取提交内容的实现方法
2016/05/25 PHP
YII框架http缓存操作示例
2019/04/29 PHP
php使用mysqli和pdo扩展,测试对比连接mysql数据库的效率完整示例
2019/05/09 PHP
javascript getElementsByTagName
2011/01/31 Javascript
基于jquery的跟随屏幕滚动代码
2012/07/24 Javascript
json数据处理技巧(字段带空格、增加字段、排序等等)
2013/06/14 Javascript
nodejs开发微博实例
2015/03/25 NodeJs
Javascript中神奇的this
2016/01/20 Javascript
javascript html5移动端轻松实现文件上传
2020/03/27 Javascript
图解prototype、proto和constructor的三角关系
2016/07/31 Javascript
两种JavaScript的AES加密方式(可与Java相互加解密)
2016/08/02 Javascript
AngularJS Controller作用域
2017/01/09 Javascript
如何让node运行es6模块文件及其原理详解
2018/12/11 Javascript
vue component 中引入less文件报错 Module build failed
2019/04/17 Javascript
24个解决实际问题的ES6代码片段(小结)
2020/02/02 Javascript
JS制作简易计算器的实例代码
2020/07/04 Javascript
vue+iview实现分页及查询功能
2020/11/17 Vue.js
Python迭代和迭代器详解
2016/11/10 Python
python实现求解列表中元素的排列和组合问题
2018/03/15 Python
python selenium 对浏览器标签页进行关闭和切换的方法
2018/05/21 Python
Python IDLE清空窗口的实例
2018/06/25 Python
对Tensorflow中的变量初始化函数详解
2018/07/27 Python
Python从ZabbixAPI获取信息及实现Zabbix-API 监控的方法
2018/09/17 Python
python算法题 链表反转详解
2019/07/02 Python
python写一个随机点名软件的实例
2019/11/28 Python
Python第三方库的几种安装方式(小结)
2020/04/03 Python
python使用openpyxl操作excel的方法步骤
2020/05/28 Python
无需JS和jQuery代码实现CSS3鼠标浮动放大图片
2016/11/21 HTML / CSS
巴西本土电商平台:Americanas
2020/06/21 全球购物
证婚人搞笑证婚词
2014/01/10 职场文书
红白喜事主持词
2015/07/06 职场文书
2015教师个人师德工作总结
2015/10/23 职场文书
吃通javascript正则表达式
2021/04/21 Javascript