2011-06-30 6 views
14

Sto usando mod_wsgi per servire un sito django tramite Apache. Ho anche qualche codice Python che viene eseguito come processo in background (dameon?). Continua a interrogare un server e inserisce i dati in uno dei modelli Django. Funziona bene ma posso avere questo codice come parte della mia applicazione Django e tuttavia in grado di funzionare costantemente in background? Non ha bisogno di essere un processo di per sé, ma un'arte del sito Django che è costantemente attiva. Se sì, potresti indicarmi un esempio o una documentazione che mi aiuterebbe a realizzare questo?Posso avere qualche codice eseguito costantemente all'interno di Django come un demone

Grazie.

risposta

14

È possibile impostare un processo cron che esegua alcune funzioni definite dall'utente o - il metodo più avanzato e probabilmente consigliato, integrare celery nel progetto (che in realtà è abbastanza semplice).

+0

Sono andato con Celery. Ha funzionato come un fascino. –

+0

un'attività cron non viene eseguita continuamente in background, ma inizia in un dato momento e termina quando è pronta. Dato che i comandi di django richiedono un tempo di avvio di 1.5 secondi (a partire dalla complessità dei modelli), questo non è solitamente il modo di farlo quando sono necessarie prestazioni elevate. – FeedTheWeb

+0

È ancora valido? Se sì, quale sarebbe un buon modo di demonizzare l'attività di Celery che farebbe la mia lunga elaborazione? –

9

è possibile creare un thread in background dallo script WSGI prima volta che viene importato.

import threading 
import time 

def do_stuff(): 
    time.sleep(60) 
    ... do periodic job 

_thread = threading.Thread(target=do_stuff) 
_thread.setDaemon(True) 
_thread.start() 

Per far funzionare tutto questo anche se si dovrebbe essere utilizzando un solo processo demone altrimenti ogni processo avrebbe fatto la stessa cosa che probabilmente non si vuole.

Se si utilizza più processi in un gruppo di processi daemon, un'alternativa è creare un gruppo di processi daemon speciale il cui unico scopo è eseguire questo thread in background. In altre parole, il processo non riceve alcuna richiesta.

È possibile farlo avendo:

WSGIDaemonProcess django-jobs processes=1 threads=1 
WSGIImportScript /usr/local/django/mysite/apache/django.wsgi \ 
    process-group=django-jobs application-group=%{GLOBAL} 

La direttiva WSGIImportScript dice di caricare lo script ed eseguirlo all'avvio nel contesto del gruppo processo 'django-posti di lavoro'.

Per evitare di dover più script, ho sottolineato che a quello che sarebbe stato il file originale di script WSGI utilizzato per WSGIScriptAlias. Noi non vogliamo che venga eseguito quando viene caricato da tale direttiva, però, così facciamo:

import mod_wsgi 

if mod_wsgi.process_group == 'django-jobs': 
    _thread = threading.Thread(target=do_stuff) 
    _thread.setDaemon(True) 
    _thread.start() 

Qui si esamina il nome del gruppo di processo demone e solo quando viene eseguito avviato nell'ambito del processo demone speciale gruppo istituito con processo unico solo per questo.

Nel complesso si sta semplicemente utilizzando Apache come un gestore di processo glorioso grande, anche se uno che è già noto per essere robusto. È un po 'eccessivo dato che questo processo consumerà memoria aggiuntiva oltre a quelle che accettano e gestiscono le richieste, ma a seconda della complessità di ciò che stai facendo può comunque essere utile.

Un aspetto carino di questo è che poiché è ancora un'applicazione Django completa, è possibile mappare URL specifici solo per questo processo e quindi fornire un'API remota per gestire o monitorare l'attività in background e cosa sta facendo .

WSGIDaemonProcess django-jobs processes=1 threads=1 
WSGIImportScript /usr/local/django/mysite/apache/django.wsgi \ 
    process-group=django-jobs application-group=%{GLOBAL} 

WSGIDaemonProcess django-site processes=4 threads=5 
WSGIScriptAlias//usr/local/django/mysite/apache/django.wsgi 

WSGIProcessGroup django-site 
WSGIApplicationGroup %{GLOBAL} 

<Location /admin> 
WSGIProcessGroup django-jobs 
</Location> 

Qui, tutti gli URL tranne per le cose di sotto run/admin in 'django-site', con/admin nel 'django-posti di lavoro'.

In ogni caso, che affronta la questione specifica di farlo all'interno del Apache mod_wsgi processo demone come richiesto.

Come indicato, l'alternativa è quella di avere uno script da riga di comando che imposta e carica Django e fa il lavoro ed esegue quello da un cron job.Uno script da riga di comando indica l'utilizzo occasionale di memoria temporanea, ma il costo di avvio per il lavoro è più elevato in quanto è necessario caricare ogni volta ogni cosa.

+0

+1 slick Non avevo idea che mod_wsgi avesse una risposta per questo. –

+0

Se usi Gunicorn, puoi iniziare una nuova discussione ignorando la funzione 'when_ready' di Gunicorn. Ecco un esempio: https://github.com/benoitc/gunicorn/blob/master/examples/example_config.py –

+0

Dalla memoria, '' when_ready'' viene eseguito nel processo genitore di gunicorn. In genere non è una buona idea fare cose di lunga data in un processo genitore. Il processo padre sarà biforcato per diventare processi di lavoro e ci possono essere implicazioni dall'intromissione di qualsiasi stato causato dal thread in background, anche se il thread in background non sarebbe sopravvissuto al fork. –

0

Ho già utilizzato un cron job ma, ti dico, dopo un po 'passerai al sedano.

Il sedano è la strada da percorrere. Inoltre, è possibile eseguire un lungo processo asincrono in modo da velocizzare il tempo di richiesta/risposta.