Apache / PHP 기반 웹 앱에서 명백한 메모리 누수의 원인을 어떻게 확인할 수 있습니까? 매우 간단한 이야기를

일주일에 한 번, 며칠 동안 정상적으로 실행 한 후 하루에 몇 번이라도 EC2 인스턴스가 응답하지 않게됩니다. Munin의 메모리 그래프는 매우 간단한 이야기를 보여줍니다. “앱”에 할당 된 메모리가 커지기 시작하고 스왑이 완전히 사용되고 인스턴스가 효과적으로 무릎을 꿇을 때까지 멈추지 않습니다. 또 다른 사용자 정의 그래프는 지속적으로 성장하는 프로세스가 아파치 2임을 보여줍니다.

mod_php와 몇 가지 PHP 스크립트를 사용하여 표준 prefork Apache 설정을 실행합니다. 아래 그래프에서 볼 수 있듯이 apache2 프로세스가 더 많은 메모리를 사용하기 시작하는 트리거가 발생합니다. 첫 번째 녹색 스파이크가 제 시간에 걸려 아파치가 시작되기 전에 Apache를 다시 시작했습니다. 두 번째 스파이크가 조금 더 멀어졌으며 인스턴스를 완전히 재부팅해야했습니다.

무닌 메모리 그래프

내가 궁금한 것은 이것을 가장 잘 디버깅하는 방법입니다. FastCGI로 PHP를 설정하고 자체 프로세스에서 실행하는 데 부족한 이유는 Apache인지 또는 PHP와 코드의 조합으로 과도한 메모리 사용을 유발하는지 확인하는 좋은 방법은 무엇입니까? 이 문제를 추적하기 위해 어떤 단계를 수행 하시겠습니까?


업데이트 : Matt이 제안한 것처럼 strace가 관련된 후 누출을 추적 할 수있었습니다.

점차적으로 메모리에서 지속적으로 증가하고있는 apache2 프로세스를 찾은 후 PHP 스크립트에 error_log () 호출을 몇 개 더 추가하여 실행시 다양한 지점에서 사용 된 RSS의 총량을 출력했습니다 (ps의 출력 사용). 그러나 그것은 오도 된 것으로 판명되었습니다. 내 스크립트가 실행 된 후에 만 ​​RSS가 뛰어 오르는 것처럼 보였지만 나중에 디버깅은 실제로 그렇지 않았습니다. 조심해!

다행히도 모든 error_log () 호출은 결국 유용한 것으로 판명되었습니다. strace ( strace -p <pid> -tt -o trace.log -s 256)를 시작했을 때 , 각 요청에 대해 프로세스가 약 400k의 메모리를 할당하는 것을 보았습니다 ( ‘brk’시스템 호출을 찾아 마지막 호출의 첫 번째 호출 매개 변수를 빼십시오. 다른 후). 그런 다음 error_log () 메시지가 포함 된 가장 최근의 ‘쓰기’시스템 호출을 검색하여 메모리에서 메모리가 할당되는 시점을 알려줍니다. 보다 정확하게 위치를 정확하게 찾기 위해 error_log () 호출을 전략적으로 배치하면서 마침내 범인을 발견했습니다.

PHP 스크립트에서 curl_exec ()를 호출했을 때 메모리가 누출되었습니다. SSL 연결 처리와 관련된 일부 컬 코드가 잘못된 일을하고 있습니다 .HTTP로 전환하면 누수가 사라졌습니다. Curl의 changelog는 7.19.5 (우리는 7.18.2에 있음)에서 수정 된 몇 가지 SSL 메모리 누수를 참조하므로 다음에 시도하겠습니다.

그 동안 Apache를 합리적인 범위 내로 유지하는 MaxRequestsPerChild가 매우 낮습니다. 모두 감사합니다!



답변

무엇이 문제를 일으키는 지 추적하면 엉덩이가 아플 수 있습니다. 그런 문제가있는 경우 가장 먼저 할 일은 MaxRequestsPerChild엄청나게 낮은 숫자 (~ 100-200) 로 줄이고 차이가 있는지 확인하는 것입니다. 그렇다면 루프 어딘가에서 메모리가 누수되는 코드가 있고 코드 감사를 실행하고 싶을 것입니다.

살펴볼 또 다른 사항은 Apache의 전체 상태입니다. 메모리 누수의 원인이되는 특정 요청을 찾을 수 있는지 확인하십시오. 의심되는 프로세스에서 PID를 가져 와서 실행합니다.


답변

금요일 @ 정확히 오후 11시? 백업 시간에 해당합니까? 시스템에 당시 프로세스 및 백업을 제공 할 수있는 I / O가 있습니까? 트렌드 소프트웨어는 # procs 또는 아파치 스코어 보드도 경향이 있습니까? 디스크 I / O는 어떻습니까?

가장 먼저 할 일은 각 proc가 얼마나 많은 mem을 계산하는지 계산 한 다음 $ procmem * $ procs가 사용 가능한 램을 초과 할 수 없도록 아파치에서 MaxRequests에 대한 합리적인 제한을 설정하는 것입니다. OOM이 (종종) 그다지 유익하지 않은 마녀 사냥을 시작하기 때문에 인스턴스를 재부팅해야한다고 생각합니다. 당신 당신의 상자가 그 범위 안에 머물면서 OOM이 아닌 스왑으로 가지 않음으로써 이러한 힘든 시간을 처리 할 수 ​​있도록해야합니다. cronjobs가 진행되는 경우 더 어렵고, cronjobs가 실행해도 안전한지 확인하지 않고 비 정기적으로 실행하는 경우에는 매우 어렵습니다 (예 : 5 분마다 스크립트가 마지막 5 분이 여전히 실행 중인지 확인하지 못함).

사물이 잘못되어도 상자를 다시 부팅 할 필요가없는 경우에도 상황이 훨씬 나아지기 시작합니다. 이 힘든 시간 동안 로그인하여 top, dstat, free -m, iostat 등을 사용하여 진행되는 작업에 대한 좋은 아이디어를 얻을 수 있습니다.

Matt의 방법은 시도해 볼 가치가 있지만 문제 해결을위한 도구로만 사용해야합니다. 다음 번에 찾을 때 전체적인 문제를 찾기가 훨씬 더 어려워 지므로 권장하지 않습니다. 즉, 아파치 / 모듈 관련 문제는 실제로 발생하지만 코드에는 아무런 문제가 없습니다. 나는 당신이 아파치 모듈에서 어떤 종류의 메모리 누출이 아니라고 생각할 가능성이 높다고 생각한다 (당신이 평판이 좋은 배포판을 사용한다고 가정).


답변

첫 번째 질문은 Apache를 통해 실행되는 응용 프로그램은 무엇입니까?

당신이 쓴 것입니까, 아니면 타사 앱입니까?

다른 어떤 구성 요소 / 패키지를 참조합니까?

패키지를 최신 상태입니까?

httpd.conf성능과 관련 하여 파일에 특정한 것이 있습니까?


답변

PHP 응용 프로그램으로 인해 문제가 발생하고 소프트웨어를 직접 작성한 경우 PHP Quick Profiler 와 같은 프로파일 러를 사용하는 것이 좋습니다 . 많은 데이터베이스 트랜잭션이 진행중인 경우 Kontrollbase 와 같은 소프트웨어 가 문제를 찾는 데 도움이 될 수 있습니다.


답변