2009-10-09 17 views
5

Sono responsabile della parte di backend di un'API, scritta in PHP, che viene principalmente utilizzata da un client Flash. Quello che succede ora è: il client Flash effettua una chiamata, il back-end carica i dati necessari, esegue qualsiasi elaborazione e post-elaborazione, registrazione e memorizzazione nella cache e restituisce il risultato al client.PHP + gzip: chiudi connessione e continua a eseguire

Quello che mi piacerebbe che succedesse è restituire i dati al client il più presto possibile, chiudere la connessione, e poi fare tutto ciò di cui il cliente non deve preoccuparsi. Ciò potrebbe rendere l'API molto più reattiva. Seguendo i suggerimenti qui:

http://php.net/manual/en/features.connection-handling.php

effettivamente funziona, solo che devo disattivare la codifica gzip al fine di farlo funzionare, il che non è molto pratico. Usiamo mod_deflate in apache, quindi una soluzione che funzioni sarebbe ideale, ma prenderei anche in considerazione un metodo diverso per gzip il nostro contenuto, se necessario.

E sembra come dovrebbe esserci un modo per far sapere ad Apache "Ti ho mandato tutti i dati che sto per inviare", ma non riesco a trovare nulla di simile.

Per coloro che si chiedono, sì, posso svuotare i risultati in anticipo, ma il client Flash non li elabora fino a quando la connessione non viene chiusa.

risposta

3

Si potrebbe provare a dividerlo in due pagine.

Nella prima pagina, eseguire l'elaborazione necessaria, quindi caricare la seconda pagina tramite arricciatura e morire().

Ciò causerebbe il completamento e la chiusura della prima pagina, indipendentemente dall'elaborazione della seconda pagina.

cioè:

Pagina 1:

Pagina 2:

<?php 

// Do other stuff.... 

?> 

Vedi http://www.php.net/curl

+0

Grazie. Sono a conoscenza di alcuni accorgimenti per questo problema, alcuni più eleganti di altri, ma mi piacerebbe davvero trovare un modo per dire semplicemente ad Apache di smettere di aspettare l'output e chiudere la connessione. :) –

0

C'è una sorta di hack per farlo mettendo il codice che si desidera da eseguire dopo la chiusura della connessione all'interno di un metodo di richiamata registrato tramite register_shutdown_function();

+0

Ooh, lucido! Ci proverò domani. –

+0

Nessuna fortuna. Il seguente esempio stampa la merda extra e impiega il tempo di esecuzione completo per chiudere la connessione quando si utilizza mod_deflate: function sleepLongTime() {print "non puoi vedere questo"; il sonno (30); } ob_end_clean(); register_shutdown_function ('sleepLongTime'); intestazione ("Connessione: chiudi \ r \ n"); ignore_user_abort (true); ob_start(); echo ('L'utente del testo vedrà'); ob_end_flush(); flush(); ob_end_clean(); die(); –

0

@ Theo.T dal momento che il sistema di commenti maciullato la merda di mio codice, sto postando qui:

Nessuna fortuna. Le seguente codice stampa la merda in più e prende il tempo di esecuzione pieno per chiudere la connessione quando si utilizza mod_deflate:

function sleepLongTime() { 
    print "you can't see this"; 
    sleep(30); 
} 
ob_end_clean(); 
register_shutdown_function('sleepLongTime'); 
header("Connection: close\r\n"); 
ignore_user_abort(true); 
ob_start(); 
echo ('Text user will see'); 
ob_end_flush(); 
flush(); 
ob_end_clean(); 
die(); 
0
set_time_limit(0); 
header("Connection: close"); 
header("Content-Length: " .(strlen($stream)+256)); 
ignore_user_abort(true); 

echo $stream; 
echo(str_repeat(' ',256)); 
@ob_flush(); 
@flush(); 
@ob_end_flush(); 

your_long_long_long_long_function_here(); 

questo vi dirà all'utente di chiudere la connessione una volta che tutti $stream è ricevuto. ma fai attenzione a non ripetere nulla prima della parte header: p

se invii dati binari (swf) potresti dover rimuovere '+256' e echo(str_repeat(' ',256)); ma in questo caso il codice 'potrebbe' fallire se i dati inviati sono les di 256 byte.

-1

Anche oggi ho incontrato questo caso, dopo alcuni test in giro, ho trovato in questo modo funziona:

due fasi:

  1. assicurarsi che l'output dello script php non è con la codifica gzip, la soluzione può fare riferimento a questo link:

    <IfModule mod_env.c>
    SetEnvIfNoCase Request_URI "\.php$" no-gzip dont-vary
    </IfModule>

Aggiungere il sopra per .htaccess file con il sito web prj, quindi evitare di gzip apache automaticamente.

  1. Come alcune persone hanno detto a features.connection-handling.php,

    set_time_limit(0); 
    ignore_user_abort(true);  
    // buffer all upcoming output - make sure we care about compression: 
    if(!ob_start("ob_gzhandler")) 
        ob_start();   
    echo $stringToOutput;  
    // get the size of the output 
    $size = ob_get_length();  
    // send headers to tell the browser to close the connection  
    header("Content-Length: $size"); 
    header('Connection: close');  
    // flush all output 
    ob_end_flush(); 
    ob_flush(); 
    flush();  
    // close current session 
    if (session_id()) session_write_close(); //close connection 
    
    // here, do what you want. 
    
+0

Richiede gzip e tu non dai una risposta gzip ... questo non aiuta. – brunoais

Problemi correlati