2012-10-25 8 views
5

Stiamo rendendo la nostra prima applicazione Django sotto mod_wsgi comedjango + mod_wsgi richiede una disciplina di programmazione con thread?

`WSGIDaemonProcess our-appname processes=6 threads=15'` 

e stiamo avendo una discussione su se il nostro codice Python e le librerie Redis e Postgres che utilizza necessità di essere thread-safe o meno.

Da quello che posso dire dalla lettura della documentazione mod_wsgi, anche se il lavoratore apache sta elaborando le richieste con più apache le discussioni, il nostro codice python è per tutti gli effetti single-threaded. Non vedo alcun avviso sui documenti mod_wsgi che dicono "Attenzione! Ora devi preoccuparti dei dati globali e della sicurezza dei thread!" ma non c'è anche alcun esplicito "Non preoccuparti dei thread non ce ne sono".

Non stiamo facendo nulla in modo esplicito con i thread nel nostro codice Python, non c'è alcun riferimento a ciò che abbiamo scritto.

Ma alcune persone qui sono dell'opinione che dal momento che stiamo correndo con threads=15 che siamo ora nel mondo multi-threaded.

Qualcuno può chiarire cosa sta succedendo? Il nostro codice Python ora è soggetto a più thread di esecuzione attraverso gli stessi dati in cui non era prima, o no?

risposta

6

Sì, ovviamente, si esegue un'applicazione multi-threaded e creerà problemi se non si prendono cura con globali, classe attributi ecc

Se hai bisogno di tenere qualcosa a livello globale, tenerlo in memoria locale thread.

Ecco una citazione da modwsgi doc, Building_A_Portable_Application

3. Una domanda deve essere ri-entrata, o semplicemente messa, essere in grado di essere chiamata contemporaneamente da più thread contemporaneamente. I dati che devono esistere per la durata della richiesta, devono essere archiviati come dati basati sullo stack , dati locali del thread o memorizzati nella cache nell'ambiente dell'applicazione WSGI. Le variabili globali all'interno del modulo applicativo effettivo non possono essere utilizzate a questo scopo.

Quindi penso che tu sia stato sufficientemente avvertito.

0

Il pitone interprete non è thread-safe, in particolare a causa del conteggio di riferimento, in modo thread non possono accedere agli oggetti pitone contemporaneamente nello stesso spazio di processo. Non è possibile configurare mod_wsgi per aggirare questo, accidentalmente o intenzionalmente, perché l'interprete è protetto da GIL (global interpreter lock). Pertanto, non ci si deve preoccupare dei problemi di sicurezza dei thread particolarmente complicati che derivano dal rischio che thread simultanei accedano agli stessi oggetti di memoria (blocco della memoria, ecc.).

Alcuni server Web come gunicorn con un gevent backer avranno più thread in memoria contemporaneamente in modo che nessun processo individuale debba essere bloccato su I/O (accesso al database, accesso alla rete, ecc.). Questo potrebbe anche essere il caso di mod_wsgi. Tuttavia, questo è implementata in modo tale che non dovrebbe essere necessario preoccuparsi nel codice dell'applicazione - se l'applicazione è sicuro da usare in multiprocessing dovrebbe anche essere sicuri da usare in questo tipo di filettatura non simultanea limitata modello.

Ovviamente, non è possibile utilizzare variabili globali o modificare dinamicamente parti dell'applicazione durante l'esecuzione, ma se si sta facendo qualcosa del genere in Django, si incontreranno problemi anche prima di dover preoccuparsi del threading. Django e altri framework web sono progettati in modo tale che i dati vengano trasmessi come una richiesta e come risposta senza doversi preoccupare della sicurezza del thread/processo all'interno di quel modello.

È necessario preoccuparsi dell'accesso simultaneo agli archivi di dati (in particolare le voci del database), come per qualsiasi applicazione Web. Codice in modo difensivo quando si tratta di accesso al database.

+1

Scusate, ma trovo molto confusa la frase che la precede. L'interprete Python stesso è thread-safe, se non lo fosse, si bloccherebbe dappertutto. Lo stato interno dell'interprete Python e la gestione dei conteggi di riferimento sono mediati da GIL come dici tu ed è ciò che garantisce che sia sicuro utilizzare l'interprete Python con più thread. Così cattivo modo di spiegarlo. Anche gunicorn con gevent non ha più thread. Quando si utilizza gevent sono tecnicamente coroutine non thread, anche se li fa apparire come thread. –

+1

Ora il problema del codice a livello di applicazione che è thread-safe è un problema diverso, ma non confondere questo se l'interprete Python è thread-safe. –

+0

Sul primo conteggio, suppongo sia vero, anche se non sono sicuro che sia meno preciso descrivere l'interprete python come non thread-safe per le operazioni di memoria sugli oggetti python nello stesso momento piuttosto che spiegare che è thread-safe perché il GIL impedisce ai thread di fare quanto sopra. Al secondo conteggio, sono d'accordo; gevent usa "fili verdi" che tecnicamente non sono thread - avrei dovuto spiegarlo. –

1

Penso che la risposta di Andrew sia un po 'fuorviante. Il fatto che CPython (si noti che ci sono altre implementazioni Python come Jython e PyPy) ha GIL non significa che non devi preoccuparti che il tuo codice sia thread-safe! A causa di GIL, non è possibile attivare contemporaneamente due thread in un processo. Ma il parallelismo viene simulato passando periodicamente tra i thread. E un tale interruttore di contesto può verificarsi in qualsiasi momento durante l'esecuzione del programma. Ad esempio, se si dispone di un modulo foo contenente una variabile "globale" x, il seguente metodo potrebbe generare qualsiasi output da 2, 3, 4, ..., a seconda del numero di thread che eseguono lo stesso metodo:

def bar(): 
    foo.x = 1 
    # a context switch might happen here! 
    foo.x = foo.x + 1 
    # or here! 
    print(foo.x) 

In realtà, è possibile configurare mod_wsgi per utilizzare max. 1 filo. E quindi non devi preoccuparti della sicurezza dei thread. Ma la correttezza del tuo programma dipenderà dalla configurazione del server web, che è una situazione molto indesiderabile.

Problemi correlati