【北京網(wǎng)站制作】PHP-CGI進(jìn)程CPU 100%與file_get_contents函數(shù)的關(guān)系
  • 更新時(shí)間:2024-10-28 16:18:31
  • 網(wǎng)站建設(shè)
  • 發(fā)布時(shí)間:1年前
  • 474

PHP-CGI 進(jìn)程 CPU 100% 與 file_get_contents 函數(shù)的關(guān)系

有時(shí),運(yùn)行Nginx和PHP-CGI(php-fpm)網(wǎng)絡(luò)服務(wù)的Linux服務(wù)器突然出現(xiàn)系統(tǒng)負(fù)載增加。使用top命令查看,很多php-cgi進(jìn)程的CPU占用率接近100%。后來(lái)通過(guò)跟蹤發(fā)現(xiàn),這種情況的出現(xiàn)與PHP的file_get_contents()函數(shù)密切相關(guān)。 (北京網(wǎng)站建設(shè))

在大中型網(wǎng)站中,基于HTTP協(xié)議的API接口調(diào)用司空見(jiàn)慣。 PHP程序員喜歡用簡(jiǎn)單方便的file_get_contents('http://example.com/')函數(shù)來(lái)獲取一個(gè)URL的返回內(nèi)容,但是如果http://example.com/網(wǎng)站響應(yīng)慢,file_get_contents()會(huì)一直卡在那里,不會(huì)暫停。

我們知道在php.ini中,有一個(gè)參數(shù)max_execution_time可以設(shè)置PHP腳本的最長(zhǎng)執(zhí)行時(shí)間,但是在php-cgi(php-fpm)中,這個(gè)參數(shù)是不會(huì)生效的。真正控制PHP腳本最大執(zhí)行時(shí)間的是php-fpm.conf配置文件中的以下參數(shù):

作為單個(gè)請(qǐng)求服務(wù)的超時(shí)(以秒為單位),之后工作進(jìn)程將被終止

應(yīng)在“max_execution_time”ini 選項(xiàng)因某種原因未停止腳本執(zhí)行時(shí)使用

“0s”表示“關(guān)閉”

valuename='request_terminate_timeout'0s/值

默認(rèn)值為0 秒,即PHP 腳本將永遠(yuǎn)執(zhí)行。這樣,當(dāng)所有的php-cgi進(jìn)程都卡在file_get_contents()函數(shù)中時(shí),這個(gè)Nginx+PHP WebServer就不能再處理新的PHP請(qǐng)求,Nginx就會(huì)返回“502 Bad Gateway”給用戶。需要修改該參數(shù)來(lái)設(shè)置PHP腳本的最大執(zhí)行時(shí)間,但治標(biāo)不治本。比如改成30s,如果file_get_contents()獲取網(wǎng)頁(yè)內(nèi)容慢,說(shuō)明150個(gè)php-cgi進(jìn)程每秒只能處理5個(gè)請(qǐng)求,WebServer也很難避免“502 Bad網(wǎng)關(guān)”。

要實(shí)現(xiàn)完整的解決方案,PHP程序員只能改掉直接使用file_get_contents('http://example.com/')的習(xí)慣,而是稍微修改一下,加個(gè)timeout,按照下面的方式實(shí)現(xiàn)HTTP GET請(qǐng)求。如果覺(jué)得麻煩,可以自己將下面的代碼封裝成一個(gè)函數(shù)。

?

="tag-name">php????
  • $ctx?=?stream_context_create(array(????
  • ???'http'?=>?array(????
  • ???????'timeout'?=>?1?//設(shè)置一個(gè)超時(shí)時(shí)間,單位為秒????
  • ???????)????
  • ???)????
  • );????
  • file_get_contents("http://example.com/",?0,?$ctx);????
  • ?>???
  •   當(dāng)然,導(dǎo)致 php-cgi 進(jìn)程 CPU 100% 的原因不只有這一種,那么,怎么確定是 file_get_contents() 函數(shù)導(dǎo)致的呢?

      首先,使用 top 命令查看 CPU 使用率較高的 php-cgi 進(jìn)程。

    1. top?-?10:34:18?up?724?days,?21:01,??3?users,??load?average:?17.86,?11.16,?7.69?
    2. Tasks:?561?total,??15?running,?546?sleeping,???0?stopped,???0?zombie?
    3. 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?
    4. Mem:???8100996k?total,??4320108k?used,??3780888k?free,???772572k?buffers?
    5. Swap:??8193108k?total,????50776k?used,??8142332k?free,???412088k?cached?
    6. ??PID?USER??????PR??NI??VIRT??RES??SHR?S?%CPU?%MEM????TIME+??COMMAND????????????????????????????????????????????????????????????
    7. 10747?www???????18???0??360m??22m??12m?R?100.6?0.3????0:02.60?php-cgi????????????????????????????????????????????????????????????
    8. 10709?www???????16???0??359m??28m??17m?R?96.8??0.4????0:11.34?php-cgi????????????????????????????????????????????????????????????
    9. 10745?www???????18???0??360m??24m??14m?R?94.8??0.3????0:39.51?php-cgi????????????????????????????????????????????????????????????
    10. 10707?www???????18???0??360m??25m??14m?S?77.4??0.3????0:33.48?php-cgi????????????????????????????????????????????????????????????
    11. 10782?www???????20???0??360m??26m??15m?R?75.5??0.3????0:10.93?php-cgi????????????????????????????????????????????????????????????
    12. 10708?www???????25???0??360m??22m??12m?R?69.7??0.3????0:45.16?php-cgi????????????????????????????????????????????????????????????
    13. 10683?www???????25???0??362m??28m??15m?R?54.2??0.4????0:32.65?php-cgi????????????????????????????????????????????????????????????
    14. 10711?www???????25???0??360m??25m??15m?R?52.2??0.3????0:44.25?php-cgi????????????????????????????????????????????????????????????
    15. 10688?www???????25???0??359m??25m??15m?R?38.7??0.3????0:10.44?php-cgi????????????????????????????????????????????????????????????
    16. 10719?www???????25???0??360m??26m??16m?R??7.7??0.3????0:40.59?php-cgi?

      找其中一個(gè) CPU 100% 的 php-cgi 進(jìn)程的 PID,用以下命令跟蹤一下:

    1. strace?-p?10747?

      如果屏幕顯示:

    1. select(7,?[6],?[6],?[],?{15,?0})????????=?1?(out?[6],?left?{15,?0})?
    2. poll([{fd=6,?events=POLLIN}],?1,?0)?????=?0?(Timeout)?
    3. select(7,?[6],?[6],?[],?{15,?0})????????=?1?(out?[6],?left?{15,?0})?
    4. poll([{fd=6,?events=POLLIN}],?1,?0)?????=?0?(Timeout)?
    5. select(7,?[6],?[6],?[],?{15,?0})????????=?1?(out?[6],?left?{15,?0})?
    6. poll([{fd=6,?events=POLLIN}],?1,?0)?????=?0?(Timeout)?
    7. select(7,?[6],?[6],?[],?{15,?0})????????=?1?(out?[6],?left?{15,?0})?
    8. poll([{fd=6,?events=POLLIN}],?1,?0)?????=?0?(Timeout)?
    9. select(7,?[6],?[6],?[],?{15,?0})????????=?1?(out?[6],?left?{15,?0})?
    10. poll([{fd=6,?events=POLLIN}],?1,?0)?????=?0?(Timeout)?
    11. select(7,?[6],?[6],?[],?{15,?0})????????=?1?(out?[6],?left?{15,?0})?
    12. poll([{fd=6,?events=POLLIN}],?1,?0)?????=?0?(Timeout)?
    13. select(7,?[6],?[6],?[],?{15,?0})????????=?1?(out?[6],?left?{15,?0})?
    14. poll([{fd=6,?events=POLLIN}],?1,?0)?????=?0?(Timeout)?
    15. select(7,?[6],?[6],?[],?{15,?0})????????=?1?(out?[6],?left?{15,?0})?
    16. poll([{fd=6,?events=POLLIN}],?1,?0)?????=?0?(Timeout)?
    17. select(7,?[6],?[6],?[],?{15,?0})????????=?1?(out?[6],?left?{15,?0})?
    18. poll([{fd=6,?events=POLLIN}],?1,?0)?????=?0?(Timeout)?
    19. select(7,?[6],?[6],?[],?{15,?0})????????=?1?(out?[6],?left?{15,?0})?
    20. poll([{fd=6,?events=POLLIN}],?1,?0)?????=?0?(Timeout)?

      那么,就可以確定是 file_get_contents() 導(dǎo)致的問(wèn)題了。

    我們專注高端建站,小程序開(kāi)發(fā)、軟件系統(tǒng)定制開(kāi)發(fā)、BUG修復(fù)、物聯(lián)網(wǎng)開(kāi)發(fā)、各類API接口對(duì)接開(kāi)發(fā)等。十余年開(kāi)發(fā)經(jīng)驗(yàn),每一個(gè)項(xiàng)目承諾做到滿意為止,多一次對(duì)比,一定讓您多一份收獲!

    本文章出于推來(lái)客官網(wǎng),轉(zhuǎn)載請(qǐng)表明原文地址:https://www.tlkjt.com/web/13826.html
    推薦文章

    在線客服

    掃碼聯(lián)系客服

    3985758

    回到頂部