最近使用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
,并根据服务器资源和应用负载调整 workers
和 threads
的数量。如果并发量非常高,并且 gthread
无法满足性能需求,可以考虑使用 gevent
或 eventlet
,但需要注意代码兼容性问题。最后避免在生产环境中使用 sync
,除非你的应用负载非常低。