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'를 의미합니다
기본값은 0초이며, 이는 PHP 스크립트가 계속 실행된다는 의미입니다. 이러한 방식으로 모든 php-cgi 프로세스가 file_get_contents() 함수에 정체되면 이 Nginx+PHP 웹서버는 더 이상 새로운 PHP 요청을 처리할 수 없으며 Nginx는 사용자에게 "502 잘못된 게이트웨이"를 반환합니다. PHP 스크립트의 최대 실행 시간을 설정하려면 이 매개변수를 수정해야 하지만 근본 원인이 아닌 증상만 치료합니다. 예를 들어
완벽한 솔루션을 얻으려면 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 프로세스를 확인합니다.
상위 - 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- cgi10719 www 25 0 360m 26m 16m r 7.3 0.3 0 : 40.59 php-cgi
找 其中 其中 一 一 一 个 个 CPU 100% 的 php-cgi 进程 的 pid, 用 以下 命令 跟踪 跟踪 一下 :
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()로 인해 발생합니다.