2013-08-13 5 views
7

Gibt es eine gute Möglichkeit, eine Mehrfachverarbeitungssperre zwischen Gunicorn-Arbeitern zu teilen? Ich versuche eine json API mit Flask zu schreiben. Einige der API-Aufrufe interagieren mit einer Python-Klasse, die einen laufenden Prozess verwaltet (z. B. ffmpeg für die Videokonvertierung). Wenn ich meine Anzahl an Web-Mitarbeitern auf mehr als 1 aufstocken kann, wie kann ich sicherstellen, dass nur ein Mitarbeiter gleichzeitig mit der Klasse interagiert?Freigeben einer Sperre zwischen Gunicorn-Arbeitern

Mein erster Gedanke war, Multiprocessing.Lock zu verwenden, so dass die Funktion start() atomar sein kann. Ich glaube nicht, dass ich den richtigen Platz heraus eine Sperre zu schaffen, so dass man über alle Arbeiter geteilt wird:

# 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() 

Hier ist mein Dummy-Betrieb:

# 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() 

Wenn ich auffrischen die Seite ein paar Mal, sehe ich die Ausgabe von jedem Anruf zusammengewoben.

Banne ich hier den falschen Baum? Gibt es einen einfacheren Weg, um sicherzustellen, dass nur die Kopie der Verarbeitungsklasse (hier nur die Dummy-Methode start) gleichzeitig ausgeführt wird? Ich denke, ich brauche vielleicht etwas wie Sellerie, um Aufgaben zu erledigen (und benutze nur 1 Arbeiter), aber das scheint ein bisschen übertrieben für mein kleines Projekt.

Antwort

5

Ich habe etwas versucht, und es scheint zu funktionieren. Ich setze preload_app = True in meine gunicorn.conf und jetzt scheint das Schloss geteilt zu werden. Ich schaue immer noch genau, was hier passiert, aber fürs erste ist das gut genug, YMMV.

+0

Das hat mir geholfen. Vielen Dank. – ATOzTOA

3

Folgen Sie Peterw's Antwort, die Arbeiter können die Sperre Ressource teilen.

Aber, es ist besser, try-finally Block zu verwenden, um sicherzustellen, dass die Sperre immer freigegeben wird.

# 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() 
Verwandte Themen