关于在 Flask 端点内使用多处理(或多线程)的建议是什么?

var*_*ble 6 python multiprocessing flask

我知道应用程序服务器可以配置为:

  1. 根据请求启动新流程

  2. 每个请求启动新线程

这个问题是关于在 Flask 端点内使用 python 多处理(或多线程)代码。例如,假设我想使用 python 多处理来进行 CPU 密集型工作(或者使用多线程来进行 IO 密集型工作)。

我有一个 Flask 端点,需要 40 秒才能运行代码(CPU 密集型工作)。我在端点代码中使用了 python 多处理(池)[以便可以通过多个进程并行完成某些 CPU 密集型操作],现在端点需要 4 秒才能运行。

当上述 2 个应用程序服务器配置之一(即,当应用程序服务器配置为在新线程中服务每个请求或在新进程中服务每个新请求时),是否可以在端点内使用 python 多处理(或多线程)代码)。每个请求的线程是 Flask 开发服务器的默认设置。至于gunicorn我可以选择其中之一。在 Flask 端点内使用多处理(或多线程)时,我需要考虑什么,这样我就不会弄乱 Flask 进程/线程。

我知道更好的解决方案是使用任务队列。但这个问题具体涉及使用多线程/多处理。

Bha*_*007 8

在 Flask 中使用多处理/线程池来运行后台或长时间运行的任务是一种反模式。你不应该这样做。Flask 旨在服务 API 并执行 CRUD。

要解决您的问题,请考虑使用 API <> Worker 模式。

Flask app --- REDIS (or other MQ) --- Celery App
    |                                         |
    +---> SQL/Database <----------------------+
Run Code Online (Sandbox Code Playgroud)

Flask 将接收 API 请求并执行基本的 CRUD(基本上与数据库相关的任何操作),仅此而已。

对于任何长时间运行的操作,将操作提交到数据库中,并将句柄排队到 redis/or-any-message-queue 中。

celery 是作业管理框架,它从队列中获取这些作业并执行它们(这些作业可能会运行很长一段时间),并不断更新数据库的进度。

芹菜:https://docs.celeryproject.org/en/stable/getting-started/introduction.html


Dav*_*ith 3

简而言之,不要。人们很容易尝试协商某种方式来直接在请求处理程序中完成大量工作,但这种方法会带来痛苦。

请考虑允许请求处理程序(例如,Flask 路由)对要异步运行的任务进行排队的框架之一。处理程序对工作进行排队,并获取任务 ID,并以允许 UI 轮询任务完成情况的某种方式保存它。同时,Flask 外部的一个完全独立的进程会接收工作、执行工作,并通过框架(或单独通过共享数据存储)返回响应。

CeleryRq就是其中两个这样的框架。(Flask Mega 教程中有一个关于 Rq 的章节值得一读。)它们确实需要一些额外的设置。您至少需要一个共享Redis实例。

这种方法有几个好处:首先,它允许您的 Web 应用程序保持响应能力。如果您的 40 秒任务演变成 80、160 或几千秒的任务,您将不会占用 Flask 线程。其次,它可以保护 Flask 免受内存增长和碎片的影响;该任务在一个完全独立的进程中执行,该进程退出时将释放内存。

您在这些任务中所做的事情与 Flask 是隔离的。想要在一个任务中使用多个进程或线程池?美好的。干扰 Flask 的风险非常小*。(*如果您在与 Flask 相同的服务器上运行任务工作线程,则可能会耗尽内存)。