从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比例,从咱们设置好的那一瞬间,永远趴在了地上!