Qualcosa "uccide" i miei processi Apache-PHP dopo un po 'di tempo


3

Ho il seguente problema davvero strano e spero, voi ragazzi potete aiutarmi. Se ci sono domande, cercherò di risponderle nel miglior modo possibile.

Il problema

Ho un server web con Debian 6.0, Apache 2.2.16 e PHP 5.3.9. Sfortunatamente, non c'è modo di aggiornare questi componenti.
Di tanto in tanto, le richieste HTTP al server vengono interrotte nel mezzo del caricamento della pagina. È sempre qualcosa di circa 3 minuti (la sua variabile tra 180 e 195 secondi). Gli script si fermano, senza alcun suggerimento, e non restituiscono alcun output al client né azioni sul lato server.

Il caso di test

Per chiarire il problema, dare un'occhiata al seguente script di test, con il quale potrei riprodurre il problema. Si noti che il problema si verifica su molti script su quel server, che durano più a lungo di 3 minuti.

<?php
    echo "Start: ".date('Y-m-d H:i:s')."<br>\n";
    flush(); ob_flush();

    $count = 0;
    while ($count++ < 300) {
        sleep(1);
        echo ".";
        flush(); ob_flush();
    }

    echo "<br>\nFinished: ".date('Y-m-d H:i:s');

Funziona 5 minuti e genera un punto ogni secondo. Per riprodurre il problema, lo apro in 3 diversi browser (Chrome, Firefox, IE) con 2 domini diversi, in modo che gli script vengano eseguiti 6 volte. Inizio lo script in ogni finestra, circa 1 secondo in ritardo l'uno dell'altro.

Che succede

Se il problema si verifica, posso vedere solo circa 180 punti, ma relativamente ad un certo punto temporale. Quindi, se il primo script è iniziato alle 10:00:00, il secondo script è iniziato alle 10:00:02 e il terzo script è iniziato alle 10:00:03, quindi il primo script ha emesso 186 punti, il secondo script 184 punti e il terzo script 183 punti. Ciò significa che tutti gli script sono stati avviati in momenti diversi, ma sono terminati esattamente alle 10:03:06.

Ho anche provato questo script con file_put_contents(), quindi posso vedere se gli script non inviano più output al client. Ma anche questo si ferma, quindi l'intero script php deve essere ucciso lato server e non viene più eseguito.

Quello che ho notato è che il problema non si verifica sempre. A volte devo fare l'esperimento la mezza giornata per vedere l'effetto, a volte succede al primo tentativo. Inoltre, quando accade, succederà per lo più in tutte e 6 le finestre, ma non sempre. A volte, le prime due finestre finiscono bene dopo 5 minuti, e le altre 4 finestre si sono fermate a circa 3 minuti.

Ho esaminato il tcpdump del traffico tra server e client. Il server invia un "FIN, ACK" nel momento in cui non viene inviato più alcun output.
L'apache access.log mostra solo gli inizi dello script, nel file error.log non esiste nulla relativo al problema o ai tempi in cui si verifica il problema.

Conclusione

In primo luogo, sembra che le richieste al server o al carico siano rilevanti, perché a volte riesco a vedere il problema più spesso, dove molte persone (70) stanno utilizzando il server e su cui sono in esecuzione numerosi cronjob.
Forse è una specie di sovraccarico della rete, quindi la rete si blocca e uccide tutte le connessioni. Ma perché succede, che a volte 2 finestre su 4 finiscono di caricare la sceneggiatura mentre le altre no?
Ho anche pensato di essere causato da qualche cronjob (ce ne sono troppi sul server), che uccide script di apache troppo vecchi ogni x minuti. Ma non riuscivo a trovarne uno né questo non spiegherebbe, perché succede (quando succede) ogni volta a circa 3 minuti. Inoltre, i processi di apache più vecchi di altri utenti continuano a essere eseguiti e non vengono uccisi.
Escludo il problema dal lato client, perché posso vedere il problema su diversi client con SO diversi e browser diversi.

Grazie

Spero di essere stato in grado di descrivere il mio problema abbastanza bene per te, quindi potresti darmi consigli, come posso analizzare meglio, dove il problema è e come posso risolverlo (senza dover aggiornare parti essenziali del server). Forse è solo un posto misterioso da qualche parte?
Grazie a tutti per aver letto fino alla fine!

Fatto divertente: se non viene eseguito alcun output in uno script, che dura più di 3 minuti (perché calcola qualcosa) e il problema si verifica, Firefox pensa principalmente "hey, nessun output ma è finito? Consente di ricaricare lo script!" E raramente pensa "hey, nessun output, ma finito? Mostrerò all'utente un messaggio di risposta vuoto". Ottimo, se dietro questo script c'è qualche azione importante e questa azione viene eseguita ancora e ancora e ancora e ancora g

Fatti attraverso i tuoi commenti

access.log è scritto solo se le richieste sono finite. Se cancella durante il caricamento, non esiste una voce access.log.

I processi in errore stanno ottenendo a SIGKILL.

Failing scripts Avvio degli script di test ogni 10 secondi. Il tempo varia da 3 minuti a fine aperto (principalmente tra 3 e 4 minuti). Cosa è interessante: per lo più 12 degli script avviati vengono uccisi.

Verifica i tuoi commenti

Iniziati pochi secondi uno dopo l'altro:

chrome_backoffice: Start: 2015-06-11 09:41:46 (cancled at 09:44:56)
..............................................................................................................................................................................................
NO ACCESS LOG ENTRY

chrome_server: Start: 2015-06-11 09:41:49 (cancled at 09:44:56)
...........................................................................................................................................................................................
NO ACCESS LOG ENTRY

firefox_server: Start: 2015-06-11 09:41:51 (cancled at 09:44:56)
.........................................................................................................................................................................................
NO ACCESS LOG ENTRY

firefox_backoffice: Start: 2015-06-11 09:41:52 (cancled at 09:44:56)
........................................................................................................................................................................................
NO ACCESS LOG ENTRY

ie_backoffice: Start: 2015-06-11 09:41:53 (cancled at 09:44:56)
.......................................................................................................................................................................................
NO ACCESS LOG ENTRY

ie_server: Start: 2015-06-11 09:41:56 (cancled at 09:44:56)
....................................................................................................................................................................................
NO ACCESS LOG ENTRY

Iniziati un minuto dopo l'altro:

chrome_backoffice: Start: 2015-06-11 09:46:17
............................................................................................................................................................................................................................................................................................................
Finished: 2015-06-11 09:51:17
###DOMAIN###:443 192.168.###IP### - - [11/Jun/2015:09:46:17 +0200] "GET /###PATH###/sleepTest.php HTTP/1.1" 200 2174 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36"

chrome_server: Start: 2015-06-11 09:47:17
............................................................................................................................................................................................................................................................................................................
Finished: 2015-06-11 09:52:17
###DOMAIN###:80 192.168.###IP### - - [11/Jun/2015:09:47:17 +0200] "GET /###PATH###/sleepTest.php HTTP/1.1" 200 2174 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36"

firefox_backoffice: Start: 2015-06-11 09:48:17 (cancled at 09:52:23)
......................................................................................................................................................................................................................................................
NO ACCESSLOG ENTRY

firefox_server: Start: 2015-06-11 09:50:55
............................................................................................................................................................................................................................................................................................................
Finished: 2015-06-11 09:55:55
###DOMAIN###:80 192.168.###IP### - - [11/Jun/2015:09:50:55 +0200] "GET /###PATH###/sleepTest.php HTTP/1.1" 200 2172 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0"

ie_backoffice: Start: 2015-06-11 09:50:57
............................................................................................................................................................................................................................................................................................................
Finished: 2015-06-11 09:55:57
###DOMAIN###:443 192.168.###IP### - - [11/Jun/2015:09:50:57 +0200] "GET /###PATH###/sleepTest.php HTTP/1.1" 200 2173 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"

ie_server: Start: 2015-06-11 09:50:56
............................................................................................................................................................................................................................................................................................................
Finished: 2015-06-11 09:55:56
###DOMAIN###:80 192.168.###IP### - - [11/Jun/2015:09:50:56 +0200] "GET /###PATH###/sleepTest.php HTTP/1.1" 200 2173 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"

Iniziati 30 secondi uno dopo l'altro:

chrome_backoffice: Start: 2015-06-11 09:56:36 (cancled at 10:00:00)
............................................................................................................................................................................................................
NO ACCESSLOG ENTRY

chrome_server: Start: 2015-06-11 09:57:06
............................................................................................................................................................................................................................................................................................................
Finished: 2015-06-11 10:02:06
###DOMAIN###:80 192.168.###IP### - - [11/Jun/2015:09:57:06 +0200] "GET /###PATH###/sleepTest.php HTTP/1.1" 200 2177 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36"

firefox_backoffice: Start: 2015-06-11 09:57:36
............................................................................................................................................................................................................................................................................................................
Finished: 2015-06-11 10:02:36
###DOMAIN###:443 192.168.###IP### - - [11/Jun/2015:09:57:36 +0200] "GET /###PATH###/sleepTest.php HTTP/1.1" 200 2177 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0"

firefox_server: Start: 2015-06-11 09:58:06
............................................................................................................................................................................................................................................................................................................
Finished: 2015-06-11 10:03:06
###DOMAIN###:80 192.168.###IP### - - [11/Jun/2015:09:58:06 +0200] "GET /###PATH###/sleepTest.php HTTP/1.1" 200 2177 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0"

ie_backoffice: Start: 2015-06-11 09:58:39
............................................................................................................................................................................................................................................................................................................
Finished: 2015-06-11 10:03:39
###DOMAIN###:443 192.168.###IP### - - [11/Jun/2015:09:58:39 +0200] "GET /###PATH###/sleepTest.php HTTP/1.1" 200 2177 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"

ie_server: Start: 2015-06-11 09:59:08
............................................................................................................................................................................................................................................................................................................
Finished: 2015-06-11 10:04:08
###DOMAIN###:80 192.168.###IP### - - [11/Jun/2015:09:59:08 +0200] "GET /###PATH###/sleepTest.php HTTP/1.1" 200 2177 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"

Un altro test case:
Script automatico sul server, che avvia lo script di test sopra ogni 10 secondi. Gli script di test aggiornano il suo stato in una tabella MySQL. Se termina, la colonna "fine" viene riempita. Altrimenti la colonna "progresso" ha la data dell'ultimo secondo, in cui lo script era ancora in esecuzione. https://jsfiddle.net/v8boufn8/

strace su un processo fallito:

[...]
--- SIGCHLD (Child exited) @ 0 (0) ---
write(22, "\0", 1)                      = -1 EAGAIN (Resource temporarily unavailable)
rt_sigreturn(0x16)                      = 0
close(42)                               = 0
wait4(22231, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 22231
poll([{fd=41, events=POLLIN|POLLPRI}], 1, 0) = 0 (Timeout)
write(41, "\1\0\0\0\16", 5)             = 5
read(41, "\7\0\0\1\0\0\0\2\0\0\0", 16384) = 11
poll([{fd=41, events=POLLIN|POLLPRI}], 1, 0) = 0 (Timeout)
write(41, "\v\0\0\0\2*********", 15)   = 15
read(41, "\7\0\0\1\0\0\0\2\0\0\0", 16384) = 11
poll([{fd=41, events=POLLIN|POLLPRI}], 1, 0) = 0 (Timeout)
write(41, "D\3\0\0\3UPDATE `*******`.`*********"..., 840) = 840
read(41, "0\0\0\1\0\1\0\2\0\0\0(Rows matched: 1  Cha"..., 16384) = 52
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {0x7f423be749d0, [], SA_RESTORER|SA_NOCLDSTOP, 0x7f42509a7f60}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({1, 0}, 0x7fff37f40790)       = 0
writev(40, [{"\27\3\1\0 A0\245\3059\204\365\311\356\334\261tu&\273\236\201e\321\243_\346h\324\226\335\217"..., 111}], 1) = 111
pipe2([42, 43], O_CLOEXEC)              = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f425144ea10) = 22439
close(43)                               = 0
fcntl(42, F_SETFD, 0)                   = 0
fstat(42, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
read(42, "0.99\n", 8192)                = 5
read(42, "", 8192)                      = 0
--- SIGCHLD (Child exited) @ 0 (0) ---
write(22, "\0", 1)                      = -1 EAGAIN (Resource temporarily unavailable)
rt_sigreturn(0x16)                      = 0
close(42)                               = 0
wait4(22439, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 22439
poll([{fd=41, events=POLLIN|POLLPRI}], 1, 0) = 0 (Timeout)
write(41, "\1\0\0\0\16", 5)             = 5
read(41, "\7\0\0\1\0\0\0\2\0\0\0", 16384) = 11
poll([{fd=41, events=POLLIN|POLLPRI}], 1, 0) = 0 (Timeout)
write(41, "\v\0\0\0\2**********", 15)   = 15
read(41, "\7\0\0\1\0\0\0\2\0\0\0", 16384) = 11
poll([{fd=41, events=POLLIN|POLLPRI}], 1, 0) = 0 (Timeout)
write(41, "D\3\0\0\3UPDATE `*******`.`*********"..., 840) = 840
read(41, "0\0\0\1\0\1\0\2\0\0\0(Rows matched: 1  Cha"..., 16384) = 52
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {0x7f423be749d0, [], SA_RESTORER|SA_NOCLDSTOP, 0x7f42509a7f60}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({1, 0},  <unfinished ...>
+++ killed by SIGKILL +++

strace su un processo di successo:

[...]
munmap(0x7f424a7e7000, 1078264)         = 0
munmap(0x7f424a8ef000, 1128872)         = 0
munmap(0x7f4251346000, 1080672)         = 0
close(14)                               = 0
munmap(0x7f423759c000, 67108864)        = 0
close(28)                               = 0
close(38)                               = 0
munmap(0x7f423e2cf000, 2570696)         = 0
munmap(0x7f423c074000, 2463760)         = 0
write(22, "@", 1)                       = -1 EAGAIN (Resource temporarily unavailable)
close(22)                               = 0
close(21)                               = 0
rt_sigaction(SIGCHLD, {SIG_DFL, [], SA_RESTORER|SA_NOCLDSTOP, 0x7f42509a7f60}, {0x7f423be749d0, [], SA_RESTORER|SA_NOCLDSTOP, 0x7f42509a7f60}, 8) = 0
munmap(0x7f423bc61000, 4270440)         = 0
munmap(0x7f423b95f000, 3152520)         = 0
munmap(0x7f423b6f8000, 2517800)         = 0
munmap(0x7f423b59c000, 1425296)         = 0
munmap(0x7f4237203000, 3770008)         = 0
munmap(0x7f4236e74000, 3731272)         = 0
munmap(0x7f423683a000, 1280128)         = 0
munmap(0x7f4235cc6000, 6166888)         = 0
munmap(0x7f424af2d000, 2645224)         = 0
munmap(0x7f424ac19000, 3223576)         = 0
munmap(0x7f424aa03000, 2186232)         = 0
close(9)                                = 0
close(8)                                = 0
exit_group(0)                           = ?

Cosa ti dicono i registri apache? Quindi lo script viene ucciso, ma l'apache continua a funzionare? Cosa succede se si esegue lo script 2 un minuto dopo lo script 1 e lo script 3 due minuti dopo?
SPRBRN

Ho appena eseguito 3 test (vedi domanda modificata con output). Access.log ha solo una voce se le richieste vengono completate correttamente. Altrimenti non ha voce. error.log non contiene alcuna voce rilevante al momento della mancanza. Sì, l'apache continua a funzionare bene per molti giorni.
Wulf

Quindi, se si avviano 6 processi contemporaneamente, fallisce. Quando si avviano 6 processi nel tempo, a un certo punto si fallirà. Cosa succede quando si avviano 10 o 20 processi nel tempo? Cosa succede con il server? Le altre pagine si aprono normalmente? Provare top o htop per il feedback sull'uso della memoria. Cosa succede se si esegue un processo per un lungo periodo? Non è un normale timeout del server? Perché non metti questi script a esecuzione prolungata in una coda e li esegui come script cron?
SPRBRN

Probabilmente lo hai max_execution_time impostato su tre minuti.
David Schwartz

1
max_execution_time nel mio php.ini è impostato su 10830. Anche questo non spiegherebbe, perché gli script falliscono allo stesso tempo indipendentemente dal loro orario di inizio, e non ciascuno dopo x secondi, e solo qualche volta. Ma grazie per la tua risposta!
Wulf

Risposte:


0

A volte il problema potrebbe essere la funzione opcache_reset () chiamata while un altro lo script è eseguito. Il tempo è esattamente di 180 secondi e nel registro php-fpm c'è un messaggio del tipo:

ATTENZIONE: [pool www] child X è uscito sul segnale 9 (SIGKILL) dopo Y secondi dall'inizio

La ragione è php-fpm uccide il suo processo figlio con SIGKILL dopo 3 minuti come indicato in https://bugs.php.net/bug.php?id=75107&thanks=6

opcache_reset () attiva il riavvio di opcache. Se un processo trattiene un blocco SHM per più di opcache.force_restart_timeout secondi dopo l'avvio del riavvio, verrà ucciso. Guarda anche http://php.net/manual/en/opcache.configuration.php#ini.opcache.force-restart-timeout .

Quindi, ci sono 2 soluzioni:

  1. aumentare opcache.force_restart_timeout
  2. smetti di usare opcache_reset negli script auto / crontab. Forse usando http://php.net/manual/en/function.opcache-invalidate.php è abbastanza?
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.