gpt4 book ai didi

django - 在 nginx/gunicorn/django Web 架构中有效处理长时间运行的 HTTP 连接

转载 作者:行者123 更新时间:2023-12-03 13:52:44 25 4
gpt4 key购买 nike

我正在开发基于 nginx 实现的 Web 服务+ gunicorn + django .客户端是智能手机应用程序。应用程序需要对外部 API(Facebook、Amazon S3...)进行一些长时间运行的调用,因此服务器只需将作业排队到作业服务器(使用 Celery 而不是 Redis )。

只要有可能,一旦服务器将作业排队,它就会立即返回,并关闭 HTTP 连接。这工作正常,并允许服务器维持非常高的负载。

client                   server                 job server
. | |
. | |
|------HTTP request----->| |
| |--------queue job------>|
|<--------close----------| |
. | |
. | |

但在某些情况下,客户需要在作业完成后立即获得结果。不幸的是,一旦 HTTP 连接关闭,服务器就无法联系客户端。一种解决方案是依靠客户端应用程序每隔几秒钟轮询一次服务器,直到作业完成。如果可能的话,我想避免这种解决方案,主要是因为它会阻碍服务的 react 性,并且还因为它会给服务器加载许多不必要的轮询请求。

简而言之,我想保持 HTTP 连接正常运行,什么都不做(除了可能每隔一段时间发送一个空格以保持 TCP 连接处于事件状态,只是 like Amazon S3 does ),直到工作完成,服务器返回结果。
client                   server                 job server
. | |
. | |
|------HTTP request----->| |
| |--------queue job------>|
|<------keep-alive-------| |
| [...] | |
|<------keep-alive-------| |
| |<--------result---------|
|<----result + close-----| |
. | |
. | |

假设服务器处于非常高的负载下,我如何以有效的方式实现长时间运行的 HTTP 连接(目前还不是这样,但目标是能够维持尽可能高的负载,每秒有数百或数千个请求)?

将实际作业卸载到其他服务器应该确保服务器上的 CPU 使用率较低,但是如何避免进程堆积并使用服务器的所有 RAM,或者由于打开的连接过多而丢弃传入请求?

这可能主要是正确配置 nginx 和 gunicorn 的问题。我读过一些关于 async workers based on greenlets in gunicorn :文档说“应用程序进行长时间阻塞调用(即外部 Web 服务)”使用异步 worker ,这听起来很完美。它还说“一般来说,应用程序应该能够使用这些工作类而无需更改”。这听起来很棒。对此有何反馈?

感谢您的建议。

最佳答案

我是 answering my own question ,也许有人有更好的解决方案。

阅读 gunicorn's documentation更进一步,阅读更多关于 eventlet 的内容和 gevent ,我认为gunicorn完美地回答了我的问题。 Gunicorn 有一个管理 worker 池的主进程。每个工作人员可以是同步的(单线程,一次处理一个请求)或异步的(每个工作人员实际上几乎同时处理多个请求)。

同步 worker 很容易理解和调试,如果 worker 失败,只会丢失一个请求。但是如果一个工作人员被困在一个长时间运行的外部 API 调用中,它基本上是在 sleep 。因此,在高负载的情况下,所有工作人员可能最终会在等待结果时进入休眠状态,并且请求最终会被丢弃。

所以解决办法就是把默认的worker类型从同步改为异步(选择eventlet或者gevent,here's a comparison)。现在每个 worker 运行多个 green threads ,每一个都非常轻巧。每当一个线程必须等待某个 I/O 时,另一个绿色线程就会恢复执行。这称为 cooperative multitasking .它非常快,非常轻量级(如果他们正在等待 I/O,单个工作人员可以处理数千个并发请求)。正是我需要的。

我想知道如何更改现有代码,但显然标准 python 模块是 monkey-patched通过 gunicorn 在启动时(实际上是通过 eventlet 或 gevent),因此所有现有代码都可以在不更改的情况下运行,并且仍然可以与其他线程很好地运行。

gunicorn 中有很多参数可以调整,例如使用 gunicorn 的 worker_connections 的最大同时客户端数参数,使用 backlog 的最大挂起连接数参数等

太好了,我马上开始测试!

关于django - 在 nginx/gunicorn/django Web 架构中有效处理长时间运行的 HTTP 连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11883214/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com