2013-02-13 10 views
5

Sto cercando di servire richieste a lungo termine usando gunicorn e i suoi dipendenti asincroni ma non riesco a trovare alcun esempio che possa arrivare a lavorare. Ho usato l'esempio here ma ottimizzato per aggiungere un ritardo falso (sonno per 5s) prima di ritornare la risposta:gunicorn non elabora simultaneamente richieste simultanee

def app(environ, start_response): 
    data = "Hello, World!\n" 
    start_response("200 OK", [ 
     ("Content-Type", "text/plain"), 
     ("Content-Length", str(len(data))) 
    ]) 
    time.sleep(5) 
    return iter([data]) 

Poi corro così gunicorn:

gunicorn -w 4 myapp:app -k gevent

Quando apro due del browser schede e digitare http://127.0.0.1:8000/ in entrambi e inviare le richieste quasi allo stesso tempo, le richieste sembrano essere elaborate sequenzialmente - una restituisce dopo 5 secondi e l'altra restituisce dopo un ulteriore 5 secondi.

D. Penso che il sonno non sia amichevole? Ma ci sono 4 lavoratori e quindi anche se il tipo di lavoratore fosse "sincronizzato" due lavoratori dovrebbero gestire due richieste contemporaneamente?

+0

Hai trovato la soluzione? –

+0

Scusa, non l'ho fatto. – swoop81

risposta

5

Mi sono imbattuto nella stessa cosa, ho aperto una domanda qui: Requests not being distributed across gunicorn workers. Il risultato è che sembra che il browser serializzi l'accesso alla stessa pagina. Forse suppongo che questo abbia qualcosa da fare con la cacheability, cioè il browser pensa che sia probabile che la pagina sia memorizzabile nella cache, aspetta fino a quando non viene scoperto che non è così fa un'altra richiesta e così via.

+0

Così fastidioso e così semplice ... :( – jwg

+0

Grazie a @CrazyCasta Ho verificato la tua risposta installando un altro browser e inviando richieste da due browser separati (chromium e firefox) contemporaneamente, e le richieste vengono revisionate in parallelo. – swoop81

0

Inviare gevent.sleep un colpo invece di time.sleep.

E 'strano che questo sta accadendo con -w 4, ma -k gevent è un tipo di lavoratore asincrona, quindi è possibile gunicorn sta alimentando entrambe le richieste per lo stesso cliente. Supponendo che ciò che sta accadendo, time.sleep bloccherà il tuo processo a meno che non usi gevent.monkey.patch_all().

1

Quando si utilizza gunicorn con tipo di lavoratore non bloccante, come gevent, verrà utilizzato SOLO UN processo che gestisce le richieste, quindi non sorprende che il lavoro di 5 secondi sia stato eseguito in sequenza.

Il lavoratore asincrono è utile quando il carico di lavoro è leggero, e la richiesta di tasso è rapido, in questo caso, gunicorn possono utilizzare volte sprecato ad aspettare IO (come, in attesa di presa per essere scrivibile di scrivere la risposta ad esso) , passando a un altro lavoratore per elaborare un'altra richiesta. passando a un'altra richiesta assegnata allo stesso operatore.

UPDATE

mi sbagliavo.

Quando si utilizza gunicorn con tipo worker non bloccante, con le impostazioni worker in gunicorn, ogni worker è un processo che esegue una coda separata.

Quindi, se lo time.sleep è stato eseguito su un processo diverso, verrà eseguito simultaneamente, ma quando viene eseguito nello stesso worker, verrà eseguito in modo sequenziale.

Il problema è che il loadbalancer gunicorn potrebbe non aver distribuito le due richieste in due processi di lavoro. È possibile controllare il processo corrente tramite os.getpid().

+0

Gunicorn non usa solo un processo per gestire le richieste, usa il numero specificato come il flag '-w'. –

+0

@ ron.rothman È vero! La mia spiegazione è sbagliata, grazie per averlo menzionato. – tdihp

Problemi correlati