经过优化Gunicorn配置得到更好的性能

对于受CPU限制的应用程序,增长了工做程序和/或内核。对于受I / O限制的应用程序,请使用“伪线程”。

Gunicorn是Python WSGI HTTP Server,一般驻留在反向代理(例如Nginx)或负载平衡器(例如AWS ELB)和Web应用程序(例如Django或Flask)之间。

1 第一种并发方式(工做者,又名UNIX进程)

每一个工做程序都是一个加载Python应用程序的UNIX进程。工做人员之间没有共享内存。
建议的数量workers是(2*CPU)+1。
对于双核(2 CPU)计算机,建议workers值为5 。python

gunicorn --workers = 5 main:app

2 第二种并发方式(线程)

Gunicorn还容许每一个工人都有多个线程。在这种状况下,每一个工做程序会加载一次Python应用程序,而且同一工做程序产生的每一个线程都共享相同的内存空间。
要将线程用于Gunicorn,请使用threads设置。每次使用时threads,worker类都设置为gthread:nginx

gunicorn --workers = 5 --threads = 2 main:app

workers * threads在咱们的状况下,最大并发请求数为10。
使用辅助线程和线程时,建议的最大并发请求数仍为(2*CPU)+1。
所以,若是咱们使用的是四核(4 CPU)计算机,而且要使用工做程序和线程的混合,则可使用3个工做程序和3个线程,以获取9个最大并发请求。web

gunicorn --workers = 3 --threads = 3 main:app

3 第三种并发方式(“伪线程”)

有一些Python库(例如gevent和Asyncio)经过使用由协程实现的“伪线程”在Python中启用并发。
Gunicorn经过设置它们的相应工做程序类,容许使用这些异步Python库。
这里的设置适用于咱们要使用gevent如下命令运行的单核计算机:django

gunicorn --worker-class = gevent --worker-connections = 1000 --workers = 3 main:app

worker-connections是gevent worker类的特定设置。
(2CPU)+1仍然建议使用,workers由于咱们只有1个核心,咱们将使用3个工做线程。
在这种状况下,最大并发请求数为3000(3个工做程序
每一个工做程序1000个链接)编程

实际用例

经过调整Gunicorn设置,咱们但愿优化应用程序性能。
1 若是应用程序受I / O限制,则最佳性能一般来自使用“伪线程”(gevent或asyncio)。如咱们所见,Gunicorn经过设置适当的worker类并调整workersto 的值来支持这种编程范例(2*CPU)+1。flask

2 若是应用程序受CPU限制,则应用程序处理多少个并发请求都可有可无。惟一重要的是并行请求的数量。因为Python的GIL,线程和“伪线程”没法并行运行。实现并行性的惟一方法是增长到workers 建议的(2*CPU)+1,要理解的是,并行请求的最大数量是内核数。服务器

3 若是有一个关于应用程序的关注内存占用,使用threads 和其对应的g线程工人阶级有利于workers产生更好的性能,由于应用程序加载每一个工人和工人股运行一些内存每一个线程一次,这涉及到一些费用额外的CPU消耗。并发

4 若是您不知道本身在作什么,请从最简单的配置开始,该配置仅设置workers为(2*CPU)+1,无需担忧threads。从那时起,基准测试全都在反复试验。若是瓶颈是内存,请开始引入线程。若是瓶颈是I / O,请考虑使用其余python编程范例。若是瓶颈是CPU,请考虑使用更多的内核并调整其workers值。app

创建系统

软件开发人员一般认为,能够经过优化应用程序代码来解决每一个性能瓶颈,但并不是老是如此。有时候,调整HTTP服务器的设置,使用更多资源或从新设计应用程序以使用不一样的编程范例是咱们提升总体应用程序性能所需的解决方案。在这种状况下,构建系统意味着了解咱们可用于部署高性能应用程序的计算资源的类型(进程,线程和“伪线程”)。经过了解,设计和实施具备正确资源的正确技术解决方案,咱们避免陷入尝试经过优化应用程序代码来提升性能的陷阱。异步