>  기사  >  백엔드 개발  >  PHP 프로세스 CPU 100% 문제 해결 - file_get_contents로 인해 문제가 발생함

PHP 프로세스 CPU 100% 문제 해결 - file_get_contents로 인해 문제가 발생함

高洛峰
高洛峰원래의
2016-10-17 11:00:211397검색

Nginx 및 PHP-CGI(php-fpm) 웹 서비스를 실행하는 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에는 PHP 스크립트의 최대 실행 시간을 설정할 수 있는 max_execution_time 매개변수가 있다는 것을 알고 있습니다. 그러나 php-cgi(php-fpm)에서는 이 매개변수가 적용되지 않습니다. PHP 스크립트의 최대 실행 시간을 실제로 제어할 수 있는 것은 php-fpm.conf 구성 파일의 다음 매개변수입니다.

작업자 프로세스가 종료된 후 단일 요청을 처리하는 제한 시간(초)입니다.

'max_execution_time' ini 옵션이 어떤 이유로 스크립트 실행을 중지하지 않을 때 사용해야 합니다.

'0s'는 'off'를 의미합니다

0s

 기본값은 0초이며, 이는 PHP 스크립트가 계속 실행된다는 의미입니다. 이러한 방식으로 모든 php-cgi 프로세스가 file_get_contents() 함수에 정체되면 이 Nginx+PHP 웹서버는 더 이상 새로운 PHP 요청을 처리할 수 없으며 Nginx는 사용자에게 "502 잘못된 게이트웨이"를 반환합니다. PHP 스크립트의 최대 실행 시간을 설정하려면 이 매개변수를 수정해야 하지만 근본 원인이 아닌 증상만 치료합니다. 예를 들어 30s로 변경하면 file_get_contents()가 웹 콘텐츠를 얻는 속도가 느리면 150개의 php-cgi 프로세스가 초당 5개의 요청만 처리할 수 있으며 WebServer도 피하기 어렵다는 의미입니다. "502 나쁜 게이트웨이".

완벽한 솔루션을 얻으려면 PHP 프로그래머가 file_get_contents("http://example.com/")를 직접 사용하는 습관을 버리고 대신 약간 수정하여 추가하는 것이 유일한 방법입니다. 시간 초과 HTTP GET 요청을 구현하려면 다음 방법을 사용하십시오. 번거롭다면 다음 코드를 함수로 직접 캡슐화할 수 있습니다.

<?php  
$ctx = stream_context_create(array(  
   &#39;http&#39; => array(  
       &#39;timeout&#39; => 1 //设置一个超时时间,单位为秒  
       )  
   )  
);  
file_get_contents("http://example.com/", 0, $ctx);  
?>

물론 이것이 php-cgi 프로세스 CPU가 100%에 도달하는 유일한 이유는 아닙니다. 그렇다면 file_get_contents() 함수에 의한 것인지 어떻게 판단할 수 있을까요?

먼저 top 명령을 사용하여 CPU 사용량이 높은 php-cgi 프로세스를 확인합니다.

상위 - 10:34:18 최대 724일, 21:01, 사용자 3명, 평균 로드: 17.86, 11.16, 7.69

작업: 총 561개, 실행 중 15개, 수면 546개, 0 중지됨, 좀비 0개

Cpu: 5.9%us, 4.2%sy, 0.0%ni, 89.4%id, 0.2%wa, 0.0%hi, 0.2%si, 0.0%st

메모리: 총 8100996k, 사용된 4320108k, 사용 가능한 3780888k, 버퍼 772572k

스왑: 총 8193108k, 사용된 50776k, 사용 가능한 8142332k, 캐시된 412088


PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ 명령                                                                               ~ 28분 17분 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.4

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.3 0.3 0 : 40.59 php-cgi

找 其中 其中 一 一 一 个 个 CPU 100% 的 php-cgi 进程 的 pid, 用 以下 命令 跟踪 跟踪 一下 :


strace -p 10747

  如果屏幕显示:


select(7, [6] , [6], [], {15, 0})        = 1 (밖 [6], 왼쪽 {15, 0})

poll([{fd=6, events=POLLIN}], 1 , 0)     = 0(시간 초과)

select(7, [6], [6], [], {15, 0})        = 1(아웃 [6], 왼쪽 {15, 0})

poll([{fd=6, events=POLLIN}], 1, 0)     = 0(시간 초과)

select(7, [6], [6], [], {15, 0})        = 1(밖 [6], 왼쪽 {15, 0})

poll([{fd=6, events=POLLIN}], 1, 0)     = 0(시간 초과)

select(7, [6], [6], [], {15, 0})        = 1 (밖 [6], 왼쪽 {15, 0})

poll( [{fd=6, events=POLLIN}], 1, 0)     = 0(시간 초과)

select(7, [6], [6], [], {15, 0})        = 1 (밖 [6], 왼쪽 {15, 0})

poll([{fd=6, events=POLLIN}], 1, 0)     = 0 (시간 초과)

select( 7, [6], [6], [], {15, 0})        = 1 ([6] 외, 왼쪽 {15, 0})

poll([{fd=6, events= POLLIN}], 1, 0)     = 0(시간 초과)

select(7, [6], [6], [], {15, 0}) = 1(밖 [6], 왼쪽 {15, 0})

poll([{fd =6, events=POLLIN}], 1, 0) = 0(시간 초과)

select(7, [6], [6], [], {15, 0}) = 1(아웃 [ 6], 왼쪽 {15, 0})

poll([{fd=6, events=POLLIN}], 1, 0) = 0(시간 초과)

select(7, [ 6], [6], [], {15, 0}) = 1 (밖 [6], 왼쪽 {15, 0})

poll([{fd=6, events=POLLIN}] , 1, 0) = 0(시간 초과)

select(7, [6], [6], [], {15, 0}) = 1(아웃 [6], 왼쪽 {15, 0 })

poll([{fd=6, events=POLLIN}], 1, 0) = 0 (Timeout)


그러면 다음을 수행할 수 있습니다. 문제는 확실히 file_get_contents()로 인해 발생합니다.


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.