2013-08-13 10 views
7

Czy istnieje dobry sposób na udostępnienie blokady wieloprocesowej między pracownikami gunicorn? Próbuję napisać json API z Flask. Niektóre wywołania API będą oddziaływać na klasę Pythona, która zarządza uruchomionym procesem (np. Ffmpeg do konwersji wideo). Kiedy zwiększam liczbę pracowników internetowych do więcej niż 1, jak mogę zagwarantować, że tylko 1 pracownik interakcji z klasą w tym samym czasie?Udostępnianie blokady między pracownikami gunicorn

Moja początkowa myśl polegała na użyciu trybu wieloprocesowego. Blokuj, aby funkcja start() mogła być atomowa. I nie sądzę, bym zorientowali się we właściwym miejscu, aby utworzyć blokadę tak, że jedna jest współdzielona przez wszystkich pracowników:

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

Oto mój manekin operacja:

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

Kiedy odświeżyć na stronie kilka razy, widzę dane wyjściowe z każdego połączenia tkane razem.

Czy szczerzę tu niewłaściwe drzewo? Czy istnieje prostszy sposób, aby upewnić się, że tylko kopia klasy przetwarzania (tutaj tylko sztuczna metoda start() zostanie uruchomiona w tym samym czasie? Myślę, że potrzebuję czegoś takiego jak seler do wykonywania zadań (i używam tylko 1 pracownika), ale wydaje mi się to nieco przesadne w przypadku mojego małego projektu.

Odpowiedz

5

Próbowałem czegoś i wygląda na to, że działa. Umieściłem preload_app = True w moim gunicorn.conf i teraz wydaje się, że blokada jest udostępniana. Nadal dokładnie sprawdzam, co się tutaj dzieje, ale na razie to wystarczająco dobrze, YMMV.

+0

Pomogło mi to. Dzięki. – ATOzTOA

3

Śledź odpowiedź peterw, pracownicy mogą udostępniać zasoby blokady.

Ale lepiej jest użyć bloku try-finally, aby upewnić się, że blokada zostanie zawsze zwolniona.

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