Nginx反向代理Django收到`上游提前关闭连接,同时读取上游响应头` [英] Nginx reverse proxying to Django receiving `upstream prematurely closed connection while reading response header from upstream`

查看:0
本文介绍了Nginx反向代理Django收到`上游提前关闭连接,同时读取上游响应头`的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

TL;DR

当Nginx尝试通过HTTP反向代理到本地Django实例(没有WSGI中间件)时,会发生什么http/tcp现象?

长版本

冒着激怒社区的风险,我不会包括任何配置,尽管我确定它是相关的,但我正在努力理解这种现象背后的理论。

我和一些队友维护了一台供内部使用的Web服务器。在我们内部工具的世界里,东西从来都不是产品化的。我们通常会做任何必要的事情,为我们的同事带来一些价值。风险和可用资源很低。

因此,我们犯了一个最大的错误,那就是独立建立了一台Python2 Django服务器。没有WSGI中间件,没有额外的进程。我看到了警告,但我们已经做了我们所做的。

我最近在这个令人讨厌的问题面前放置了一个Nginx实例,以便让我们能够在零宕机的情况下"热插拔"我们的Web应用程序的实例。我仍然没有在中间插入任何东西。Nginx只是反向代理,通过本地主机http到Django实例监听本地主机非标准端口。

在此更改后,我们开始看到来自Nginx的502脉冲。有几个页面是"实时的",因为他们会进行一些轮询来检查事物的更新。因此,对于我们拥有的用户数量来说,流量"很大"。

我实际上认为,在引入Nginx之前,无论问题是什么,都已经存在了,但由于浏览器直接获得了错误,所以它只是重试了一次,用户看不到这个问题,而现在他们得到了一个难看的502错误消息。

现在回答问题: 如果我在Nginx error.logupstream prematurely closed connection while reading response header from upstream中看到这实际上是什么意思?我在这个网站上看到了很多关于更改配置的建议的帖子,似乎没有一个适用于我,但我正在寻找的是理论。

该错误意味着什么? 当Nginx试图代理Django的请求时,它到底经历了什么? 姜戈是在拒绝联系吗? Django是否在连接完成之前关闭连接?

如果姜戈做了这些事情,为什么?是否内存不足、线程数、有什么原因限制线程数等?

作为周末临时修补程序的盲目尝试,我启动了应用程序的第二个实例,并将Nginx配置为对它们进行循环负载平衡。它似乎奏效了,但我要到周一早上高峰接踵而至的时候才能确定。

第二个实例位于同一计算机上,因此不可能有任何额外的系统资源。是不是某个Python解释器实例中的某些资源即将耗尽,因此创建第二个实例会使我的容量"两倍"?

我真的想在这里学到一些有价值的东西,而不是"投入更多的资源!"

如有任何帮助,我们将不胜感激。提前谢谢!

更新

Philipp,非常感谢您的详尽回答!一个快速问题可以加深我的理解...

如果我的上游Python服务器"不能并行处理足够多的请求并阻塞",这可能是什么原因。这是一个单一的过程,所以我认为这在某种程度上简化了问题。什么资源会耗尽?难道服务器不可能只是以其所能适应的速度读取套接字吗?什么样的系统/服务器配置决定了它一次可以处理的动态请求的数量?我仔细查看了一番,找不到任何会人为限制其响应性的显式Django(Python服务器库)配置选项。我当然可以支持额外的资源,但如果这更多的是系统限制,那么我不会期望同一机器上的另一个实例能做任何事情(这是我现在预计的,因为第二个实例在周末开始产生相同的问题)。我想在这里一劳永逸地做出一个经过深思熟虑的决定。

再次感谢您(或其他任何人)的帮助!

更新%2

我周一早上一到办公室,一位精通Linux内核的同事就向我描述了根本问题是监听队列深度。

正是这种构造在其容量上受到限制。当进程侦听端口并且新的连接尝试传入(在建立连接之前)时,如果进程建立连接的速度慢于它们的传入速度,则侦听队列就是所建立的连接。

因此,这与内存或CPU无关(除非这些资源不足是连接建立缓慢的原因),而是对进程连接容量的限制。

我绝对不是这方面的专家,但我就是想知道为什么给定进程突然决定(或操作系统决定)它将不再接受任何连接的原因就是这个结构。

可以阅读更多内容here

再次感谢Philipp带领我走上正确的道路!

推荐答案

从上游读取响应头时,上游过早关闭连接

该错误肯定是在上游,也就是说,在您的情况下,是与您的Python服务器的连接。502表示从Nginx到其上游服务器之一的TCP连接已关闭(从python进程主动关闭,或在超时时由系统关闭)。

从您所描述的情况来看,可能是因为Python服务器无法并行处理足够多的请求和块。只要你前面没有nginx,你就不会注意到,也许只会注意到请求很慢。有了Nginx,它就发生了变化,因为Nginx可以轻松地处理大量请求,并可能接受比其上游服务器(即,您的Python服务器)跟得上的更多的请求。在这种情况下,上游服务器没有响应,最终套接字关闭,这迫使Nginx失败,并返回502(Bad Gateway)。

为了测试这一理论,我们比较了向Nginx或直接向Python服务器发出多个请求时所发生的情况。当您直接转到Python服务器时,IT请求会被阻止并得到较慢的处理(但没有错误),但当您转到Nginx时,所有请求都会立即被接受(但有些会失败,出现502),这可能就是我描述的情况。

在这种情况下,您可以尝试以下操作:

  • 确保Keep-Alive能在Nginx上运行(这无论如何都是个好主意,应该限制上游的并行请求数)。详情请参见this answer
  • (如果可能)更改Python服务器,以便它们可以处理更多并行请求
  • 确保服务器上的文件句柄未用完,并监视系统上的TPC套接字数量(例如,使用sudo netstat -tulpan)。

我可能是错的,因为我在答案中进行了很多猜测。不过,我希望它能为您提供一些思路,帮助您解决请求关闭(或超时)的问题。

这篇关于Nginx反向代理Django收到`上游提前关闭连接,同时读取上游响应头`的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆