get_headers()函数运行是否会造成Apache服务器过载?
问题产生原因
get_headers()是PHP原生同步阻塞函数,你当前传入的流上下文仅配置了关闭SSL校验,没有设置任何超时参数,会默认读取php.ini中default_socket_timeout配置(默认值60秒),拿到目标站完整响应前会一直阻塞当前PHP进程。- 目标站点sportsdirect配置了明确的反爬规则,PHP默认请求携带的User-Agent会被直接识别为爬虫流量,站点不会返回正常响应、也不会主动断开TCP连接,会直接把连接挂起,导致对应PHP进程长期处于僵死等待状态。
get_headers()默认发起GET请求,哪怕你只需要响应头,函数也会等待目标站返回完整页面内容才会结束,额外消耗带宽和时间拉长阻塞周期。- 如果你使用prefork模式运行Apache,每个僵死的请求会长期占用一个工作进程,短时间内多次触发该请求就会把Apache的工作进程池占满,后续所有打到Apache的请求(包括同服务器托管的其他站点请求)没有空闲进程处理,就会持续加载最终触发连接超时。
可行替代方案
优先使用可控性更强的cURL扩展实现请求,显式配置超时、请求头、请求方法规则,从根源避免进程长时间阻塞:
$url = "https://www.sportsdirect.com/york-monks-cross-store-1099"; $ch = curl_init($url); curl_setopt_array($ch, [ // 以下两行SSL配置与原逻辑保持一致,生产环境建议移除并开启证书校验 CURLOPT_SSL_VERIFYPEER => false, CURLOPT_SSL_VERIFYHOST => false, // 仅拉取响应头,不请求页面内容,降低请求耗时 CURLOPT_HEADER => true, CURLOPT_NOBODY => true, // 模拟普通浏览器UA,绕过基础反爬检测 CURLOPT_USERAGENT => "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36", // 连接超时5秒,总请求超时10秒,禁止设置过长超时 CURLOPT_CONNECTTIMEOUT => 5, CURLOPT_TIMEOUT => 10, // 最多跟随2次跳转,避免死循环跳转占用资源 CURLOPT_FOLLOWLOCATION => true, CURLOPT_MAXREDIRS => 2, CURLOPT_RETURNTRANSFER => true, ]); $response = curl_exec($ch); curl_close($ch); // 解析响应头为数组 $headers = []; if ($response) { $headerLines = array_filter(explode("\r\n", trim($response))); foreach ($headerLines as $line) { if (str_contains($line, ':')) { [$key, $value] = explode(':', $line, 2); $headers[trim($key)] = trim($value); } else { $headers[] = trim($line); } } }
如果坚持使用get_headers(),必须在流上下文中补全超时、UA、请求方法配置,避免无限制阻塞:
$url = "https://www.sportsdirect.com/york-monks-cross-store-1099"; $context = stream_context_create( [ 'ssl' => [ 'verify_peer' => false, 'verify_peer_name' => false, ], 'http' => [ 'timeout' => 10, 'user_agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36', 'follow_location' => 1, 'max_redirects' => 2, 'method' => 'HEAD' ] ]); $headers = get_headers($url, 0, $context);
额外优化建议:
- 不要在面向用户的Web请求中直接发起外部HTTP请求,这类依赖第三方站点的请求很容易因为目标站故障、网络波动拖垮服务,有条件的话将这类抓取任务放到异步队列,通过CLI脚本执行,不要占用Apache的Web工作进程。
- 生产环境不要关闭SSL证书校验,避免遭遇中间人攻击导致请求内容泄露、被篡改。
内容的提问来源于stack exchange,提问作者Arzath Az
相关产品推荐
相关产品推荐

