And*_*lan 7 gil python-multithreading flask uwsgi python-3.x
我有一个 Flask 应用程序,在命令行上运行时可以正常工作,但是当它通过 uWSGI 运行时,它无法正确响应请求或工作线程无法正常工作。我重写了一个简单的概念验证/失败程序来演示这个问题:
from datetime import datetime
from threading import Event, Thread
from flask import Flask
class JobManager:
def __init__(self):
self.running = False
self.event = Event()
def start(self):
self.running = True
while self.running:
print("Processing Job at", datetime.now().strftime('%c'))
self.event.clear()
self.event.wait(5)
if self.event.is_set():
print("Interrupted by request!")
def stop(self):
self.running = False
self.event.set()
app = Flask(__name__)
jobs = JobManager()
t = Thread(target=jobs.start)
t.start()
@app.route('/')
def hello_world():
global jobs
jobs.event.set()
return "I'm alive at " + datetime.now().strftime('%c')
if __name__ == '__main__':
app.run()
Run Code Online (Sandbox Code Playgroud)
我希望调用 / 路由会打印“被请求中断!” 在控制台上,但即使作业应该在单独的线程中运行,它也会挂起。
我的 uWSGI 配置是:
[uwsgi]
module = app:app
master = true
processes = 5
threads = 2
socket = 0.0.0.0:5000
protocol = http
reload-mercy = 5
worker-reload-mercy = 5
die-on-term = true
enable-threads = true
thunder-lock = true
logto = /home/user/dev/flask-thread/uwsgi_log.log
logto2 = /home/user/dev/flask-thread/uwsgi2_log.log
env = PATH=/home/user/dev/flask-thread/env/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Run Code Online (Sandbox Code Playgroud)
然后我在 venv 中运行 uWSGI: uwsgi --ini uwsgi-test.ini
如果我使用python app.py并使用内置的 Flask 开发服务器,它将起作用。
我唯一的猜测是它与 GIL 与 uWSGI 交互有关,但这是一个疯狂的猜测,我不知道如何阻止它。
fiv*_*vef 10
对我来说,使用 uwsgi 标志--lazy有效。
uwsgi foo.ini --socket=0.0.0.0:5000 --protocol=http --lazy -w wsgi
Run Code Online (Sandbox Code Playgroud)
解释:
引自http://lists.unbit.it/pipermail/uwsgi/2011-June/002307.html:
单进程(无主):
该进程创建了 WSGI 可调用数据放入的线程。
还行吧
与主进程:
主加载应用程序并生成线程。然后它分叉一名或多名工人。这个worker是新进程,与master中产生的线程没有关系。所以你的数据将无处可去(只有主人可以访问初始线程)。
你有两种方法可以遵循:
1)在命令行中添加--lazy,这样你的应用程序将在master的fork后加载,所以每个worker都会得到它的线程。
2) 重写您的应用程序以使用 uwsgi.post_fork_hook 功能。