2013-08-13 2 views
7

Есть ли хороший способ разделить многопроцессорный замок между рабочими-стрелками? Я пытаюсь написать json API с Flask. Некоторые вызовы API будут взаимодействовать с классом python, который управляет запущенным процессом (например, ffmpeg для преобразования видео). Когда я увеличиваю количество веб-работников до более чем 1, как я могу гарантировать, что только один рабочий взаимодействует с классом одновременно?Разделение замка между рабочими-артиллеристами

Моя первоначальная мысль заключалась в использовании многопроцессорности. Блокировка, поэтому функция start() может быть атомарной. Я не думаю, что я понял, правильное место, чтобы создать блокировку, так что один является общим для всех работников:

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

Вот моя фиктивная операция:

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

Когда я обновить страницу несколько раз, я вижу результат каждого вызова, сотканного вместе.

Я здесь лаяю неправильное дерево? Есть ли более простой способ убедиться, что одновременно запускается только копия класса обработки (здесь только метод dummy start())? Я думаю, мне может понадобиться что-то вроде сельдерея для запуска задач (и просто использовать только одного работника), но это кажется немного излишним для моего небольшого проекта.

ответ

5

Я пробовал что-то, и это работает. Я положил preload_app = True в свой gunicorn.conf, и теперь блокировка, кажется, поделена. Я все еще смотрю на то, что здесь происходит, но на данный момент это достаточно хорошо, YMMV.

+0

Это помогло мне. Благодарю. – ATOzTOA

3

Следуйте за ответом peterw, рабочие могут совместно использовать ресурс блокировки.

Но, лучше использовать блок try-finally для обеспечения того, чтобы блокировка всегда была отпущена.

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