使用完整url时,PHP文件获取内容的速度非常慢
我正在使用一个从HTML页面生成pdf文件的脚本(最初不是我创建的)。问题是现在需要很长的时间,比如1-2分钟来处理。据推测,这原本运行良好,但在过去几周内已经放缓 该脚本在php脚本上调用使用完整url时,PHP文件获取内容的速度非常慢,php,Php,我正在使用一个从HTML页面生成pdf文件的脚本(最初不是我创建的)。问题是现在需要很长的时间,比如1-2分钟来处理。据推测,这原本运行良好,但在过去几周内已经放缓 该脚本在php脚本上调用file\u get\u contents,然后将结果输出到服务器上的HTML文件中,并在该文件上运行pdf生成器应用程序 我似乎已将问题缩小到对完整url而不是本地路径的file\u get\u contents调用 当我使用 $content = file_get_contents('test.txt')
file\u get\u contents
,然后将结果输出到服务器上的HTML文件中,并在该文件上运行pdf生成器应用程序
我似乎已将问题缩小到对完整url而不是本地路径的file\u get\u contents
调用
当我使用
$content = file_get_contents('test.txt');
它几乎是瞬间处理的。但是,如果我使用完整的url
$content = file_get_contents('http://example.com/test.txt');
处理过程需要30-90秒
它不仅限于我们的服务器,在访问任何外部url(例如)时速度都很慢。我相信这个脚本调用了完整的url,因为如果您在本地调用该文件,就需要一些查询字符串变量,但这些变量不起作用
我还试过
fopen
、readfile
和curl
,它们都同样慢。有什么办法可以解决这个问题吗?你能试着在服务器上从命令行获取这个url吗?我想到了卷发或wget。如果这些人以正常速度检索URL,那么这不是网络问题,很可能是apache/php设置中的问题。我会用它来获取外部内容,因为这比file\u get\u contents
方法快得多。不确定这是否能解决问题,但值得一试
还要注意,服务器速度会影响检索文件所需的时间
下面是一个用法示例:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://example.com/test.txt');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
curl_close($ch);
注意:这已在PHP 5.6.14中修复。即使是HTTP/1.0请求,现在也会自动发送连接:close
头
我花了很长时间才弄清楚文件获取内容脚本缓慢的原因
通过使用Wireshark进行分析,问题(在我的情况下,也可能是你的情况下)是远程web服务器直到15秒才关闭TCP连接(即“保持活动”)
事实上,file_get_contents不会发送“connection”HTTP头,因此远程web服务器默认认为这是一个保持活动的连接,并且在15秒之前不会关闭TCP流(这可能不是标准值-取决于服务器配置)
如果HTTP有效负载长度达到响应内容长度HTTP报头中指定的长度,则正常浏览器会考虑页面被完全加载。文件内容不能做到这一点,这太可惜了
解决方案
因此,如果您想了解解决方案,请参见:
$context = stream_context_create(array('http' => array('header'=>'Connection: close\r\n')));
file_get_contents("http://www.something.com/somepage.html",false,$context);
下载完成后,只需告诉远程web服务器关闭连接,因为文件获取内容本身不够智能,无法使用响应内容长度HTTP头完成连接。有时,这是因为服务器上的DNS速度太慢,请尝试以下操作: 替换
echo file_get_contents('http://www.google.com');
作为
我也有同样的问题
唯一对我有效的方法是在$options
数组中设置超时
$options = array(
'http' => array(
'header' => implode($headers, "\r\n"),
'method' => 'POST',
'content' => '',
'timeout' => .5
),
);
时间:50976 ms(平均时间总共5次尝试)
时间:46679 ms(平均时间总共5次尝试)
注意:request.php用于从mysql数据库中获取一些数据。我有一个通过API传递的巨大数据,我正在使用
file\u get\u contents
读取数据,但大约需要60秒。然而,使用KrisWebDev的解决方案大约需要25秒
$context = stream_context_create(array('https' => array('header'=>'Connection: close\r\n')));
file_get_contents($url,false,$context);
我也将用CURL来考虑,你可以“线程”请求。这对我帮助很大,因为我目前还没有访问到允许线程的PHP版本 例如,我使用file_get_内容从远程服务器获取7个图像,每个请求需要2-5秒。在用户等待生成PDF时,仅此过程就向过程中添加了30秒或其他时间 这实际上将时间减少到大约1张图像。另一个例子是,我在之前验证36个URL所用的时间。我想你明白了。:-) 然后关闭文件:
curl_multi_close($master);
我知道这是一个老问题,但我今天发现了,答案对我来说并不适用。我没有看到有人说每个IP的最大连接数可以设置为1。这样,您正在执行API请求,而API正在执行另一个请求,因为您使用了完整的url。这就是直接从光盘加载的原因。对我来说,这解决了一个问题:
if (strpos($file->url, env('APP_URL')) === 0) {
$url = substr($file->url, strlen(env('APP_URL')));
} else {
$url = $file->url;
}
return file_get_contents($url);
当我从命令行尝试wget时,速度也非常慢。它挂在墙上。。。步服务器上可能存在某种DNS问题。尝试使用“主机”或“nslookup”(任何可用的)并尝试从系统中解析各种不同的主机名。你能链接到一个关于比较文件内容和卷曲速度的基准吗?@shamittomar,基准各不相同,但一个简单的谷歌可以得出一系列不同的结果。是其中之一。我只知道,在我过去使用过的各种应用程序中,cURL的速度更快。这仅仅是个人的经验,因为cURL的开发是为了获取远程文件。其中as file_get_contents/fopen是为一般读取本地文件而开发的。curl的一个优点是它将重用现有的连接(当使用相同的句柄时),这一点很重要,如果您对单个主机执行多个请求(例如API调用)。我在API测试路由上执行get(无数据库连接或文件系统交互),只需从
文件获取内容
切换到curl
即可将响应时间从约500毫秒缩短到约100毫秒。感谢您,这是一款超级甜蜜的产品。已被接受、镀金、装框并广受欢迎。非常感谢。这可以从somepage.html方面完成吗?(如果somepage.html是一个php脚本,它可以
$context = stream_context_create(array('https' => array('header'=>'Connection: close\r\n')));
file_get_contents($url,false,$context);
$timeout = 30;
$retTxfr = 1;
$user = '';
$pass = '';
$master = curl_multi_init();
$node_count = count($curlList);
$keys = array("url");
for ($i = 0; $i < $node_count; $i++) {
foreach ($keys as $key) {
if (empty($curlList[$i][$key])) continue;
$ch[$i][$key] = curl_init($curlList[$i][$key]);
curl_setopt($ch[$i][$key], CURLOPT_TIMEOUT, $timeout); // -- timeout after X seconds
curl_setopt($ch[$i][$key], CURLOPT_RETURNTRANSFER, $retTxfr);
curl_setopt($ch[$i][$key], CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($ch[$i][$key], CURLOPT_USERPWD, "{$user}:{$pass}");
curl_setopt($ch[$i][$key], CURLOPT_RETURNTRANSFER, true);
curl_multi_add_handle($master, $ch[$i][$key]);
}
}
// -- get all requests at once, finish when done or timeout met --
do { curl_multi_exec($master, $running); }
while ($running > 0);
if ((int)curl_getinfo($ch[$i][$key], CURLINFO_HTTP_CODE) > 399 || empty($results[$i][$key])) {
unset($results[$i][$key]);
} else {
$results[$i]["options"] = $curlList[$i]["options"];
}
curl_multi_remove_handle($master, $ch[$i][$key]);
curl_close($ch[$i][$key]);
curl_multi_close($master);
if (strpos($file->url, env('APP_URL')) === 0) {
$url = substr($file->url, strlen(env('APP_URL')));
} else {
$url = $file->url;
}
return file_get_contents($url);