如何用Curl批量发起大量数据请求?遇内存溢出等问题求助
嘿,我来帮你搞定这个批量CURL请求的问题!45000个请求直接怼上去肯定会出问题,内存溢出和页面一直加载的根源在于资源没及时回收和一次性处理的请求量太大,咱们一步步来解决:
核心问题分析
- 内存溢出:你用
curl_multi_init时,每个请求都会创建一个CURL句柄,如果不及时关闭、释放这些句柄,内存会持续累积,直到超出PHP的内存限制。 - 页面持续加载:Web环境下PHP脚本有执行时间限制,45000个请求完全处理完的时间远超这个限制,而且同步处理会一直占用连接。
解决方案:分批次处理+资源及时回收
直接上可落地的方案,分这几步来:
1. 拆分请求为小批次
不要一次性把45000个用户名都塞进CURL multi,而是分成小批次(比如每批15个,你可以根据服务器性能调整),处理完一批再处理下一批,这样内存压力会小很多。
2. 严格回收CURL资源
每个请求完成后,必须关闭单个CURL句柄、从multi句柄中移除,还要手动unset相关变量,让PHP的垃圾回收机制能及时释放内存。
3. 改用CLI模式运行(强烈推荐)
Web环境下脚本容易超时,直接用命令行运行脚本(php your_script.php),没有浏览器和Web服务器的超时限制,能安心处理完所有请求。
完整代码示例
// 临时调整内存限制(按需设置,比如256M,比默认的大一些) ini_set('memory_limit', '256M'); // 脚本执行时间设为无限制(CLI模式下生效) set_time_limit(0); $usernames = []; // 你的45000个用户名数组 $targetUrl = 'https://你的目标URL.com'; // 替换成你的请求地址 $batchSize = 15; // 每批处理的请求数,可根据内存情况调整 // 把用户名数组拆分成多个小批次 $userBatches = array_chunk($usernames, $batchSize); $totalProcessed = 0; foreach ($userBatches as $batch) { $multiHandle = curl_multi_init(); $curlHandles = []; // 为当前批次的每个用户创建CURL句柄 foreach ($batch as $username) { $ch = curl_init($targetUrl); // 设置请求参数(这里假设是POST传递username,GET的话直接拼URL) curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(['username' => $username])); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 设置超时,避免单个请求卡住拖慢整个批次 curl_setopt($ch, CURLOPT_TIMEOUT, 10); // 跳过SSL验证(如果目标地址是HTTPS且证书有问题,可选) // curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_multi_add_handle($multiHandle, $ch); $curlHandles[] = $ch; } // 执行批量请求 $running = null; do { curl_multi_exec($multiHandle, $running); curl_multi_select($multiHandle); // 降低CPU占用,避免空循环 } while ($running > 0); // 处理每个请求的响应 foreach ($curlHandles as $index => $ch) { $username = $batch[$index]; $response = curl_multi_getcontent($ch); $error = curl_error($ch); if ($error) { // 记录错误日志,方便后续排查 error_log("[ERROR] 处理用户 $username 失败:$error"); } else { // 这里写你的响应处理逻辑,比如存数据库、写文件等 // processResponse($response, $username); $totalProcessed++; } // 关键:回收单个CURL资源 curl_multi_remove_handle($multiHandle, $ch); curl_close($ch); unset($ch); } // 回收multi句柄 curl_multi_close($multiHandle); unset($multiHandle, $curlHandles); // 输出进度,方便查看处理情况 echo "已处理 $totalProcessed / " . count($usernames) . " 个用户\n"; } echo "所有请求处理完成!";
额外优化建议
- 调整batchSize:如果还是出现内存溢出,把
$batchSize改小(比如10),减少每批的请求数。 - 添加日志记录:把成功/失败的请求都记录到日志文件,方便后续核对数据。
- 异步持久化:如果响应处理(比如存数据库)耗时,可以把响应先写到临时文件,后续再批量处理,进一步减少内存占用。
内容的提问来源于stack exchange,提问作者Talha Sarwar
相关产品推荐
相关产品推荐

