繁体   English   中英

在 gunicorn 工人之间共享锁

[英]Sharing a lock between gunicorn workers

有没有一种在 gunicorn 工人之间共享多处理锁的好方法? 我正在尝试用 Flask 编写一个 json API。 一些 API 调用将与管理正在运行的进程的 python 类交互(如用于视频转换的 ffmpeg)。 当我将网络工作者的数量扩大到 1 个以上时,如何确保只有 1 个工作者同时与班级互动?

我最初的想法是使用 multiprocessing.Lock 以便 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()

当我刷新页面几次时,我看到每个调用的输出交织在一起。

我在这里吠错树了吗? 有没有更简单的方法来确保只有处理类的副本(这里只是虚拟 start() 方法)同时运行? 我想我可能需要像 celery 这样的东西来运行任务(并且只使用 1 个工人),但这对于我的小项目来说似乎有点矫枉过正。

我尝试了一些东西,它似乎有效。 我把preload_app = True放在我的gunicorn.conf ,现在锁似乎是共享的。 我仍在调查这里到底发生了什么,但现在这已经足够了,YMMV。

按照 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()

后期补充:
如果由于某种原因,使用preload_app不可行,那么您需要使用命名锁 这确保所有进程都使用相同的锁对象。 使用mp.Lock()将为每个进程创建一个不同的对象,否定任何值。

我看到了这个包,但还没有使用它。 它在一台机器的范围内提供一个命名锁; 这意味着同一台机器内的所有进程将使用相同的锁,但在一台机器的边界之外,这种解决方案是不合适的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM