Visualizzazione risultati 1 fino 5 di 5

Discussione: PHP esecuzione script dopo invio risposta

  1. #1
    matest non è connesso Utente AlterBlog
    Data registrazione
    16-04-2017
    Messaggi
    3

    Predefinito PHP esecuzione script dopo invio risposta

    Dovrei eseguire parte di uno script in php dopo aver inviato la risposta al client, in modo da evitare attese inutili (devo inviare una notifica).
    Stavo cercando una soluzione e ho trovato questa:
    Codice PHP:
    ob_end_clean();
    header("Connection: close");
    ignore_user_abort(true); // just to be safe
    ob_start();
    echo(
    'Text the user will see');
    $size ob_get_length();
    header("Content-Length: $size");
    ob_end_flush(); // Strange behaviour, will not work
    flush(); // Unless both are called !
    // Do processing here 
    sleep(5);
    echo(
    'Text user will never see'); 
    In locale funziona perfettamente, mentre quando lo carico su altervista lo script mostra entrambi gli echo e attende i 5 secondi dello sleep... Sto usando qualche funzione non supportata? Uso php 5.6

    Grazie in anticipo!
    Ultima modifica di matest : 16-04-2017 alle ore 19.10.28

  2. #2
    mzanella non è connesso AlterVistiano
    Data registrazione
    29-12-2015
    Messaggi
    806

    Predefinito

    Mi sembra strano che funzioni in locale!

    Analizzato riga per riga, quel codice impartisce le seguenti istruzioni:
    1. vuota il buffer output buffering
    2. imposta il tipo di connessione a close: una volta inviati tutti i dati, la connessione sarà chiusa e non "riciclata"
    3. se l'utente si disconnette, continua comunque l'esecuzione dello script
    4. ob_start() da ora in poi, scrivi nel buffer
    5. echo ...: scrivi dell'output (nel buffer)
    6. $size = ...: leggi la lunghezza dell'output scritto
    7. header(...): imposta il content-length del messaggio HTTP ad un valore (sbagliato!)
    8. ob_end_flush(): fine della scrittura sul buffer,svuota il buffer e d'ora in poi mostra l'output normalmente
    9. flush(): invia il messaggio parziale costruito fin'ora
    10. sleep(5): aspetta 5 secondi
    11. echo ...: mostra altro output
    12. (operazioni implicite al termine dello script): invia la parte finale del messaggio al client, comprendente la sequenza di caratteri che indica la fine del messaggio, e chiudi la connessione

    Probabilmente il motivo per cui in locale funziona e online no va cercato nella configurazione del server. Per motivi di efficienza, il server potrebbe "ignorare" il comando flush(), porre il risultato parziale in un buffer, aspettare il completamento dello script, ed inviare il contenuto del buffer, magari anche correggendo lo header content-type.

    Se hai due blocchi di codice in cui il secondo va eseguito dopo il primo ma indipendentemente dall'invio della risposta HTTP, dovresti usare qualche tecnica di calcolo parallelo anziché trucchi strani [img]http://forum.it.altervista.org/images/smilie/icon_smile.gif[/i].

    Una strategia potrebbe essere usare una fork: esegui il blocco di codice che produrrà l'output ed esegui la fork. Il processo padre terminerà subito, restituendo l'output al client, il processo figlio continuerà per la sua stra in maniera indipendente facendo le operazioni che deve fare.

    In alternativa potresti separare l'esecuzione in due pagine, una che restituisca l'output richiesto e poi invii una richiesta HTTP asincrona ad una seconda pagina (ad esempio attraverso cURL) in modo che questa esegua i suoi calcoli in maniera indipendente.

    C'è una "terza strada" che è quella di chiedersi se sia necessario: parallelizzare il codice comporta "spese" di progettazione e mantenimento, che non sempre sono giustificate dal guadagno di prestazioni, soprattutto in ambiente web dove i tempi dovuti a latenza e larghezza di banda sono spesso dominanti.
    In termini concreti, se la pagina "ottimizzata" impiega 500 ms per caricarsi, e la parallelizzazione ti fa guadagnare 5-10 ms, il guadagno è trascurabile... Diversa è la questione se la parallelizzazione fa guadagnare 5 secondi! Dunque, valuta tu .

  3. #3
    matest non è connesso Utente AlterBlog
    Data registrazione
    16-04-2017
    Messaggi
    3

    Predefinito

    La parallelizzazione mi serve perché dovrei inviare delle notifiche push tramite firebase, quindi invio una richiesta con curl alle api google, ma la risposta ci mette qualche secondo ad arrivare, e quindi blocca tutto.
    Forse potrei rendere questa richiesta asincrona ?
    Ho provato con il fork ma sembra non si possa usare su altervista...

    Grazie mille per la risposta!

    EDIT: Non riesco a trovare un modo per eseguire una richiesta con curl in modo asincrono...
    Comunque ho corretto il codice di prima:
    Codice PHP:
    ob_start();
    echo 
    "ok"
    header('Connection: close');
    header("Content-Encoding: none");
    header('Content-Length: '.ob_get_length());
    ob_end_flush();
    ob_flush();
    flush();
    echo 
    "Non visibile"
    Su EasyPHP funziona, e penso che il problema su altervista sia il fatto che non imposta "Connection: close'". Su altervista il valore rimane "keep-alive", e quindi non chiude la connessione. Ci sarebbe un modo per impostarlo ?
    Ultima modifica di matest : 17-04-2017 alle ore 21.31.40

  4. #4
    mzanella non è connesso AlterVistiano
    Data registrazione
    29-12-2015
    Messaggi
    806

    Predefinito

    C'è un articolo che parla di "multithreading" con cURL qui: Multithreading in PHP with CURL.

    cURL Easy, tra le altre cose, permette di effettuare chiamate HTTP non bloccanti (cerca tra gli esempi "###Single request without blocking").

    Infine, puoi sempre usare fsockopen e costruirti a mano il messaggio HTTP, che probabilmente è la soluzione più performante: sending a non-blocking HTTP POST request.

    Su altervista il valore rimane "keep-alive", e quindi non chiude la connessione. Ci sarebbe un modo per impostarlo ?
    Il metodo era appunto impostare lo header, ma se il server decide di ignorare tale direttiva non credo ci sia modo di aggirarlo.

  5. #5
    matest non è connesso Utente AlterBlog
    Data registrazione
    16-04-2017
    Messaggi
    3

    Predefinito

    Ok sono riuscito a farlo con fsockopen seguendo l'esempio nel link!

    Grazie ancora

Tags for this Thread

Regole di scrittura

  • Non puoi creare nuove discussioni
  • Non puoi rispondere ai messaggi
  • Non puoi inserire allegati.
  • Non puoi modificare i tuoi messaggi
  •