nginx健康检查导致的问题

最近有次web应用版本上线,出现了一个可怕的事情,上线之后所有http请求都报502,但是之前在测试环境和预发布环境测试功能是没有任何问题的。
502错误说明是tomcat应用出问题了,查看tomcat启动日志,没有任何异常,日志显示应用已经正常启动成功了,ssh连上服务器,通过wget调用接口发现是可以正常响应的,这就更说明了tomcat应用本身是没问题的。但是查看应用的localhost_access日志发现了大量的下列错误:
nginx健康检查导致的问题_第1张图片
而且该错误在持续的报,找了一下原因,是因为nginx配了健康检查导致的,/health/status是我们tomcat应用的健康检查接口,nginx每隔5秒钟会调用这个接口检查tomcat应用的健康状态:
nginx健康检查导致的问题_第2张图片
但是当时以为健康检查接口不会导致功能有问题,所以并没有把这个错误跟功能错误关联起来。因为是502错误,所以开始怀疑是不是tomcat应用在调用后台的某个接口报错或者超时了,但是在我们的监控平台没有发现任何调用异常的接口。由于测试环境是没有问题的,所以比较测试环境和线上环境一些应用配置差异,也没有发现可疑的地方。但是看了一下测试环境的nginx配置发现,测试机的nginx是没有配定时健康检查的。把测试机nginx的健康检查加上之后,神奇的发现问题可以重现了,健康检查一样的500,功能测试一样的502。最后通过万能的debug发现,原因是在nginx调用/health/status健康检查时应用中有个拦截器会去检查请求头的UA,但是对UA字段没有做NPE检查,由于nginx发起的健康检查请求没有带上UA头域,所以就抛出NPE,所以就导致健康检查请求一直失败500。
那么为什么健康检查接口失败会导致这个功能问题呢,了解了一下nginx健康检查机制,当nginx发给后台服务器的健康检查失败之后,nginx会认为这是一台有问题的服务器,会把它从服务器列表中暂时踢掉,后续的任何请求都不会分到这台服务器了,直到健康检查接口成功才会把它加回去。由于上线之后这个NPE我们所有的tomcat应用的健康检查请求都失败了,nginx会认为没有可用的服务器了,所以任何请求都会失败502。所以即使你应用的功能接口是正常的,但是如果健康检查接口报错了,那么nginx也会把它当成有问题的应用处理。
如果报了NPE有日志打出来那定位问题就会快很多,但spring-mvc框架并没有任何日志打出来,略坑。。。后面要给应用加个异常处理器HandlerExceptionResolver,把异常信息都日志打出来便于快速定位问题。

你可能感兴趣的:(编程技术,JAVA,Nginx)