我的碎碎念

不为繁华易匠心,不舍初心得始终。

0%

使用gunicorn部署应用,选择哪一种worker_class模式好?

最近使用gunicorn部署python web应用,发现了一些异常。比如无法同时多个大模型聊天等等。现在重新学习gunicorn的工作模式。

根据gunicorn的官方文档,有以下几种工作模式:

sync

sync:这是默认的模式。优点是最简单,缺点是每个 worker 进程一次只能处理一个请求,并发性能较低。我一开始就是使用这个模式部署,并且设置了worker=1,所以无法同时多个大模型聊天。

gthread

gthread:优先推荐的模式。优点是适用于 I/O 密集型应用,内存占用相对较低,支持多线程处理请求,可以利用多核 CPU 的优势。缺点是会受GIL限制。这个模式基本适用django和flask应用了。

下面以一个启动示例来讲解:

1
gunicorn --worker-class gthread --workers 3 --threads 2 myproject.wsgi:application

这个配置启动 3 个 worker 进程,每个 worker 进程有 2 个线程,这样总共可以处理 6 个并发请求。

部署后,可以根据需要监控gunicorn的性能指标,比如CPU和内存,并根据实际情况调整 worker class 和相关参数。

gevent/eventlet

gevent/eventlet:这是非常适合高并发的模式,能够处理大量并发连接,性能优于 gthread。但是缺点是需要修改代码,以确保与 gevent/eventlet 兼容,配置复杂,并且可能会出现 monkey-patching 相关的问题。

我在部署一个有后台长时间运行的线程的时候,需要设置gunicorn的preload的配置,提前加载app来启动后台线程,但是部署的时候,就出现了monkey-patching。查了github的issue,这个问题至今也没解决,参见:https://github.com/benoitc/gunicorn/issues/927

如何选择

那么如何选择?首先尝试使用 gthread,并根据服务器资源和应用负载调整 workersthreads 的数量。如果并发量非常高,并且 gthread 无法满足性能需求,可以考虑使用 geventeventlet,但需要注意代码兼容性问题。最后避免在生产环境中使用 sync,除非你的应用负载非常低。