0

0

php如何实现并发请求(代码)

不言

不言

发布时间:2018-09-11 15:08:40

|

11321人浏览过

|

来源于php中文网

原创

本篇文章给大家带来的内容是关于php如何实现并发请求(代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

后端服务开发中经常会有并发请求的需求,比如你需要获取10家供应商的带宽数据(每个都提供不同的url),然后返回一个整合后的数据,你会怎么做呢?

PHP中,最直观的做法foreach遍历urls,并保存每个请求的结果即可,那么如果供应商提供的接口平均耗时5s,你的这个接口请求耗时就达到了50s,这对于追求速度和性能的网站来说是不可接受的。

这个时候你就需要并发请求了。

PHP请求

PHP是单进程同步模型,一个请求对应一个进程,I/O是同步阻塞的。通过nginx/apache/php-fpm等服务的扩展,才使得PHP提供高并发的服务,原理就是维护一个进程池,每个请求服务时单独起一个新的进程,每个进程独立存在。

立即学习PHP免费学习笔记(深入)”;

PHP不支持多线程模式和回调处理,因此PHP内部脚本都是同步阻塞式的,如果你发起一个5s的请求,那么程序就会I/O阻塞5s,直到请求返回结果,才会继续执行代码。因此做爬虫之类的高并发请求需求很吃力。

那怎么来解决并发请求的问题呢?除了内置的file_get_contentsfsockopen请求方式,PHP也支持cURL扩展来发起请求,它支持常规的单个请求:PHP cURL请求详解,也支持并发请求,其并发原理是cURL扩展使用多线程来管理多请求。

PHP并发请求

我们直接来看代码demo:

// 简单demo,默认支持为GET请求
public function multiRequest($urls) {
    $mh = curl_multi_init();
    $urlHandlers = [];
    $urlData = [];
    // 初始化多个请求句柄为一个
    foreach($urls as $value) {
        $ch = curl_init();
        $url = $value['url'];
        $url .= strpos($url, '?') ? '&' : '?';
        $params = $value['params'];
        $url .= is_array($params) ? http_build_query($params) : $params;
        curl_setopt($ch, CURLOPT_URL, $url);
        // 设置数据通过字符串返回,而不是直接输出
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        $urlHandlers[] = $ch;
        curl_multi_add_handle($mh, $ch);
    }
    $active = null;
    // 检测操作的初始状态是否OK,CURLM_CALL_MULTI_PERFORM为常量值-1
    do {
        // 返回的$active是活跃连接的数量,$mrc是返回值,正常为0,异常为-1
        $mrc = curl_multi_exec($mh, $active);
    } while ($mrc == CURLM_CALL_MULTI_PERFORM);
    // 如果还有活动的请求,同时操作状态OK,CURLM_OK为常量值0
    while ($active && $mrc == CURLM_OK) {
        // 持续查询状态并不利于处理任务,每50ms检查一次,此时释放CPU,降低机器负载
        usleep(50000);
        // 如果批处理句柄OK,重复检查操作状态直至OK。select返回值异常时为-1,正常为1(因为只有1个批处理句柄)
        if (curl_multi_select($mh) != -1) {
            do {
                $mrc = curl_multi_exec($mh, $active);
            } while ($mrc == CURLM_CALL_MULTI_PERFORM);
        }
    }
    // 获取返回结果
    foreach($urlHandlers as $index => $ch) {
        $urlData[$index] = curl_multi_getcontent($ch);
        // 移除单个curl句柄
        curl_multi_remove_handle($mh, $ch);
    }
    curl_multi_close($mh);
    return $urlData;
}

在该并发请求中,先创建一个批处理句柄,然后将urlcURL句柄添加到批处理句柄中,并不断查询批处理句柄的执行状态,当执行完成后,获取返回的结果。

curl_multi 相关函数

/** 函数作用:返回一个新cURL批处理句柄
    @return resource 成功返回cURL批处理句柄,失败返回false
*/
resource curl_multi_init ( void )

/** 函数作用:向curl批处理会话中添加单独的curl句柄
    @param $mh 由curl_multi_init返回的批处理句柄
    @param $ch 由curl_init返回的cURL句柄
    @return resource 成功返回cURL批处理句柄,失败返回false
*/
int curl_multi_add_handle ( resource $mh , resource $ch )

/** 函数作用:运行当前 cURL 句柄的子连接
    @param $mh 由curl_multi_init返回的批处理句柄
    @param $still_running 一个用来判断操作是否仍在执行的标识的引用
    @return 一个定义于 cURL 预定义常量中的 cURL 代码
*/
int curl_multi_exec ( resource $mh , int &$still_running )

/** 函数作用:等待所有cURL批处理中的活动连接
    @param $mh 由curl_multi_init返回的批处理句柄
    @param $timeout 以秒为单位,等待响应的时间
    @return 成功时返回描述符集合中描述符的数量。失败时,select失败时返回-1,否则返回超时(从底层的select系统调用).
*/
int curl_multi_select ( resource $mh [, float $timeout = 1.0 ] )

/** 函数作用:移除cURL批处理句柄资源中的某个句柄资源
    说明:从给定的批处理句柄mh中移除ch句柄。当ch句柄被移除以后,仍然可以合法地用curl_exec()执行这个句柄。如果要移除的句柄正在被使用,则这个句柄涉及的所有传输任务会被中止。
    @param $mh 由curl_multi_init返回的批处理句柄
    @param $ch 由curl_init返回的cURL句柄
    @return 成功时返回0,失败时返回CURLM_XXX中的一个
*/
int curl_multi_remove_handle ( resource $mh , resource $ch )

/** 函数作用:关闭一组cURL句柄
    @param $mh 由curl_multi_init返回的批处理句柄
    @return void
*/
void curl_multi_close ( resource $mh )

/** 函数作用:如果设置了CURLOPT_RETURNTRANSFER,则返回获取的输出的文本流
    @param $ch 由curl_init返回的cURL句柄
    @return string 如果设置了CURLOPT_RETURNTRANSFER,则返回获取的输出的文本流。
*/
string curl_multi_getcontent ( resource $ch )
本例中使用到的预定义常量:
CURLM_CALL_MULTI_PERFORM: (int) -1
CURLM_OK: (int) 0

PHP并发请求耗时对比

  1. 第一次请求使用上面的curl_multi_init方法,并发请求105次。

  2. 第二次请求使用传统的foreach方法,遍历105次使用curl_init方法请求。

实际的请求耗时结果为:

易企CMS1.8
易企CMS1.8

易企CMS:国内首款完全基于SEO友好性开发的营销型企业网站系统,让企业网络营销从此易如反掌。 本程序特征:100%开发源代码,免费开源;后台管理操作简单易行;模板div+css标准设计,符合w3c标准,兼容主流浏览器;开发语言和数据库:PHP+Mysql。 本程序亮点:从基础代码开发起完全符合SEOWHY理论的SEO规范,力图实现国内首款对SEO最友好的企业网站开源程序,为企业网络营销的巨大成功

下载

433410620-5b965e6a51814_articlex.png

刨除download的约765ms耗时,单纯的请求耗时优化达到了39.83/1.58达到了25倍,如果继续刨除建连相关的耗时,应该会更高。这其中的耗时:

  • 方案1:最慢的一个接口达到了1.58s

  • 方案2:105个接口的平均耗时是384ms

这个测试的请求是我的环境的内部接口,所以耗时很短,实际爬虫请求环境优化会更明显。

注意项

并发数限制

curl_multi会消耗很多的系统资源,在并发请求时并发数有一定阈值,一般为512,是由于CURL内部限制,超过最大并发会导致失败。

具体的测试结果我没有做,可以参考别人的文章:每次使用curl multi同时并发多少请求合适

超时时间

为了防止慢请求影响整个服务,可以设置CURLOPT_TIMEOUT来控制超时时间,防止部分假死的请求无限阻塞进程处理,最后打死机器服务。

CPU负载打满

在代码示例中,如果持续查询并发的执行状态,会导致cpu的负载过高,所以,需要在代码里加上usleep(50000);的语句。
同时,curl_multi_select也可以控制cpu占用,在数据有回应前会一直处于等待状态,新数据一来就会被唤醒并继续执行,减少了CPU的无谓消耗。

相关推荐:

AJAX的队列请求如何实现(附代码)

PHP使用curl_multi实现并发请求的方法示例php技巧

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
nginx 重启
nginx 重启

nginx重启对于网站的运维来说是非常重要的,根据不同的需求,可以选择简单重启、平滑重启或定时重启等方式。本专题为大家提供nginx重启的相关的文章、下载、课程内容,供大家免费下载体验。

233

2023.07.27

nginx 配置详解
nginx 配置详解

Nginx的配置是指设置和调整Nginx服务器的行为和功能的过程。通过配置文件,可以定义虚拟主机、HTTP请求处理、反向代理、缓存和负载均衡等功能。Nginx的配置语法简洁而强大,允许管理员根据自己的需要进行灵活的调整。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

502

2023.08.04

nginx配置详解
nginx配置详解

NGINX与其他服务类似,因为它具有以特定格式编写的基于文本的配置文件。本专题为大家提供nginx配置相关的文章,大家可以免费学习。

500

2023.08.04

tomcat和nginx有哪些区别
tomcat和nginx有哪些区别

tomcat和nginx的区别:1、应用领域;2、性能;3、功能;4、配置;5、安全性;6、扩展性;7、部署复杂性;8、社区支持;9、成本;10、日志管理。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

234

2024.02.23

nginx报404怎么解决
nginx报404怎么解决

当访问 nginx 网页服务器时遇到 404 错误,表明服务器无法找到请求资源,可以通过以下步骤解决:1. 检查文件是否存在且路径正确;2. 检查文件权限并更改为 644 或 755;3. 检查 nginx 配置,确保根目录设置正确、没有冲突配置等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

341

2024.07.09

Nginx报404错误解决方法
Nginx报404错误解决方法

解决方法:只需要加上这段配置:try_files $uri $uri/ /index.html;即可。想了解更多Nginx的相关内容,可以阅读本专题下面的文章。

3520

2024.08.07

nginx部署php项目教程汇总
nginx部署php项目教程汇总

本专题整合了nginx部署php项目教程汇总,阅读专题下面的文章了解更多详细内容。

33

2026.01.13

nginx配置文件详细教程
nginx配置文件详细教程

本专题整合了nginx配置文件相关教程详细汇总,阅读专题下面的文章了解更多详细内容。

53

2026.01.13

C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

9

2026.01.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Node.js 教程
Node.js 教程

共57课时 | 9.8万人学习

Vue 教程
Vue 教程

共42课时 | 7.5万人学习

ASP 教程
ASP 教程

共34课时 | 4.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号