
睡梦中手机震个不停迷迷糊糊摸过来一看好家伙告警群里已经炸了核心业务接口大面积502客服那边电话快被打爆了。我盯着天花板愣了两秒然后爬起来开电脑远程连上跳板机那一刻说实话手都是抖的。这种场景做运维的应该都不陌生吧大晚上被叫起来脑子还没转过弯来屏幕上全是红色告警脑子里只有一个念头这锅今天是不是得我来背后来那次故障复盘会上领导问我一个问题502到底是怎么来的你下次能不能10分钟之内定位清楚我当时没敢接话。但事后我花了整整一周时间把502的所有可能场景、排查路径、命令清单、根因分类全部整理了一遍。今天这篇文章就是我整理出来的成果。不敢说100%覆盖但生产环境里能踩的坑基本都在里面了。你要是看完能少熬两个夜少背几次锅这文章就没白写。502到底是个什么东西在开干之前得先搞清楚502到底是什么不然排查的时候就是瞎子摸象。502的全称是Bad Gateway翻成人话就是网关或者代理服务器在往上游拿数据的时候没拿到或者拿到的东西不对于是就给你返回了一个502。这句话听起来简单但里面的信息量很大。第一个关键词网关。也就是说502基本不会出现在直连后端的场景里它一定是有中间层的情况下才会出现。Nginx、Apache、Haproxy、SLB、CDN、F5这些都是常见的网关。第二个关键词上游。502是网关在告诉客户端我没拿到上游的正常响应。至于是没连上、超时了、还是上游给我返回了一个乱七八糟的东西那就是后面要具体排查的内容了。所以你记住一句话502的锅永远不在用户和网关之间一定是网关到上游这段路出了问题。这也是为什么很多新手排查502的时候一上来就去看后端服务的日志看半天发现服务其实跑得好好的于是就懵了——其实方向就不对。排查前的三件准备工作讲具体排查步骤之前先说几个准备工作这几个步骤能帮你少走一半弯路。第一先确认影响范围。是所有接口都502还是只有部分接口是所有用户都中招还是只有某个地区、某个运营商的用户这个信息决定了你是S级故障还是A级故障也决定了你需要叫多少人起来一起干。我之前就吃过亏大半夜一看到告警就埋头排查结果搞了半天才发现是某个边缘节点的局部问题影响范围非常小但当时我慌得一批根本没先评估范围。第二先抓现场。故障窗口期是金贵的你排查过程中产生的所有数据最好都保留下来。日志、监控截图、网络包、命令输出能留的都留。为啥因为等你查完已经天亮了领导问你你确定是这个问题的时候你得有东西给他看。空口无凭的故障复盘谁都不会买账。第三先沟通。发现故障的第一时间别自己一个人闷头干。在群里吼一声说现在线上有502问题正在排查影响范围XXX这个动作比排查本身还重要。沟通到位了出了问题大家一起扛沟通不到位最后就是你的锅。这不是甩锅这是基本的职业素养。好准备工作说完进入正餐。Nginx返回502的几种典型场景生产环境里502最多的场景还是Nginx作为反向代理的时候。所以我重点讲这块。Nginx的error.log是排查502的第一现场基本所有502的原因都能在这个日志里找到蛛丝马迹。所以排查的第一步永远是去看Nginx的error.log。一般路径是 /var/log/nginx/error.logtail一下最近的错误基本就能看出个大概。下面是我这些年遇到的高频错误形态。connect() failed (111: Connection refused)这种错误的意思是Nginx去连上游的时候连接被拒了。翻译成普通话就是上游服务根本没在监听那个端口或者服务挂了。排查思路很直接上游服务是不是活着直接curl一下上游的IP端口看能不能连上上游服务的端口是不是变了有时候发版的时候改了端口Nginx配置没同步上游服务是不是只监听了127.0.0.1这种情况下外部根本连不进去我之前有个项目后端用的是Spring Boot默认配置下服务只监听127.0.0.1本地测试一切正常一上线就502。后来排查了半天定位到是这个原因加上server.address配置才解决。这种情况其实挺常见的尤其是开发环境和生产环境配置不一致的时候特别容易出这种幺蛾子。connect() failed (110: Connection timed out)这个比Connection refused更恶心因为它意味着连接请求发出去之后对方一直没回应直到超时。这种情况一般是网络层面的问题比如上游服务器宕机或者网络断了防火墙拦截了请求安全组规则没放行上游服务卡死了没法accept新连接排查这种问题的时候telnet是最直接的工具。telnet 上游IP 上游端口要是telnet都连不上基本可以确认是网络问题。这时候你要做的事情是在Nginx所在的机器上ping一下上游IPtraceroute一下看路由路径检查iptables规则检查云上的安全组配置有一回我遇到一个特别坑爹的情况上游服务器明明在跑本地telnet也能通但Nginx就是连不上。最后查出来是两台机器之间的MTU不一致大的包被丢了。改完MTU立马就好了。这种问题排查起来特别费时间因为从表面看一切正常但就是不通。upstream prematurely closed connection这个错误的意思是Nginx刚和上游建立连接上游就主动把连接关了连响应都没给。这种场景的根因基本都在上游服务比如上游服务crash了上游服务的worker被kill了上游服务处理请求太慢超过了Nginx的超时时间上游服务在做优雅停机这种问题光看Nginx的日志是不行的必须配合上游服务的日志一起看。我的习惯是定位到上游机器之后tail -f 应用日志同时在Nginx那边复现请求然后两边对照着看。有一次遇到一个诡异的问题上游是Java应用每次Nginx打过来的请求处理到一半就被中断了Nginx报prematurely closed。查了两天才发现是JVM的某个参数配错了导致Socket被异常关闭。504 Gateway Time-out虽然这个错误码是504不是502但很多同学会混淆而且它们的排查思路其实是相通的所以也放在一起讲。504的意思是Nginx和上游建立了连接但上游在规定时间内没返回响应。这种场景基本都是上游服务处理能力的问题。排查思路看上游服务的QPS、RT、错误率看上游服务的CPU、内存、线程数看上游是否有慢SQL、死锁、FullGC等情况看上游依赖的下游服务是否正常我处理过的最典型的一次504是数据库出现了一条慢SQL单条查询要跑30秒拖垮了整个服务池。这种情况下Nginx报错后端服务看起来也没崩但请求就是处理不过来。经验之谈遇到504的时候不要只盯着Nginx的timeout配置调大调大只是掩盖问题根因还在上游。no live upstreams这个错误比较少见但遇到了就很头疼。它的意思是Nginx配置的upstream组里所有服务器都被标记为不可用了。这种情况一般是健康检查配置有问题或者上游真的全挂了。排查思路检查upstream配置里有没有启用健康检查看健康检查的阈值配得是否合理手动测试upstream里的每台机器是否都还活着我之前有个项目配了比较激进的健康检查策略结果服务稍微一抖动就被标记为不可用后来调整了阈值才好。SSL握手失败如果你的Nginx是HTTPS的上游也是HTTPS的那中间还有个SSL握手的过程。SSL握手失败也会导致502。这种场景的错误日志一般是SSL_do_handshake() failed之类的。排查思路检查证书是否过期检查证书链是否完整检查SSL协议版本和加密套件是否兼容检查上游是否要求客户端证书生产环境里证书过期导致的502简直是运维的噩梦。尤其是Let’s Encrypt的免费证书90天就要续期一次没自动化的话很容易忘记。Nginx自身资源耗尽还有一种容易被忽略的情况Nginx自己扛不住了。Nginx的worker_connections是有上限的默认是1024。要是连接数打满了新的请求就处理不了表现出来也可能是502。排查命令# 查看Nginx当前的连接数 ss -n | grep :80 | wc -l # 查看Nginx的worker进程状态 ps aux | grep nginx这种情况一般是遭受了CC攻击或者上游回包太慢导致大量连接被占用。完整排查路径图上面讲的是单点场景现在串起来讲一个完整的排查流程。第一步看监控确认影响范围和持续时间Grafana、Zabbix、Prometheus都行先看一下502的QPS和占比影响的接口范围故障开始的时间点是否有发布、配置变更、网络调整等动作同步发生第二步看Nginx错误日志tail -f error.log观察错误的具体形态。这一步至关重要能帮你快速定位到是上面几种场景里的哪一种。第三步测试上游连通性从Nginx机器上直接curl上游curl -v http://上游IP:端口/health注意要用-v参数能看到详细的连接过程。这一步能验证最基本的网络连通性。第四步检查上游服务状态进程是否在跑端口是否在监听资源使用情况应用日志有没有异常第五步缩小问题范围根据前三步的结果基本能定位到是网络问题、上游服务问题、还是Nginx配置问题。然后针对性地深入排查。第六步根因定位 临时止血找到根因之后先做临时止血比如重启服务、回滚配置、切流量。然后再彻底解决。第七步事后复盘故障恢复之后写复盘文档把时间线、根因、改进措施都写清楚。几个真实案例案例一某天晚上业务高峰期突然大量502那次的error.log显示是connect() failed (110: Connection timed out)。我第一反应是上游挂了结果telnet测试一切正常。继续查发现是云厂商的负载均衡SLB和后端服务器之间的健康检查出了问题SLB认为后端不健康所以把流量都打到了同一台机器上那台机器扛不住就超时了。解决方法在SLB上调整健康检查的阈值并且增加后端机器数量。案例二发版之后部分接口502部分正常这种就很典型了肯定是发布相关的问题。我查了一下Nginx配置果然是上游upstream的地址没改新的服务在新的端口Nginx还在打老端口。教训发布流程里一定要有Nginx配置同步这个环节最好做配置变更的自动化检查。案例三CDN回源502CDN回源502的排查和直接Nginx的502类似但要更复杂一些因为中间多了CDN这一层。排查思路先确认是不是全网502还是只有某些节点通过修改hosts的方式直连源站测试查看CDN的回源配置CDN的问题很多时候是回源Host配置不对或者源站有针对CDN的特殊限制比如限流、白名单。502排查的避坑清单聊几个我踩过的坑新司机认真看。不要只看Nginx的配置不看上游。很多时候问题真的不在Nginx在上游。不要忽略keepalive配置。Nginx和上游之间的长连接配置不当会导致大量连接重建性能急剧下降。不要在生产环境直接改配置再reload。一定要在测试环境验证通过。不要忽略时间点的对齐。把监控时间点、Nginx日志时间点、上游日志时间点对齐到秒往往能发现一些隐藏的关联。不要只查HTTP状态码。要看完整的请求和响应包括header、body这些信息对定位问题非常关键。502的预防比排查更重要写到最后说点预防的事情因为最好的故障处理就是不让它发生。做好健康检查。Nginx自带的健康检查比较弱建议用Tengine或者自己写脚本来做主动健康检查。做好超时配置。connect_timeout、send_timeout、read_timeout这些参数要根据业务特点合理设置不要照搬默认值。做好监控告警。502的错误率一定要有监控阈值要合理既不能太敏感导致告警风暴也不能太迟钝导致故障扩散。做好容量评估。定期做压测了解系统的极限在哪里提前扩容或者优化。做好变更管理。所有的配置变更、发布操作都要有记录有回滚方案有审批流程。做好预案。针对502这类常见故障要有标准化的处理流程新人来了也能照着做。写在最后做运维这几年最大的感受就是故障是不可避免的但好的运维能让故障的影响降到最低。502这个错误码看着简单背后牵扯到的东西可不少。网络、服务、配置、架构任何一个环节出问题都可能导致它。但只要你按照一个标准化的流程去排查有完整的工具链和监控体系支持定位它其实并不难。我今天写的这些都是我这些年线上实战踩过的坑、走过的弯路。有一些看起来很基础但恰恰是这些基础的东西在关键时刻能救你一命。建议你把这篇文章收藏起来下次遇到502的时候拿出来对照着排查。说不定能帮你省下一个通宵。