我有一个运行长期工作的Web服务(大约几个小时)。我正在使用Flask,Gunicorn和nginx进行开发。
我想做的是让路径花费很长时间才能完成,调用一个创建线程的函数。然后该函数将guid返回到路由,并且路由将返回用户可用于检查进度的URL(使用guid)。我正在使线程成为守护进程(thread.daemon = True),以便在我的调用代码退出(意外)时线程退出。
这是正确的使用方法吗?它有效,但这并不意味着它是正确的。
my_thread = threading.Thread(target=self._run_audit, args=())
my_thread.daemon = True
my_thread.start()
答案 0 :(得分:20)
Celery和RQ正在为简单任务进行过度设计。 看一下这个文档 - https://docs.python.org/3/library/concurrent.futures.html
另请参阅示例,如何在Flask app的后台运行长时间运行的作业 - https://stackoverflow.com/a/39008301/5569578
答案 1 :(得分:8)
处理此类问题的常规方法是使用像Celery这样的任务管理器系统从基本应用程序中提取操作并在外部调用它。
使用this教程,您可以创建任务并从Web应用程序中触发它。
from flask import Flask
app = Flask(__name__)
app.config.update(
CELERY_BROKER_URL='redis://localhost:6379',
CELERY_RESULT_BACKEND='redis://localhost:6379'
)
celery = make_celery(app)
@celery.task()
def add_together(a, b):
return a + b
然后你可以运行:
>>> result = add_together.delay(23, 42)
>>> result.wait()
65
请记住,您需要单独管理员工:
celery -A your_application worker
答案 2 :(得分:5)
好吧,虽然你的方法不正确,但基本上它可能会导致你的程序耗尽可用的线程。如Ali所述,一般方法是使用RQ
或Celery
等作业队列。但是,您不需要提取函数来使用这些库。对于Flask,我建议您使用Flask-RQ。起步很简单:
pip install flask-rq
请记住在使用Flask应用程序之前安装Redis。
只需在Flask函数中使用@Job Decorator:
from flask.ext.rq import job
@job
def process(i):
# Long stuff to process
process.delay(3)
最后你需要rqworker
来启动工作人员:
rqworker
您可以查看RQ docs了解详情。 RQ专为简单的长期运行流程而设计。
Celery更复杂,具有大量功能,如果您不熟悉作业队列和分布式处理方法,则不建议使用。
Greenlets有交换机。让您在长时间运行的进程之间切换。 您可以使用greenlet运行进程。好处是你不需要Redis和其他工作人员,而是你必须重新设计你的兼容功能:
from greenlet import greenlet
def test1():
print 12
gr2.switch()
print 34
def test2():
print 56
gr1.switch()
print 78
gr1 = greenlet(test1)
gr2 = greenlet(test2)
gr1.switch()
答案 3 :(得分:2)
你的方法很好,并且完全有效,但是为什么在广泛接受的解决方案(即芹菜)中重新发明python web应用程序的后台工作者。
在我信任任何家庭代码执行这么重要的任务之前,我需要看很多测试。
Plus芹菜为您提供了诸如任务持久性和在多台机器上分配工作人员的功能。