php函数file_get_contents(一)

<p>早在2010年时候遇到过这样的事情,因为file_get_contents函数造成服务器挂掉的情况,现在觉得很有必要总结下。</p><p>公司里有经常有这样的业务,需要调用第三方公司提供的HTTP接口,在把接口提供的信息显示到网页上,代码是这样写的: file_get_contents(&quot;http://example.com/&quot;) 。</p><p>有一天突然接到运维同事的报告,说是服务器挂了,查出原因说是因为file_get_contents函数造成的,那么为什么一个函数会把服务器给搞挂掉呢?</p><p>经过详细的查询发现第三方公司提供接口已经坏掉了,就是因为接口坏掉了,才导致服务器挂掉。</p><p>问题分析如下:</p><p> 我们代码是&quot;file_get_contents(&quot;http://example.com/&quot;) &quot;获取一个 URL 的返回内容,如果第三方公司提供的URL响应速度慢,或者出现问题,我们服务器的PHP程序将会一直执行去获得这个URL,我们知道,在 php.ini 中,有一个参数 max_execution_time 可以设置 PHP 脚本的最大执行时间,但是,在 php-cgi(php-fpm) 中,该参数不会起效。真正能够控制 PHP 脚本最大执行时间的是 php-fpm.conf 配置文件中的以下参数: &lt;value name=&quot;request_terminate_timeout&quot;&gt;0s&lt;/value&gt;  默认值为 0 秒,也就是说,PHP 脚本会一直执行下去,当请求越来越多的情况下会导致php-cgi 进程都卡在 file_get_contents() 函数时,这台 Nginx+PHP 的 WebServer 已经无法再处理新的 PHP 请求了,Nginx 将给用户返回&quot;502 Bad Gateway&quot;。CPU的利用率达到100% ,时间一长服务器就会挂掉。</p><p>问题的解决:</p><p> 已经找到问题,那么我们该怎么解决呢?</p><p> 当时想到的解决问题的办法就是设置PHP的超时时间,用set_time_limit; 设置超时时间,这样就不会卡住了。代码上线后发现服务器还是会挂掉,好像根本不起作用。后来查了资料才知道,set_time_limit设置的是PHP程序的超时时间,而不是file_get_contents函数读取URL的超时时间。set_time_limit和修改php.ini文件里max_execution_time 效果是一样的。</p><p>要设置file_get_contents函数的超时时间,可以用resource $context的timeout参数,代码如下:</p><pre class="brush:php;toolbar:false">1$opts=array( 2  &#39;http&#39;=&gt;array( 3    &#39;method&#39;=&gt;&quot;GET&quot;, 4    &#39;timeout&#39;=&gt;10, 5  ) 6); 7$context=stream_context_create($opts); 8$html=file_get_contents(&#39;http://www.example.com&#39;,false,$context); 9echo$html;</pre><p>代码中的timeout就是file_get_contents读取url的超时时间。</p><p>另外还有一个说法也可以改变读取url的超时时间,就是修改php.ini中的default_socket_timeout的值,或者 ini_set(&#39;default_socket_timeout&#39;, 10); 但是我没有测试过不知道行不行。</p><p>有了解决方法之后,服务器就不会挂掉了。</p><p>在解决的过程中我还发现起到关键作用的是stream_context_create方法,里面method 可以是GET,那么能否可以POST呢?还有没有其他的参数?</p><p>还有一个为老同事告诉我们还有一个比file_get_contents更好的办法,就是用CURL。</p><p>请看下面两篇。</p>
RangeTime:0.006034s
RangeMem:207.56 KB
返回顶部 留言