具体现象应用迁移到我们的PaaS平台后,会出现零星的502问题。报错见图片:相对于程序的请求量,报错肯定是比较少见的,但是报错时常发生,会影响到调用者的代码。您需要检查问题的原因。为什么只看到POST请求?读者肯定会说,你的ELKfilter字段包含POST,那肯定只有POST请求。事实上,情况并非如此。GET请求也会有502,但是Nginx会重试GET请求。生成类似如下的日志:重试机制是Nginx默认的:proxy_next_upstreamhttp://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream,因为GET方法会被认为是幂等的,所以当一个upstream出现502时,nginx会再试一次。对于我们的问题,主要是想确认为什么会有502,只看POST请求就可以了,两者的原因应该是一样的。网络拓扑当网络请求流入集群时,对于我们集群的结构:Userrequest=>Nginx=>Ingress=>uwsgi不要问为什么会有Ingress和Nginx。这是历史原因,一些工作暂时需要Nginx来承担。统计排查是根据我们对Nginx和Ingress的错误请求统计,发现两者中的502错误是预期等待,说明问题一定出现在Ingress<=>uwsgi。抓包并不是第一个想到的解决方案,因为我们用了很多统计方法,都未能总结出其中的规律。最后只能寄希望于抓包了。。。请求日志如下:抓包结果如下:从抓包的角度来看,当前的tcp连接被复用由于Ingress中使用的是HTTP1.1协议,它会尝试在tcp连接中发送第二次HTTP请求,但是uwsgi不支持http1.1,所以第二次请求根本不会被处理,直接拒绝.所以在Ingress看来,请求失败,所以返回502。由于GET请求会重试,而POST请求无法重试,所以访问统计中出现POST请求502的问题。Ingress配置学习Ingress,upstream默认使用的http版本是1.1,但是我们的uwsgi使用的是http-socket而不是http11-socket,而且我们的Ingress使用的是和后端不同的协议,出现了意想不到的502错误。https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#proxy-http-version因为Nginx默认是1.0,但是切换到Ingress默认是1.1,我们没有统一,解决方法是强制指定Ingress使用的http协议版本。{%ifkeepalive_enableissameastrue%}nginx.ingress.kubernetes.io/proxy-http-version:"1.1"{%else%}nginx.ingress.kubernetes.io/proxy-http-version:"1.0"{%endif%}如果有人看过,可以简单说说Ingress什么时候会重用http1.1连接,为什么Ingress不重用每一个连接,这样问题就会尽快暴露出来。我没有继续深究这些问题了。毕竟换个语言比如Golang,就不会出现这个问题了。这是一个uwsgi独有的错误。总结一下这个502问题的排查,我个人认为通过最后抓包一次性解决问题没有什么特别的。抓到就能发现问题,不抓到就找不到问题。给大家一个启发,如何排查一个整体的链接:我们这里同时使用了Nginx和Ingress,排查的时候需要先查看错误的个数,如果错误基本一致,说明错误与Nginx无关,需要在Ingress上查看错误。对于多个中转请求,这种排查可以快速确定链接的错误位置。
