Nginx + uWSGI + Flask 连接重置

Nginx + uWSGI + Flask 连接重置

问题

我使用 Elastic Beanstalk 的“单容器 Docker”平台(撰写本文时最新版本为 3.2.5)部署了一个 Flask 应用程序,并在其前面部署了一个“应用程序负载均衡器”。我在 EB 中使用“Python 3.6”平台(和“经典负载均衡器”)部署了这个相同的 Flask 应用程序很长时间,但在升级到新部署后开始出现问题。在配置 Nginx / uWSGI 方面,我是一个相对新手,请耐心等待...

具体问题

error.log我的环境处理的请求中约有 0.01% 出现在 Nginx 文件中,出现了以下错误:

<timestamp> [error] 22400#0: *52192 upstream prematurely closed connection while reading response header from upstream, client: <ip>, server: , request: "POST <endpoint> HTTP/1.1", upstream: "http://<ip>:5000/<endpoint>", host: "<my hostname>"
...
<timestamp> [error] 22400#0: *101979 readv() failed (104: Connection reset by peer) while reading upstream, client: <ip>, server: , request: "POST <endpoint> HTTP/1.1", upstream: "http://<ip>:5000/<endpoint>", host: "<my hostname>"

我在对不同端点的请求中、使用不同的 HTTP 方法(GETPOST)以及看似随机的时间看到了这些错误。此外,我在 Flask 应用程序日志中没有看到任何应用程序错误,这表明这不是应用程序问题,而是配置问题。

讨论

我最终阅读并尝试了很多东西,所以我将为后人讲述我的经历。我得出的答案似乎很简单,以至于我仍然怀疑我是否正确。

从我读过的资料来看,这听起来像是一个相当简单的问题,Nginx + uWSGI 之间的一些错误配置超时。读完这篇文章后,我受到了鼓舞邮政它几乎描述了我使用 Elastic Beanstalk 的具体情况。

第 1 部分:半随机挥动

在关于这个问题的众多不同答案中邮政我发现了一些可以尝试的事情:

  1. 我尝试设置 uWSGI 参数,post-buffering = 32768因为人们建议这样做。但这没有帮助,这是有道理的,因为该设置仅适用于带有 的请求,而且我也Body一直在请求中观察到上述错误。GET
  2. 我尝试使用 Nginx 的keepalive+keepalive_timeout和 uWSGI 的so-keepalivehttp-timeout、 和socket-timeout

通过阅读文档我意识到这些 uWSGI 设置肯定不会有帮助,尽管我对此抱有希望so-keepalive

此时,我确实注意到这些错误的频率相对明显下降,但它们并没有完全消失。像一个糟糕的工程师一样,我在一些试验中同时更改了多个变量。因此,很难确切知道是什么起了作用。我怀疑我通过将 Nginx 设置keepalive为连接数 <= 我看到的它在 uWSGI 日志中可以处理的最大连接数(100 个连接)来使情况变得更好。欢迎其他人对此发表见解,尽管没有太多可继续的内容……

第 2 部分:我认为,已经修复……

我决定尝试覆盖upstreamElastic Beanstalk 放入 Nginx 配置中的默认定义。原始定义如下所示:

upstream docker {
    server <some ip>:5000;
    keepalive 256;
}

我所做的只是用我自己的上游替换它,将 Nginx 更改location为指向我的自定义upstream(如下),并且根本不设置参数keepalive。就像这样:

upstream myapp {
    server <some ip>:5000;
}
...
location / {
    # proxy_pass http://docker;
    proxy_pass http://myapp;
}

这似乎有效……自从做出更改以来,我基本上没有5xx在我的 Elastic Beanstalk 环境中看到任何错误。事实上,这种方法有效,这一点似乎也得到了以下事实的证实回答其中提到:

... uwsgi 连接不可重复使用,因此它会被关闭,并且每次请求时都会打开一个新连接;在正常运行中,它不会长时间保持空闲状态。

我不确定这在哪有记载,但在阅读有关使用 uWSGI + Nginx 的文章时我没有注意到它。如果这是准确的,那肯定解释了很多。

结论/帮助?

我真的很高兴我能够解决这个问题,而且 API 似乎运行得很好,但我无法摆脱这种感觉:我不明白为什么它会起作用,或者我在这种配置上犯了一些严重的错误。

在 Elastic Beanstalk 中覆盖这些内容感觉有点麻烦,这让我觉得我不应该这么做。随着 uWSGI 在 Python Web 应用程序上的流行,我的直觉告诉我,应该已经有很多关于这个 Nginxkeepalive运行不佳的帖子了uWSGI。尤其是因为这是这个 Elastic Beanstalk 平台的默认配置。

如果您已经读到这里并且了解了一些情况,请随意发表意见。希望至少下一个在 Nginx 日志中看到这些错误的人能有另一个数据点来判断问题可能是什么。

相关内容