在实际项目或者自己编写小工具(比如新闻聚合,商品价格监控,比价)的过程中, 通常需要从第3方网站或者API接口获取数据, 在需要处理1个URL队列时, 为了提高性能, 可以采用cURL提供的curl_multi_*族函数实现简单的并发.
本文将探讨两种具体的实现方法, 并对不同的方法做简单的性能对比.
1. 经典cURL并发机制及其存在的问题
经典的cURL实现机制在网上很容易找到, 比如参考PHP在线手册的如下实现方式:
function classic_curl($urls, $delay) {
$queue = curl_multi_init();
$map = array();
foreach ($urls as $url) {
// create cURL resources
$ch = curl_init();
// set URL and other appropriate options
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_TIMEOUT, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_NOSIGNAL, true);
// add handle
curl_multi_add_handle($queue, $ch);
$map[$url] = $ch;
}
$active = null;
// execute the handles
do {
$mrc = curl_multi_exec($queue, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
while ($active > 0 && $mrc == CURLM_OK) {
if (curl_multi_select($queue, 0.5) != -1) {
do {
$mrc = curl_multi_exec($queue, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}
$responses = array();
foreach ($map as $url=>$ch) {
$responses[$url] = callback(curl_multi_getcontent($ch), $delay);
curl_multi_remove_handle($queue, $ch);
curl_close($ch);
}
curl_multi_close($queue);
return $responses;
}
首先将所有的URL压入并发队列, 然后执行并发过程, 等待所有请求接收完之后进行数据的解析等后续处理. 在实际的处理过程中, 受网络传输的影响, 部分URL的内容会优先于其他URL返回, 但是经典cURL并发必须等待最慢的那个URL返回之后才开始处理, 等待也就意味着CPU的空闲和浪费. 如果URL队列很短, 这种空闲和浪费还处在可接受的范围, 但如果队列很长, 这种等待和浪费将变得不可接受.
2. 改进的Rolling cURL并发方式
仔细分析不难发现经典cURL并发还存在优化的空间, 优化的方式时当某个URL请求完毕之后尽可能快的去处理它, 边处理边等待其他的URL返回, 而不是等待那个最慢的接口返回之后才开始处理等工作, 从而避免CPU的空闲和浪费. 闲话不多说, 下面贴上具体的实现:
function rolling_curl($urls, $delay) {
$queue = curl_multi_init();
$map = array();
foreach ($urls as $url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_TIMEOUT, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_NOSIGNAL, true);
curl_multi_add_handle($queue, $ch);
$map[(string) $ch] = $url;
}
$responses = array();
do {
while (($code = curl_multi_exec($queue, $active)) == CURLM_CALL_MULTI_PERFORM) ;
if ($code != CURLM_OK) { break; }
// a request was just completed -- find out which one
while ($done = curl_multi_info_read($queue)) {
// get the info and content returned on the request
$info = curl_getinfo($done['handle']);
$error = curl_error($done['handle']);
$results = callback(curl_multi_getcontent($done['handle']), $delay);
$responses[$map[(string) $done['handle']]] = compact('info', 'error', 'results');
// remove the curl handle that just completed
curl_multi_remove_handle($queue, $done['handle']);
curl_close($done['handle']);
}
// Block for data in / output; error handling is done by curl_multi_exec
if ($active > 0) {
curl_multi_select($queue, 0.5);
}
} while ($active);
curl_multi_close($queue);
return $responses;
}
3. 两种并发实现的性能对比
改进前后的性能对比试验在LINUX主机上进行, 测试时使用的并发队列如下:
http://item.taobao.com/item.htm?id=14392877692
http://item.taobao.com/item.htm?id=16231676302
http://item.taobao.com/item.htm?id=17037160462
http://item.taobao.com/item.htm?id=5522416710
http://item.taobao.com/item.htm?id=16551116403
http://item.taobao.com/item.htm?id=14088310973
简要说明下实验设计的原则和性能测试结果的格式: 为保证结果的可靠, 每组实验重复20次, 在单次实验中, 给定相同的接口URL集合, 分别测量Classic(指经典的并发机制)和Rolling(指改进后的并发机制)两种并发机制的耗时(秒为单位), 耗时短者胜出(Winner), 并计算节省的时间(Excellence, 秒为单位)以及性能提升比例(Excel. %). 为了尽量贴近真实的请求而又保持实验的简单, 在对返回结果的处理上只是做了简单的正则表达式匹配, 而没有进行其他复杂的操作. 另外, 为了确定结果处理回调对性能对比测试结果的影响, 可以使用usleep模拟现实中比较负责的数据处理逻辑(如提取, 分词, 写入文件或数据库等).
性能测试中用到的回调函数为:
function callback($data, $delay) {
preg_match_all('/(.+)/iU', $data, $matches);
usleep($delay);
return compact('data', 'matches');
}
数据处理回调无延迟时: Rolling Curl略优, 但性能提升效果不明显.
------------------------------------------------------------------------------------------------ Delay: 0 micro seconds, equals to 0 milli seconds ------------------------------------------------------------------------------------------------ Counter Classic Rolling Winner Excellence Excel. % ------------------------------------------------------------------------------------------------ 1 0.1193 0.0390 Rolling 0.0803 67.31% 2 0.0556 0.0477 Rolling 0.0079 14.21% 3 0.0461 0.0588 Classic -0.0127 -21.6% 4 0.0464 0.0385 Rolling 0.0079 17.03% 5 0.0534 0.0448 Rolling 0.0086 16.1% 6 0.0540 0.0714 Classic -0.0174 -24.37% 7 0.0386 0.0416 Classic -0.0030 -7.21% 8 0.0357 0.0398 Classic -0.0041 -10.3% 9 0.0437 0.0442 Classic -0.0005 -1.13% 10 0.0319 0.0348 Classic -0.0029 -8.33% 11 0.0529 0.0430 Rolling 0.0099 18.71% 12 0.0503 0.0581 Classic -0.0078 -13.43% 13 0.0344 0.0225 Rolling 0.0119 34.59% 14 0.0397 0.0643 Classic -0.0246 -38.26% 15 0.0368 0.0489 Classic -0.0121 -24.74% 16 0.0502 0.0394 Rolling 0.0108 21.51% 17 0.0592 0.0383 Rolling 0.0209 35.3% 18 0.0302 0.0285 Rolling 0.0017 5.63% 19 0.0248 0.0553 Classic -0.0305 -55.15% 20 0.0137 0.0131 Rolling 0.0006 4.38% ------------------------------------------------------------------------------------------------ Average 0.0458 0.0436 Rolling 0.0022 4.8% ------------------------------------------------------------------------------------------------ Summary: Classic wins 10 times, while Rolling wins 10 times
数据处理回调延迟5毫秒: Rolling Curl完胜, 性能提升40%左右.
<span style="font-size: 14px; "><span style="font-family: Arial, Helvetica, sans-serif; ">------------------------------------------------------------------------------------------------ Delay: 5000 micro seconds, equals to 5 milli seconds ------------------------------------------------------------------------------------------------ Counter Classic Rolling Winner Excellence Excel. % ------------------------------------------------------------------------------------------------ 1 0.0658 0.0352 Rolling 0.0306 46.5% 2 0.0728 0.0367 Rolling 0.0361 49.59% 3 0.0732 0.0387 Rolling 0.0345 47.13% 4 0.0783 0.0347 Rolling 0.0436 55.68% 5 0.0658 0.0286 Rolling 0.0372 56.53% 6 0.0687 0.0362 Rolling 0.0325 47.31% 7 0.0787 0.0337 Rolling 0.0450 57.18% 8 0.0676 0.0391 Rolling 0.0285 42.16% 9 0.0668 0.0351 Rolling 0.0317 47.46% 10 0.0603 0.0317 Rolling 0.0286 47.43% 11 0.0714 0.0350 Rolling 0.0364 50.98% 12 0.0627 0.0215 Rolling 0.0412 65.71% 13 0.0617 0.0401 Rolling 0.0216 35.01% 14 0.0721 0.0226 Rolling 0.0495 68.65% 15 0.0701 0.0428 Rolling 0.0273 38.94% 16 0.0674 0.0352 Rolling 0.0322 47.77% 17 0.0452 0.0425 Rolling 0.0027 5.97% 18 0.0596 0.0366 Rolling 0.0230 38.59% 19 0.0679 0.0480 Rolling 0.0199 29.31% 20 0.0657 0.0338 Rolling 0.0319 48.55% ------------------------------------------------------------------------------------------------ Average 0.0671 0.0354 Rolling 0.0317 47.24% ------------------------------------------------------------------------------------------------ Summary: Classic wins 0 times, while Rolling wins 20 times</span></span>
通过上面的性能对比, 在处理URL队列并发的应用场景中Rolling cURL应该是更加的选择, 并发量非常大(1000+)时, 可以控制并发队列的最大长度, 比如20, 每当1个URL返回并处理完毕之后立即加入1个尚未请求的URL到队列中, 这样写出来的代码会更加健壮, 不至于并发数太大而卡死或崩溃. 详细的实现请参考: http://code.google.com/p/rolling-curl/

curl和Pythonrequests都是发送HTTP请求的强大工具。虽然curl是一种命令行工具,可让您直接从终端发送请求,但Python的请求库提供了一种更具编程性的方式来从Python代码中发送请求。将curl转换为Pythonrequestscurl命令的基本语法如下所示:curl[OPTIONS]URL将curl命令转换为Python请求时,我们需要将选项和URL转换为Python代码。这是一个示例curlPOST命令:curl-XPOSThttps://example.com/api

在Linux下更新curl版本,您可以按照以下步骤进行操作:检查当前curl版本:首先,您需要确定当前系统中安装的curl版本。打开终端,并执行以下命令:curl--version该命令将显示当前curl的版本信息。确认可用的curl版本:在更新curl之前,您需要确定可用的最新版本。您可以访问curl的官方网站(curl.haxx.se)或相关的软件源,查找最新版本的curl。下载curl源代码:使用curl或浏览器,下载您选择的curl版本的源代码文件(通常为.tar.gz或.tar.bz2

PHP8.1发布:引入curl多个请求并发处理近日,PHP官方发布了最新版本的PHP8.1,其中引入了一个重要的特性:curl多个请求并发处理。这个新特性为开发者提供了一个更加高效和灵活的方式来处理多个HTTP请求,极大地提升了性能和用户体验。在以往的版本中,处理多个请求往往需要通过创建多个curl资源,并使用循环来分别发送和接收数据。这种方式虽然能够实现目

从头到尾:如何使用php扩展cURL进行HTTP请求引言:在Web开发中,经常需要与第三方API或其他远程服务器进行通信。而使用cURL进行HTTP请求是一种常见而强大的方式。本文将介绍如何使用php扩展cURL来执行HTTP请求,并提供一些实用的代码示例。一、准备工作首先,确保php已安装cURL扩展。可以在命令行执行php-m|grepcurl查

现在很多热爱游戏的windows用户都进入了Steam客户端,可以搜索、下载和玩任何好游戏。但是,许多用户的个人资料可能具有完全相同的名称,这使得查找个人资料或什至将Steam个人资料链接到其他第三方帐户或加入Steam论坛以共享内容变得困难。为配置文件分配了一个唯一的17位id,它保持不变,用户无法随时更改,而用户名或自定义URL可以更改。无论如何,一些用户并不知道他们的Steamid,这对于了解这一点非常重要。如果您也不知道如何找到您帐户的Steamid,请不要惊慌。在这篇文

使用url进行编码和解码编码和解码的类java.net.URLDecoder.decode(url,解码格式)解码器.解码方法。转化成普通字符串,URLEncoder.decode(url,编码格式)将普通字符串变成指定格式的字符串packagecom.zixue.springbootmybatis.test;importjava.io.UnsupportedEncodingException;importjava.net.URLDecoder;importjava.net.URLEncoder

PHPCurl中如何处理网页的301重定向?在使用PHPCurl发送网络请求时,时常会遇到网页返回的301状态码,表示页面被永久重定向。为了正确处理这种情况,我们需要在Curl请求中添加一些特定的选项和处理逻辑。下面将详细介绍在PHPCurl中如何处理网页的301重定向,并提供具体的代码示例。301重定向处理原理301重定向是指服务器返回了一个30

在linux中,curl是一个非常实用的、用来与服务器之间传输数据的工具,是一个利用URL规则在命令行下工作的文件传输工具;它支持文件的上传和下载,是综合传输工具。curl提供了一大堆非常有用的功能,包括代理访问、用户认证、ftp上传下载、HTTP POST、SSL连接、cookie支持、断点续传等等。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

MinGW - 适用于 Windows 的极简 GNU
这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

SublimeText3 英文版
推荐:为Win版本,支持代码提示!

EditPlus 中文破解版
体积小,语法高亮,不支持代码提示功能

VSCode Windows 64位 下载
微软推出的免费、功能强大的一款IDE编辑器

ZendStudio 13.5.1 Mac
功能强大的PHP集成开发环境