xiewz 2018-11-10
一、背景
大家做项目的时候,不免会看到前辈的代码。博主最近看到前辈有的时候请求外部接口用的是file_get_contents,有的用的是curl。稍微了解这两部分的同学都知道,curl在性能上和速度上是优于file_get_contents的,那么为什么呢,从哪里体现出来的差距呢?
二、file_get_contents和curl
1、file_get_contents概述
file_get_contents() 函数把整个文件读入一个字符串中。
手册:http://www.w3school.com.cn/php/func_filesystem_file_get_contents.asp
这里可以看出来,file_get_contents函数的最优选择是读取文件的内容。要求对方的服务器php.ini必须开启:allow_url_fopen
2、curl的概述
CURL是一个非常强大的开源库,支持很多协议,包括HTTP、FTP、TELNET等,我们使用它来发送HTTP请求。它给我 们带来的好处是可以通过灵活的选项设置不同的HTTP协议参数,并且支持HTTPS。CURL可以根据URL前缀是“HTTP” 还是“HTTPS”自动选择是否加密发送内容。需要php.ini开启curl扩展
参考文章:http://www.cnblogs.com/manongxiaobing/p/4698990.html
从定义上来说,curl作为一个开源库,拥有众多的语法也支持众多的协议,这点能看出来curl相比于file_get_contents() 是能做更多的事情的
三、为什么curl比file_get_contents好
博主百度了网上的众多说法,总共分为下面几个方面:
1、file_get_contents() 更容易造成服务器挂掉
关于造成服务器挂掉,这部分主要涉及两个方面:
(1)直接使用file_get_contents,未设置超时处理造成nginx报错:502 Bad Gateway
这部分大家可以参考博客:http://www.cnblogs.com/aipiaoborensheng/p/5000096.html
设置超时时间即可。当然,如果是选用curl的话,设置超时时间会更加的方便,明显,一般不会因为超时而造成服务器垮掉。
(2)用file_get_contents请求效率很低,页面经常卡顿很久
这部分在网上也有个解释,说file_get_contents每次请求远程URL中的数据都会重新做DNS查询,并不对DNS信息进行缓存。而curl则可以通过设置参数的方式来缓存DNS,从而达到快速访问的目的
curl设置DNS缓存:
CURLOPT_DNS_USE_GLOBAL_CACHE 启用时会启用一个全局的DNS缓存,此项为线程安全的,并且默认启用。
CURLOPT_DNS_CACHE_TIMEOUT 设置在内存中保存DNS信息的时间,默认为120秒。
1
2
参考链接:https://www.cnblogs.com/jking10/p/6595981.html
(3)curl能做到file_get_contents做不到的事情
这部分是博主之前解决一个需求的时候发现的。当我需要把网络图片转换为二进制的图片流的时候,curl能实现,而file_get_contens就不行。
参考我之前的文章:https://blog.csdn.net/LJFPHP/article/details/81357839
2、file_get_contents速度很慢
关于速度慢的原因,一部分是DNS缓存,这确实是file_get_contents的瓶颈,另一方面就是关于header头的原因。大家都知道,file_get_contents的请求是不带头的,这样它接收完所有数据后,没有主动断开和服务器的http连接。
解决方案:
$opts = array(
'http'=>array(
'method' => 'POST',
'header' => 'Content-type:application/x-www-form-urlencoded',
'content' => $postdata,
'timeout' => 60 * 10 // 超时时间(单位:s)
'Connection'=>"close"
)
);
$context = stream_context_create($opts);
file_get_contents($filename, false, $context);
1
2
3
4
5
6
7
8
9
10
11
我们通过设置句柄的方式,定义超时时间和header头,这样就能最大化的提升file_get_contents的速度
3、file_get_contents请求HTTP时,使用的是http_fopen_wrapper,不会keeplive。而curl却可以。这样在多次请求多个链接时,curl效率会好一些。
这部分博主查询了下keeplive的相关知识,发现自己对于http请求方面还不是很熟悉。关于keeplive也是一个很大模块,博主这里就也不废话了,给大家推荐几篇不错的博客,有兴趣的可以看看:
(1)(apache)http的keeplive
1
https://blog.csdn.net/jackyrongvip/article/details/9217931
http://www.cnblogs.com/hixiaowei/p/9261358.html
(2)tcp的keepAlive
1
http://www.cnblogs.com/xiaoleiel/p/8308514.html
四、关于服务器是否支持file_get_contents的判断方法
众所周知的,file_get_contents是需要请求的服务商开启allow_url_fopen,但是很多服务商为了安全考虑都会关掉这个功能。而curl是要求php必须开启curl扩展。不过相对来说,很少有服务商不开启curl的,所以curl的运用场合会更多一些。
这里我们可以使用php自带的:function_exists方法来判断服务商是否定义的有此方法。
文档:http://php.net/manual/zh/function.function-exists.php
代码:
if(function_exists('file_get_contents')) {
$file_contents = file_get_contents($url);
} else {
//这里可以执行curl方案
}
1
2
3
4
5
通过对比我们也能发现两个函数的优劣势。如果是读取文件或者只是去拉取数据,那么file_get_contents的效率比较高 也比较简单。如果是要进行远程连接或者高频次的访问,那么还是老老实实用curl吧。
end