如何在PHP中使用Guzzle实现异步并行API请求?
使用Guzzle实现PHP并行HTTP请求优化响应时间
要解决逐个请求导致响应慢的问题,Guzzle自带的异步请求和并行处理机制就能搞定,下面是两种常用的实现方案:
前提:安装Guzzle
确保已经通过Composer安装了Guzzle:
composer require guzzlehttp/guzzle
方案一:用Promise批量处理少量并行请求
适合请求数量不多(比如几十以内)的场景,所有请求同时发起,总耗时接近最慢的单个请求。
<?php require 'vendor/autoload.php'; use GuzzleHttp\Client; use GuzzleHttp\Promise; // 初始化Guzzle客户端 $client = new Client(); // 你的目标API地址列表 $apiUrls = [ 'https://api.example.com/item/1', 'https://api.example.com/item/2', 'https://api.example.com/item/3', // 可添加更多URL ]; // 生成异步请求的Promise数组 $promises = []; foreach ($apiUrls as $url) { $promises[$url] = $client->getAsync($url)->then( // 请求成功:解析JSON响应 function ($response) { return json_decode($response->getBody(), true); }, // 请求失败:返回错误信息 function ($exception) use ($url) { return [ 'url' => $url, 'error_msg' => $exception->getMessage(), 'error_code' => $exception->getCode() ]; } ); } // 等待所有请求完成,获取结果 $results = Promise\unwrap($promises); // 也可以用Promise\all($promises)->wait(),效果一致 // 遍历处理最终结果 foreach ($results as $url => $data) { if (isset($data['error_msg'])) { echo "请求{$url}失败:{$data['error_msg']}(错误码:{$data['error_code']})\n"; } else { echo "请求{$url}成功,返回数据:" . print_r($data, true) . "\n"; } } ?>
方案二:用Pool处理大量请求(带并发限制)
如果请求数量超过几十甚至上百个,直接批量发起可能会触发第三方API的限流,或者占用过多本地资源。用Pool可以限制同时发起的请求数,避免这类问题。
<?php require 'vendor/autoload.php'; use GuzzleHttp\Client; use GuzzleHttp\Pool; use GuzzleHttp\Psr7\Request; // 初始化客户端 $client = new Client(); // 大量API地址列表 $apiUrls = [ 'https://api.example.com/item/1', 'https://api.example.com/item/2', // 可添加数百个URL ]; // 生成请求迭代器(用yield延迟生成请求,节省内存) $requestGenerator = function ($urls) { foreach ($urls as $url) { // 如果需要POST请求/自定义headers,可在这里修改Request参数 yield new Request('GET', $url); } }; // 配置Pool,设置并发数 $pool = new Pool($client, $requestGenerator($apiUrls), [ 'concurrency' => 5, // 同时最多发起5个请求,根据API限流规则调整 'fulfilled' => function ($response, $index) use ($apiUrls) { // 请求成功时即时处理结果 $data = json_decode($response->getBody(), true); echo "请求{$apiUrls[$index]}成功:" . print_r($data, true) . "\n"; }, 'rejected' => function ($reason, $index) use ($apiUrls) { // 请求失败时即时处理错误 echo "请求{$apiUrls[$index]}失败:{$reason->getMessage()}\n"; }, ]); // 启动Pool并等待所有请求完成 $pool->promise()->wait(); ?>
注意事项
- 并发数不要设置过高,一定要参考第三方API的限流规则,避免被封禁。
- 如果需要重试失败的请求,可以搭配Guzzle的重试中间件实现。
- 若要发送POST请求,只需把
getAsync换成postAsync,并在参数里传递form_params或json选项;Pool里的Request对象也可以设置body和headers。
内容的提问来源于stack exchange,提问作者Baran Batur
相关产品推荐
相关产品推荐

