PHP Curl加载耗时过长求助:战地1战队网站数据获取超时
解决PHP Curl加载慢/超时的问题
看起来你遇到的核心问题是在循环里逐个发起Curl请求——每个请求都要经历TCP握手、发送请求、等待响应的完整流程,队员数量多的话,这些时间叠加起来很容易触发30秒的PHP执行超时。下面给你几个针对性的优化方案,按优先级排序:
1. 优先尝试批量请求(如果API支持)
先去核对你使用的游戏数据API是否支持批量查询多个PSNID。很多这类API允许一次性传入多个ID(比如用逗号分隔),这样只需要发起1次Curl请求就能拿到所有队员的数据,这会把请求耗时压缩到原来的几十分之一。
举个示例(假设API支持批量参数):
// 先收集所有队员的PSNID到数组 $psnIds = []; $data = $connection->query("SELECT psnid FROM bfplayers"); while($row = mysqli_fetch_assoc($data)){ $psnIds[] = $row['psnid']; } // 转成API要求的批量格式(比如逗号分隔字符串) $batchPsnIds = implode(',', $psnIds); // 发起单次批量请求 $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "https://your-api-domain.com?psnids={$batchPsnIds}"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 10); // 设置请求超时 $response = curl_exec($ch); curl_close($ch); // 解析批量返回的数据,对应到每个队员 $allPlayerData = json_decode($response, true); // 后续渲染页面的逻辑...
2. 缓存API数据(最有效的长期优化)
队员的游戏数据不会实时高频变化,完全没必要每次用户访问页面都去请求API。你可以把API返回的数据存在自己的数据库里,新增一个last_updated字段,设置合理的更新间隔(比如1小时、6小时),只有当数据超过间隔时才去请求API更新。
示例逻辑:
$data = $connection->query("SELECT * FROM bfplayers"); while($row = mysqli_fetch_assoc($data)){ $psnid = $row['psnid']; $lastUpdated = strtotime($row['last_updated']); $now = time(); // 仅当数据超过1小时未更新时,才请求API if($now - $lastUpdated > 3600){ $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "https://your-api-domain.com?psnid={$psnid}"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 10); // 单个请求超时时间 curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); // 连接超时时间 $playerData = curl_exec($ch); curl_close($ch); // 更新数据库中的数据和更新时间 if($playerData){ $stmt = $connection->prepare("UPDATE bfplayers SET data = ?, last_updated = NOW() WHERE psnid = ?"); $stmt->bind_param("ss", $playerData, $psnid); $stmt->execute(); $stmt->close(); } } // 从数据库读取缓存的数据展示 $displayData = json_decode($row['data'], true); // 渲染队员信息的页面逻辑... }
3. 用Curl多处理并行发起请求
如果API不支持批量查询,那可以用curl_multi_init()并行发起多个请求,而不是串行等待每个请求完成,这样能大幅缩短总耗时。
示例简化代码:
// 收集所有PSNID $psnIds = []; $data = $connection->query("SELECT psnid FROM bfplayers"); while($row = mysqli_fetch_assoc($data)){ $psnIds[] = $row['psnid']; } // 初始化Curl多处理句柄 $multiHandle = curl_multi_init(); $curlHandles = []; // 批量创建Curl请求 foreach($psnIds as $psnid){ $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "https://your-api-domain.com?psnid={$psnid}"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 10); curl_setopt($ch, CURLOPT_FORBID_REUSE, false); // 允许复用连接 $curlHandles[$psnid] = $ch; curl_multi_add_handle($multiHandle, $ch); } // 执行所有并行请求 $running = null; do { curl_multi_exec($multiHandle, $running); curl_multi_select($multiHandle); } while ($running > 0); // 收集每个请求的结果 $playerDataMap = []; foreach($curlHandles as $psnid => $ch){ $playerDataMap[$psnid] = curl_multi_getcontent($ch); curl_multi_remove_handle($multiHandle, $ch); curl_close($ch); } curl_multi_close($multiHandle); // 后续用$playerDataMap对应每个队员渲染数据...
4. 临时调整PHP执行时间(治标方案)
如果以上优化都做了还是偶尔超时,可以临时延长PHP的执行时间,但这只是应急手段,优先用前面的方法解决根本问题:
// 在脚本开头设置,比如延长到60秒 set_time_limit(60);
内容的提问来源于stack exchange,提问作者Dennishofken
相关产品推荐
相关产品推荐

