请教下各位 Gunicorn 启动时 Python 进程池

2022-08-31 18:13:48 +08:00
 cyberpoint

大佬们问下 Python 多进程的问题

功能概述

发送一个请求 /task/create 开启了一个长耗时计算密集型任务。在这个任务运行的过程中,可以发送另一个请求 /task/close 来关闭这个任务。

需求

  1. 需要可以主动关闭这个任务
  2. 优化长耗时任务

目前的状况

用 flask 建立了一个项目,通过 Gunicorn + Gevent 在 centos7 上部署了服务(尚未通过 Nginx 走代理)。

问题

为了解决以上两个需求,我想通过多进程来实现,但是没有具体的实现方式。

  1. 需要有一个能实现的最简示例。
  2. 如果通过 Nginx 代理,Gunicorn 的 -w 参数还需要设置 cpu *2 +1 的数量吗

其他补充

用 Gunicorn 启动服务后,在 flask 的 路由函数里面开启了多进程(通过 ProcessPoolExecutor),控制台会提示有些进程被忽略掉,而且有些进程没有运行,好像有些进程也被阻塞了。
然后看到 multiprocessing.Pool 可以直接 terminate 终止进程池,但是有个限制

注意 start() 、join() 、is_alive() 、terminate() 和 exitcode 方法只能由创建进程对象的进程调用。

2748 次点击
所在节点    Python
18 条回复
cyberpoint
2022-08-31 18:19:46 +08:00
对咯,这个服务用的 时候,不会用太多用户,一般就 三四人用户同时在用。
Kobayashi
2022-08-31 18:38:57 +08:00
为什么不用 rq 或者 celery ?
Kobayashi
2022-08-31 18:43:01 +08:00
实现不了。
cyberpoint
2022-08-31 19:04:52 +08:00
@Kobayashi 感谢,我也是刚刚接触 Python ,处于边学边用的状态。我去看看你说的 rq 和 celery 话说推荐用其中哪个呢。
svtter
2022-08-31 19:45:57 +08:00
长耗时任务,应该用异步跑。
cyberpoint
2022-08-31 20:07:53 +08:00
@svtter 是指 asyncio 吗。 这个应该不适合我这里。我这个 是计算密集型
LindsayZhou
2022-08-31 20:23:08 +08:00
@cyberpoint #6
asyncio 可以用多线程跑: https://docs.python.org/3/library/asyncio-task.html#running-in-threads

然后还有个 Task 类可以用来管理 Coroutines 的生命周期: https://docs.python.org/3/library/asyncio-task.html#task-object

我只是看到过,没用过,只能帮你把文档找出来
ch2
2022-08-31 20:23:41 +08:00
这种需求,应该用消息队列来做,多进程做起来耦合挺严重的
huangzhiyia
2022-08-31 20:26:36 +08:00
用 celery +redis 吧,符合你所有需求。
raycool
2022-08-31 20:30:40 +08:00
这种可以使用 tornado + redis + concurrent.futures.ProcessPoolExecutor 来做
elboble
2022-08-31 20:53:48 +08:00
Celery 吧,应该比较合适
LindsayZhou
2022-08-31 20:58:00 +08:00
svtter
2022-08-31 21:20:40 +08:00
1. 异步任务是那些被引擎放在一边,不进入主线程、而进入任务队列的任务。
2. 任务队列可以用 celery + redis 来做。
3. WEB 应用系统是负责接收前端请求,并进行简单处理的软件系统。
4. 计算型的程序逻辑,应根据对算力的要求,另外开启进程或者采用另外的服务器来做。
svtter
2022-08-31 21:23:02 +08:00
5. 使用 celery 的话,celery worker 就是`另外的进程`
6. celery worker 如果不在本机,就是`另外的服务器`
lambdaq
2022-08-31 21:25:03 +08:00
就问一个简单问题,如果 2 个机器跑你这个 web 服务

A 机器执行了 /task/create 开始多进程

B 机器接到了 /task/close 怎么办?
imycc
2022-08-31 21:33:07 +08:00
gunicorn 只负责做接收 web 请求,计算任务通过 celery 的 worker 去执行,去看看 celery 的官网教程就好。中间消息传递的部分,需要用消息队列或者 redis ( mysql 其实也行)

至于停止任务,可以用 celery 的[revoke 方法]( https://docs.celeryq.dev/en/stable/userguide/workers.html#revoke-revoking-tasks) 创建任务之后会得到一个 task_id ,存起来或者返回给前端。然后用这个 task_id 取消掉任务就行。

但杀掉正在运行的进程,只对 prefork 和 eventlet 类型的 worker 有效,因为线程和协程没法单独杀掉。如果你用线程 /协程创建的 worker ,需要引入额外的机制,让他们每隔一段时间就检查外部的标志位,判断是否要继续运行。
ospider
2022-08-31 22:30:29 +08:00
千万别用 celery ,bug 一大堆,坑你没商量。自己拿 redis 封装个消息队列很简单的,别想太复杂。
subjadeites
2022-09-03 12:01:11 +08:00
土一点甚至可以把计算部分单独封一个入口,然后调命令启动获取 pid ,在 redis 里存 task 标识符和 pid ,收到 close 直接 kill(

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/876794

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX