我们是如何解决偶发性的 502 错误的

总结:浏览器Nginx的keepalive时间需要等于Nginx应用服务器keepalive的时间

从ingress的监控中心,我们看到,失败率虽然不高,但始终保持在0.05到0.1的水平:

我们用这样的条件去查询,发现绝大部分错误是502错误:

 
status>=500 | select status, count(*) a group by status order by a desc

那么502错误到底是个什么错误呢?百度百科给出的解释是:

502 Bad Gateway是指错误网关,无效网关;在互联网中表示一种网络错误。表现在WEB浏览器中给出的页面反馈。它通常并不意味着上游服务器已关闭(无响应网关/代理) ,而是上游服务器和网关/代理使用不一致的协议交换数据。鉴于互联网协议是相当清楚的,它往往意味着一个或两个机器已不正确或不完全编程。

还有人说是超时导致的:

马上在评论区有人反驳:

百度百科对504错误的解释:

504错误代表网关超时(Gateway timeout),是指服务器作为网关或代理,但是没有及时从上游服务器收到请求。服务器(不一定是Web 服务器)正在作为一个网关或代理来完成客户(如您的浏览器或我们的CheckUpDown 机器人)访问所需网址的请求。

显然,504错误才是超时,而502并不是。

而且从我们对502错误日志的进一步分析来看,发生502错误时的请求时间和响应时间都极短,不可能是超时。

查502与504的区别,只有这个说法相对靠谱:

也就是说我们后端的服务是能够响应的,但响应不符合要求,所以出现了502错误。但这种错误并不是必然的,如果是必然出现,则网站整体不可用,早就被发现了,正因为它是偶发的,所以有必要看一下在发生502的时候到底发生了什么。

为此我们把nginx的logtail日志的stderr输出打开:

此前这里本来是false,现在我们把它改成true,使它能够将错误日志输出出来,便于我们查找原因。

stderr错误输出之后,立刻就能在日志里看到大量的这种错误:

 

2022/04/02 16:59:55 [error] 11168#11168: *739601507 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 49.93.83.68, server: www.domain.com, request: "POST /myserver/service HTTP/1.1", upstream: "http://192.108.1.121:8080/myserver/service", host: "www.domain.com"

从字面意思来理解,是说上游服务器直接关闭了连接。但是上游服务器为什么要关闭连接呢?将错误信息放入搜索引擎进一步排查,很多文章将我们的思路导向了keepalive这个方向,最应该检查的是keepalive_timeout和keepalive_request这两个属性。

什么是keepalive?这是http 1.1协议的缺省配置,在http 1.0的时候,如果你的网页上有10个图片,那么浏览器和服务器之间要同时建立10个连接,把这10个图片发过去然后再关闭这10个连接,显然对于服务器来说,建立10个连接再关闭10个连接,消耗是比较大的。所以在http 1.1协议里增加了keepalive的功能,在发10张图片的时候只需要建立一个连接就够了,只要还有内容要传输,这个通道会始终保持开放状态,不会在传输完毕之后立刻关闭,这就是keepalive保活的意思。

但是keepalive不能把这个连接永远保持,如果没有内容了还继续保持,无疑也是一种浪费,所以这里就产生了超时的概念,keepalive_timeout的意思是说如果这个连接当中没有内容传输了并且超过了这个时间,那么就把这个连接断掉,keepalive_requests的意思是说我们这个连接最多允许传输多少个内容,超过这个内容那么也把它断掉。

那么这个keepalive_timout和我们的502错误之间有什么关系呢?因为所有网站的架构都不是浏览器直接连接后端的应用服务器,而一定是中间有nginx服务器做反向代理的,浏览器和nginx服务器之间建立keepalive连接,nginx再和后端的应用服务器建立keepalive连接,所以这是两种不同的keepalive连接。我们把浏览器和nginx之间的keepalive连接叫做ka1,把nginx和应用服务器之间的keepalive连接叫做ka2。

如果ka1的超时设置为100秒,也就是说如果100秒之内没有新内容要传输,就把nginx和浏览器之间的连接断掉。而同时,我们把ka2设置为50秒,也就是说如果nginx和应用服务器之间没有新内容要传输,那么就把应用服务器和nginx之间的连接断掉。那么这时候就会产生一个问题:前50秒没有传输内容,在第51秒的时候,浏览器向nginx发了一个请求,这时候ka1还没有断掉,因为没有到100秒的时间,所以这是没有问题的,但是当nginx试图向应用服务器发请求的时候就出问题了,ka2断了!因为ka2的超时设置是50秒,这时候已经超了,所以就断了,这时候nginx无法再从应用服务器获得正确响应,只好返回浏览器502错误!

但是我们根本就没有设置过这些参数啊,怎么会有这种问题呢?

这没关系,既然没有设置过,那系统肯定用的是缺省参数,我们来看一下ka1的缺省设置是多少,也就是nginx(ingress)和浏览器之间的缺省的keepalive_timeout值:

upstream-keepalive-timeout

Sets a timeout during which an idle keepalive connection to an upstream server will stay open. default: 60

ka1的缺省设置是60秒。

我们再看一下ka2的缺省设置是多少秒,Tomcat官方文档上说:

The number of milliseconds this Connector will wait for another HTTP request before closing the connection. The default value is to use the value that has been set for the connectionTimeout attribute. Use a value of -1 to indicate no (i.e. infinite) timeout.

缺省值等同于connectionTimeout的值,那connectionTimeout等于多少呢?

The number of milliseconds this Connector will wait, after accepting a connection, for the request URI line to be presented. Use a value of -1 to indicate no (i.e. infinite) timeout. The default value is 60000 (i.e. 60 seconds) but note that the standard server.xml that ships with Tomcat sets this to 20000 (i.e. 20 seconds). Unless disableUploadTimeout is set to false, this timeout will also be used when reading the request body (if any).

connectionTimeout的缺省值是60秒,但是,他们提供的标准的server.xml里把这个值设为了20秒!

那么现在问题就很清楚了,我们的ka1是60秒,而ka2是20秒,从21秒到60秒之间的任何时间有请求进来都会发生502错误。

找到了问题的根源,解决起来就好办了,我们只需要确保ka1的超时设置小于ka2的设置就够了。或者修改ka1,或者修改ka2,都是可以的。

我们先修改ka1看一下,对于ingress来说,要修改ka1需要在ingress的configMap中修改,所以我们找到configMap设置的地方,给它增加一个新的属性:

这里我们把upstream-keepalive-timeout设为4,确保它低于ka2的20,设置完之后,ingress会自动加载新设置,我们看一下结果:

原先不断产生的502错误彻底消失了!

再来看一下错误图:

注意那个黄颜色的5XX比例,从我们设置好的那一瞬间,永远趴在了地上!

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好!对于Spring Security的偶发性登录失败问题,我可以给出一些可能的解决方案: 1. 检查用户名和密码:首先要确保用户输入的用户名和密码是正确的,包括大小写和特殊字符。可以尝试使用正确的凭据进行登录,以确定是否是输入错误导致的登录失败。 2. 检查数据库连接:如果您在登录时使用了数据库验证用户凭据,那么请确保数据库连接正常,并且用户表中存在正确的用户名和密码信息。可以尝试连接数据库并查询用户表,以验证数据库连接是否正常。 3. 检查Spring Security配置:检查您的Spring Security配置文件,确保已正确配置身份验证和授权规则。可能存在一些配置错误导致偶发性登录失败。可以参考Spring Security的官方文档或者其他资源,检查您的配置是否符合要求。 4. 检查错误日志:查看应用程序的错误日志,以了解登录失败的具体原因。错误日志通常会提供有关登录失败的详细信息,如错误类型或异常堆栈跟踪。根据错误日志中提供的信息,可以更容易地定位和解决问题。 5. 检查网络连接和服务器状态:偶发性登录失败可能与网络连接或服务器状态有关。请确保网络连接稳定,并且服务器正常运行。如果在高负载或网络不稳定的情况下出现登录失败,可以尝试增加服务器资源或者优化网络环境。 这些是一些常见的解决方案,希望能对您有所帮助。如果问题仍然存在,请提供更多详细信息,以便我能够更好地帮助您解决问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值