2013-08-13 20 views
7

C'è un buon modo per condividere un blocco multiprocessing tra lavoratori gunicorn? Sto cercando di scrivere un'API json con Flask. Alcune chiamate API interagiranno con una classe python che gestisce un processo in esecuzione (come ffmpeg per la conversione video). Quando ridimensiono il mio numero di web worker a più di 1, come posso garantire che solo 1 lavoratore stia interagendo con la classe nello stesso momento?Condivisione di un blocco tra lavoratori gunicorn

Il mio primo pensiero era di usare il multiprocessing.Lock in modo che la funzione start() possa essere atomica. Io non credo di aver capito il posto giusto per creare un blocco in modo che uno viene condiviso tra tutti i lavoratori:

# runserver.py 
from flask import Flask 
from werkzeug.contrib.fixers import ProxyFix 
import dummy 

app = Flask(__name__) 

@app.route('/') 
def hello(): 
    dummy.start() 
    return "ffmpeg started" 

app.wsgi_app = ProxyFix(app.wsgi_app) 

if __name__ == '__main__': 
    app.run() 

Qui è la mia operazione dummy:

# dummy.py 
from multiprocessing import Lock 
import time 

lock = Lock() 

def start(): 
    lock.acquire() 

    # TODO do work 
    for i in range(0,10): 
     print "did work %s" % i 
     time.sleep(1) 

    lock.release() 

Quando rinfresco la pagina alcune volte, vedo l'output di ogni chiamata tessuta insieme.

Sto abbaiando sull'albero sbagliato qui? Esiste un modo più semplice per assicurarsi che solo la copia della classe di elaborazione (qui solo il metodo dummy start()) venga eseguita contemporaneamente? Penso che potrei aver bisogno di qualcosa come il sedano per eseguire i compiti (e usare solo 1 lavoratore) ma sembra un po 'eccessivo per il mio piccolo progetto.

risposta

5

Ho provato qualcosa e sembra funzionare. Inserisco preload_app = True nel mio gunicorn.conf e ora il blocco sembra essere condiviso. Sto ancora esaminando esattamente cosa sta succedendo qui, ma per ora questo è abbastanza buono, YMMV.

+0

Questo mi ha aiutato. Grazie. – ATOzTOA

3

Seguire la risposta di peterw, i lavoratori possono condividere la risorsa di blocco.

Tuttavia, è preferibile utilizzare il blocco try-finally per garantire che il blocco venga sempre rilasciato.

# dummy.py 
from multiprocessing import Lock 
import time 

lock = Lock() 

def start(): 
    lock.acquire() 

    try: 
     # TODO do work 
     for i in range(0,10): 
      print "did work %s" % i 
      time.sleep(1) 
    finally: 
     lock.release() 
Problemi correlati