问题出现:

线上异常告警,如图:

总的来说,就是各种对外接口频繁出现偶发性的商户请求不通,同时集中在同一项目部署的应用,Nginx 502 告警,并报错日志 no live upstreams while connecting to upstream。

排查过程:

顾名思义:这个报错是没有上游可用,但是是什么原因导致呢?对于Nginx而言,出现这个报错存在很多的可能性,大致可以有:①Nginx资源不足 ②上游服务器异常 ③上游应用业务异常 等等。 

然后排查过程中,需要思考的因素蛮多的,首先运维很快就排除了①,有同事提议可能性②:可不可能是并发导致上游应用资源不足? 导致tomcat连接数不足?详情可以参考此文章:https://www.cnblogs.com/zjfjava/p/10909087.html

我看下了当时的并发数,可以很快推定,不是这个原因导致的。所以原因②几乎不成立。所以重点回到③。然后大伙查日志发现Nginx还有个很重要的信息。如图:

 

 upstream server temporarily disabled while connecting to upstream。这个报错就很清楚明了,Nginx常规报错。初步判断是上游业务异常。

接下来顺藤摸瓜,开始排查对外接口,然后有一个接口,这里别名为 A。A接口感觉是我们不常用,为啥频繁出现请求,然后有看下参数,发现都是空传。初步判断是被攻击了。然后对A接口进行剖析(当然A接口已经被强制下线),发现报错mybatis,同时返回状态码为 500 。如图所示:

原因是A这个接口请求返回500,Nginx标记A所在上游不可用,然后轮询所有的上游都不可用,有其他的请求进来,Nginx直接返回502,内部报错无可用upstream。

再后来,运维通过修改 Nginx 的 max_fails = 0。也验证我们排查问题的结论。

总结: 

①发生问题的原因是我们那个对外接口处理逻辑不正确,即商户请求进来并不是常规的验签验参(如果验签验参不通过,系统是会返回常规错误码 200),而是直接请求了数据库。上述问题相当于查全表操作了,才导致Mybatis报错,返回错误码 500,引发一系列的问题。同时也引发了我写代码的思考:程序编程的时候,我们不单单要考虑如何实现业务,也要多一份思考去防止被攻击以及性能等的可能性。本次异常具体原因:https://www.jianshu.com/p/6cf9bab3de50

②排查问题是时候,都是和运维小伙伴一起排查,相互指引完成的。所以排查问题的时候,不能局限自身,多看各方意见,才能快速定位并解决问题。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐