从上游读取响应头时,Nginx uwsgi (104: Connection reset by peer)。

56

环境为Nginx + uwsgi。

在某些GET请求中,从Nginx获取502 bad gateway错误。似乎与URL的长度有关。在我们特定的情况下,它是一长串GET参数。缩短GET参数后,没有502错误。

从nginx/error.log中获取更多信息。

[error] 22113#0: *1 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 192.168.1.100, server: server.domain.com, request: "GET <long_url_here>"

uwsgi错误日志中没有任何信息。


4
你可能需要在uwsgi中增加请求的最大大小:https://dev59.com/ZWjWa4cB1Zd3GeqPtsT2 - Sohan Jain
8个回答

111

在花费大量时间之后,我终于找到了答案。关于Nginx和“connection reset by peer”的问题有许多参考资料,但大部分似乎与PHP有关。我无法找到一个特定于Nginx和uwsgi的答案。

最终,我在一个关于fastcgi和502坏网关错误的参考资料中找到了线索(https://support.plesk.com/hc/en-us/articles/213903705)。这使我开始寻找uwsgi配置文件中的缓冲区大小限制,其存在于buffer-size中。默认值为4096。根据文档上的说明:

如果您计划接收具有大量标头的大型请求,则可以将此值增加到64k(65535)。

有许多配置uwsgi的方法,我碰巧使用了.ini文件。所以在我的.ini文件中,我尝试使用:

buffer-size=65535

这解决了问题。您可以根据自己的口味进行调整。也许从最大值开始逐渐减小,直到找到可接受的值,或者只保留最大值。

这很令人沮丧,因为在uwsgi方面没有错误。


由于错误指出了从上游读取响应头,那么它不应该是关于上游HTTP响应头字节大小的问题,而不是HTTP请求头字节大小的问题吗? - CMCDragonkai
这涉及到很多头文件或者文档中的http://uwsgi-docs.readthedocs.org/en/latest/Options.html#buffer-size,还有大量的查询字符串。 - srt32
1
在我的情况下,工作参数是 output_buffering = 65535 在php.ini中,正如你所提到的,祝愉快! - Kiko Seijo
1
它真的起作用了,我将其放在/etc/uwsgi/sites/xxx.ini中,并重新启动了uwsgi服务,在django和python的情况下,感谢您的贡献。 - Alex Hurtado
1
我没有找到名为uwsgi的文件夹或uwsgi.ini的文件。我应该在哪里进行这个配置? - Malay M
显示剩余3条评论

5
我遇到了相同的nginx错误,但是uwsgi日志中没有任何信息。问题在于,在某些情况下,应用程序没有像http://uwsgi-docs.readthedocs.org/en/latest/ThingsToKnow.html所建议的那样完全使用请求正文:

如果HTTP请求具有正文(例如由表单生成的POST请求),则必须在应用程序中读取(消耗)它。如果您不这样做,则与Web服务器的通信套接字可能会被破坏。如果您很懒,可以使用后缓冲选项,该选项将自动为您读取数据。对于Rack应用程序,此选项已自动启用。

当然,这在你的情况下不是问题,但对于其他遇到相同nginx错误的人可能会有用。

4
我们只需要在php.ini中将"output_buffering"属性的值增加到65535或其他适当的值即可。

我猜这应该是对其他答案的评论? - mastov
1
我已经寻找了许多天来解决这个问题,因为我在我的服务器上一整天都会间歇性地看到它,而这个方法对我有用。在我的情况下,我将默认值4096加倍至8192。谢谢! - Alan

1

当我们收到像 (104: Connection reset by peer) while reading response header from upstream 这样的消息时,通常情况下,我们可以指责上游出现了这种错误。

如描述所述,连接是由上游对等方重置的,而不是由nginx本身重置。作为客户端,nginx几乎无法采取任何措施来解决问题。

我怀疑修改缓冲区大小是否会产生神奇效果。基本上,该命令更改响应标头缓存的缓冲区大小。当响应标头太大时(我们收到一条消息,其中包含“upstream sent too big header while reading response header from upstream”),这将生效,并且这与“connection reset by peer”完全不同。

由于这种类型的错误是随机触发的,因此建议您检查nginx在与上游通信时是否使用了 keepalive 。如果是这种情况,当空闲超时时,上游服务器可能会重置连接,而nginx并不知道连接已经断开,从而使用相同的连接转发请求。

据我所知,没有优雅的解决方案。您可以重试或在nginx中为上游连接池设置 keepalive_timeout 值,以避免这个问题。

参考资料:

Apache HttpClient 临时错误:NoHttpResponseException

http://tengine.taobao.org/document/http_upstream_keepalive_timeout.html


0

--post-buffering 32768 对我来说起到了作用,就像这里NGINX + uWSGI Connection Reset by Peer所建议的(并且不被鼓励)。

目前我没有时间进一步调查它(快速原型模式:),但由于我花了很多时间找到这个技巧,所以在这里发布可能是值得的。


0

如果您的请求/响应头非常大,可能会发生这种情况。

要解决此问题,在/etc/uwsgi/apps-available/your-app.ini中添加buffer-size=65535


-1

它偶尔不会出现。

我猜最可能的原因是您的php-fpm.log文件太大了。尝试在php-fpm.conf中将log_level更改为更高的级别,并清除日志。

总之,对于我来说,它有效。


-12

您需要重新安装PHP:

apt-get install --reinstall php5-fpm

重新安装 PHP 应该如何解决这个问题? - chifliiiii
我认为这个答案与@eduan-lenine的答案有关。不会影响任何东西。此外,apt-get install --only-upgrade php5-fpm 给我的输出是 php5-fpm is already the newest version. - sampoh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接