如何使用Guzzle PHP在批量HTTP请求包之间设置1秒延迟?
用Guzzle实现分组异步请求并添加组间延迟
完全可以通过Guzzle实现你的需求,推荐使用Pool组件——它比直接批量创建getAsync promise更适合控制并发数和请求调度,能有效避免瞬间发送大量请求导致的封禁问题。
核心思路
将请求按每10个一组拆分,每组内部并发发送请求,组与组之间等待1秒再执行下一组。这种方式既保证了批量请求的效率,又能控制对目标域名的请求频率。
改造后的代码示例
use GuzzleHttp\Pool; use GuzzleHttp\Psr7\Request; use GuzzleHttp\Exception\RequestException; use Psr\Http\Message\ResponseInterface; // 1. 将请求数据按每10个一组拆分 $groups = array_chunk($data, 10); $results = []; foreach ($groups as $groupIndex => $group) { // 非第一组执行1秒延迟 if ($groupIndex > 0) { sleep(1); } // 2. 使用Pool处理当前组的并发请求 $pool = new Pool($this->client, function () use ($group) { foreach ($group as $d) { // 保留原有的数据解析逻辑 if (is_string($d)) { $d = json_decode($d, true); } // 构建Scrapestack请求URL $url = sprintf('%s?%s', 'http://api.scrapestack.com/scrape', $this->createScrapestackRequestData($d['link'])); yield new Request('GET', $url); } }, [ // 设置每组的并发数为10 'concurrency' => 10, // 请求成功的回调 'fulfilled' => function (ResponseInterface $response, $index) use (&$results) { $results[] = [ 'success' => true, 'data' => $response->getBody()->getContents() ]; }, // 请求失败的回调 'rejected' => function (RequestException $e, $index) use (&$results) { $results[] = [ 'success' => false, 'error' => $e->getMessage() ]; }, ]); // 启动Pool并等待当前组所有请求完成 $pool->promise()->wait(); }
关键说明
为什么用Pool?
- 相比你原代码中一次性创建所有
getAsyncpromise的方式,Pool可以动态控制并发数,避免内存占用过高(尤其是请求量极大时)。 - 内置的回调机制能更清晰地处理成功/失败的请求结果,便于后续数据处理。
- 相比你原代码中一次性创建所有
延迟逻辑的选择
- 这里用
sleep(1)实现同步延迟,适合大多数Web API场景(只要你的Symfony API是同步处理请求)。如果是异步非阻塞场景,可以替换为异步延迟方法,但同步sleep已经能满足你的核心需求。
- 这里用
额外优化建议
- 可以根据目标域名进一步分组(比如把同一域名的请求放到同一组),再添加延迟,能更精准地避免单域名请求频率过高。
- 建议给Scrapestack请求添加超时配置,避免单个请求卡住导致整体流程延迟。
内容的提问来源于stack exchange,提问作者briandev
相关产品推荐
相关产品推荐

