Circa una volta alla settimana, ma a volte anche un paio di volte al giorno dopo aver funzionato bene per giorni, le mie istanze EC2 non rispondono. I grafici della memoria di Munin raccontano una storia piuttosto semplice: la memoria allocata alle "app" inizia a crescere e non si ferma fino a quando lo swap non viene completamente utilizzato e l'istanza viene effettivamente messa in ginocchio. Un altro grafico personalizzato mostra che il processo in costante crescita è apache2.
Eseguo un'impostazione Apache prefork standard con mod_php e alcuni script PHP. Come puoi vedere nel grafico qui sotto, succede qualcosa che innesca i processi apache2 per iniziare a consumare sempre più memoria. Il primo picco verde che ho colto in tempo e riavviato Apache prima che le cose sfuggissero di mano. Il secondo picco è diventato un po 'più lontano e l'istanza ha dovuto essere riavviata completamente.
Grafico della memoria di Munin
Quello che mi chiedo è come eseguire il debug al meglio. A meno di configurare PHP con FastCGI e farlo funzionare nei propri processi, qual è un buon modo per scoprire se è Apache o una combinazione di PHP e del mio codice che sta causando un uso eccessivo della memoria? Quali passi fareste ragazzi per rintracciare questo problema?
AGGIORNAMENTO: Sono stato in grado di rintracciare la perdita dopo essere stato coinvolto nella strass, come ha suggerito Matt di seguito.
Dopo aver trovato un processo apache2 che stava gradualmente e continuamente crescendo in memoria, ho aggiunto alcune altre chiamate error_log () al mio script PHP che stampavano la quantità totale di RSS usata in vari punti della sua esecuzione (usando l'output di ps). Ciò tuttavia si è rivelato fuorviante - mentre sembrava che l'RSS saltava solo dopo che la mia sceneggiatura era stata eseguita, in seguito il debug ha rivelato che non era proprio il caso. Stai attento!
Fortunatamente, tutte quelle chiamate error_log () si sono rivelate utili alla fine. Quando ho avviato strace ( strace -p <pid> -tt -o trace.log -s 256
), ho visto che per ogni richiesta, il processo stava allocando circa 400k di memoria (cercare la chiamata di sistema "brk" e sottrarre il parametro della prima chiamata dall'ultima chiamata - alcuni di solito arrivano in uno dopo un'altro). Ho quindi cercato la più recente chiamata di sistema "write" che conteneva il mio messaggio error_log (), che mi diceva in quale punto dello script era allocata la memoria. Con alcune chiamate error_log () più strategicamente posizionate per individuare la posizione in modo più preciso, ho finalmente trovato il colpevole.
La memoria stava perdendo quando abbiamo chiamato curl_exec () dal nostro script PHP. Alcuni codici arricciati relativi alla gestione di una connessione SSL stanno facendo qualcosa di sbagliato: la perdita è andata via quando sono passato a HTTP. Il log delle modifiche di Curl fa riferimento ad alcune perdite di memoria SSL che sono state risolte in 7.19.5 (eravamo su 7.18.2), quindi ci proverò dopo.
Nel frattempo, sto correndo con un MaxRequestsPerChild molto basso che mantiene Apache entro limiti ragionevoli. Grazie a tutti!