2012-09-26 11 views
11

Qualsiasi server Web potrebbe dover gestire un sacco di richieste allo stesso tempo. Poiché l'interprete python ha effettivamente un vincolo GIL, come viene implementata la concorrenza?Come supera un server web Python GIL

Usano più processi e utilizzano IPC per la condivisione dello stato?

+4

Che condivisione dello stato? L'intero punto delle richieste web è che ognuna è indipendente, non esiste uno stato condiviso. –

risposta

2

Come normale. Il servizio Web è principalmente legato all'I/O e GIL viene rilasciato durante le operazioni di I/O. Quindi, il threading viene utilizzato senza alcuna sistemazione speciale o viene utilizzato un ciclo di eventi (come Twisted).

+1

Non sto parlando di attesa/ricezione richiesta. Sto parlando di gestirli. Ad esempio, se ricevo una richiesta, potrei dover eseguire qualche elaborazione, come il controllo di varie richieste POST o GET, che di solito viene scritta come codice Python. Quindi, come interpreta Python eseguirà questi blocchi di codice in concomitanza con il vincolo GIL. –

+2

Questo è semplicemente falso. Non tutti i carichi di lavoro sono vincolati all'IO. È del tutto comune vedere i server Web con CPU con prestazioni massime. Dipende dall'applicazione in esecuzione. – usr

1

Di solito si hanno molti lavoratori (cioè gunicorn), ciascuno con richieste indipendenti. Tutto il resto (relativo alla concorrenza) viene gestito dal database in modo tale da essere estratto da voi.

Non hai bisogno di IPC, basta una "singola fonte di verità", che sarà il RDBMS, un server cache (Redis, memcached), ecc

1

Prima di tutto, le richieste possono essere gestito in modo indipendente. Tuttavia, i server vogliono simultaneamente gestirli al fine di mantenere il numero di richieste che possono essere gestite per volta al massimo.

L'implementazione di questo concetto di concorrenza dipende dal server web.

Alcune implementazioni possono avere un numero fisso di thread o processi per la gestione delle richieste. Se tutti sono in uso, le richieste aggiuntive devono attendere fino a quando non vengono gestite.

Un'altra possibilità è che un processo o un thread venga generato per ogni richiesta. Generare un processo per ogni richiesta porta ad una memoria assurda e sovraccarico della CPU. Generare fili leggeri è meglio. In questo modo, puoi servire centinaia di clienti al secondo. Tuttavia, anche i thread portano il loro overhead di gestione, manifestandosi in alta memoria e consumo di CPU.

Per servire migliaia di client al secondo, un'architettura basata sugli eventi basata su coroutine asincrone è una soluzione all'avanguardia. Consente al server di servire i client ad alta velocità senza generare milioni di miliardi di thread. Sul numero Wikipedia page of the so-called C10k problem si trova un elenco di server Web. Tra questi, molti fanno uso di questa architettura.

Le coroutine sono disponibili anche per Python. Dai un'occhiata allo http://www.gevent.org/. Ecco perché un'applicazione Python WSGI basata su ad esempio uWSGI + gevent è una soluzione estremamente performante.

+0

"Creazione di un processo per ogni richiesta porta a un'assurda memoria e sovraccarico della CPU." Questo dipende completamente dal sistema operativo. –

+0

@ IgnacioVazquez-Abrams: per quale sistema operativo questo non è vero ("assurdo" era inteso in confronto al sovraccarico di threading o coroutine)? –

+0

Non è che non sia vero, è che la definizione esatta di "assurdo" varia; Windows è una grande pila fumante di escrementi benedetti quando si tratta di avviare nuovi processi, ma i netti tendono ad essere un po 'più leggeri in confronto. –