|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
左手拿着MOTOLOLA右手拿着NOKIA,要多潇洒,有多潇洒,哈哈,终于学会了,但是可能这个时候,又会有人不经意的拍拍肩膀对你说:哥们,别高兴的太早,你还是菜鸟,离学会还差着一大截呢! 有时分,运转 Nginx、PHP-CGI(php-fpm) Web办事的 Linux 办事器,俄然体系负载上升,利用 top 号令检查,良多 php-cgi 历程 CPU 利用率接近100%。后来,我经由过程跟踪发明,这类情形的呈现,跟 PHP 的 file_get_contents() 函数有着亲切的关系。
大、中型网站中,基于 HTTP 协定的 API 接口挪用,是屡见不鲜。PHP 法式员们喜好利用复杂便捷的 file_get_contents("http://example.com/") 函数,来获得一个 URL 的前往内容,然而,假如 http://example.com/ 这个网站呼应迟缓,file_get_contents() 就会一向卡在那儿,不会超时。
咱们晓得,在 php.ini 中,有一个参数 max_execution_time 可以设置 PHP 剧本的最大履行工夫,然而,在 php-cgi(php-fpm) 中,该参数不会起效。真正可以掌握 PHP 剧本最大履行工夫的是 php-fpm.conf 设置装备摆设文件中的以下参数: The timeout (in seconds) for serving a single request after which the worker process will be terminated
Should be used when 'max_execution_time' ini option does not stop script execution for some reason
'0s' means 'off'
<value name="request_terminate_timeout">0s</value>
默许值为 0 秒,也就是说,PHP 剧本会一向履行下去。如许,当一切的 php-cgi 历程都卡在 file_get_contents() 函数时,这台 Nginx+PHP 的 WebServer 已没法再处置新的 PHP 恳求了,Nginx 将给用户前往“502 Bad Gateway”。修正该参数,设置一个 PHP 剧本最大履行工夫是需要的,然而,治本不治标。例如改成 30s,假如产生 file_get_contents() 获得网页内容较慢的情形,这就意味着 150 个 php-cgi 历程,每秒钟只能处置 5 个恳求,WebServer 一样很难防止“502 Bad Gateway”。
要做到完全处理,只能让 PHP 法式员们改失落直接利用 file_get_contents("http://example.com/") 的习气,而是略微修正一下,加个超不时间,用以下体例来完成 HTTP GET 恳求。如果感觉费事,可以自即将以下代码封装成一个函数。 <?php
$ctx = stream_context_create(array(
'http' => array(
'timeout' => 1 //设置一个超不时间,单元为秒
)
)
);
file_get_contents("http://example.com/", 0, $ctx);
?>
固然,招致 php-cgi 历程 CPU 100% 的缘由不只要这一种,那末,怎样肯定是 file_get_contents() 函数招致的呢?
起首,利用 top 号令检查 CPU 利用率较高的 php-cgi 历程。 top - 10:34:18 up 724 days, 21:01, 3 users, load average: 17.86, 11.16, 7.69
Tasks: 561 total, 15 running, 546 sleeping, 0 stopped, 0 zombie
Cpu(s): 5.9%us, 4.2%sy, 0.0%ni, 89.4%id, 0.2%wa, 0.0%hi, 0.2%si, 0.0%st
Mem: 8100996k total, 4320108k used, 3780888k free, 772572k buffers
Swap: 8193108k total, 50776k used, 8142332k free, 412088k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
10747 www 18 0 360m 22m 12m R 100.6 0.3 0:02.60 php-cgi
10709 www 16 0 359m 28m 17m R 96.8 0.4 0:11.34 php-cgi
10745 www 18 0 360m 24m 14m R 94.8 0.3 0:39.51 php-cgi
10707 www 18 0 360m 25m 14m S 77.4 0.3 0:33.48 php-cgi
10782 www 20 0 360m 26m 15m R 75.5 0.3 0:10.93 php-cgi
10708 www 25 0 360m 22m 12m R 69.7 0.3 0:45.16 php-cgi
10683 www 25 0 362m 28m 15m R 54.2 0.4 0:32.65 php-cgi
10711 www 25 0 360m 25m 15m R 52.2 0.3 0:44.25 php-cgi
10688 www 25 0 359m 25m 15m R 38.7 0.3 0:10.44 php-cgi
10719 www 25 0 360m 26m 16m R 7.7 0.3 0:40.59 php-cgi
找个中一个 CPU 100% 的 php-cgi 历程的 PID,用以下号令跟踪一下: strace -p 10747 select(7, [6], [6], [], {15, 0}) = 1 (out [6], left {15, 0})
poll([{fd=6, events=POLLIN}], 1, 0) = 0 (Timeout)
select(7, [6], [6], [], {15, 0}) = 1 (out [6], left {15, 0})
poll([{fd=6, events=POLLIN}], 1, 0) = 0 (Timeout)
select(7, [6], [6], [], {15, 0}) = 1 (out [6], left {15, 0})
poll([{fd=6, events=POLLIN}], 1, 0) = 0 (Timeout)
select(7, [6], [6], [], {15, 0}) = 1 (out [6], left {15, 0})
poll([{fd=6, events=POLLIN}], 1, 0) = 0 (Timeout)
select(7, [6], [6], [], {15, 0}) = 1 (out [6], left {15, 0})
poll([{fd=6, events=POLLIN}], 1, 0) = 0 (Timeout)
select(7, [6], [6], [], {15, 0}) = 1 (out [6], left {15, 0})
poll([{fd=6, events=POLLIN}], 1, 0) = 0 (Timeout)
select(7, [6], [6], [], {15, 0}) = 1 (out [6], left {15, 0})
poll([{fd=6, events=POLLIN}], 1, 0) = 0 (Timeout)
select(7, [6], [6], [], {15, 0}) = 1 (out [6], left {15, 0})
poll([{fd=6, events=POLLIN}], 1, 0) = 0 (Timeout)
select(7, [6], [6], [], {15, 0}) = 1 (out [6], left {15, 0})
poll([{fd=6, events=POLLIN}], 1, 0) = 0 (Timeout)
select(7, [6], [6], [], {15, 0}) = 1 (out [6], left {15, 0})
poll([{fd=6, events=POLLIN}], 1, 0) = 0 (Timeout)
那末,就能够肯定是 file_get_contents() 招致的成绩了。
<P style="TEXT-INDENT: 2em">
对于PHP的语法结构,刚开始真的很不习惯,真搞不懂为什么每个变量之前都要加个“$”符号,每个语句写完之后都必须加上“分号”来表示此句已经结束,还有,PHP对字母的大小写是敏感的,写的时候一定要注意大小写的区别。 |
|