Tomcat竟然有bug,这我能信?
副标题[/!--empirenews.page--]
背景介绍 为了解决分布式链路追踪的问题,我们引入了实现OpenTracing的Jaeger来实现。然后我们为SpringBoot框架写了一个starter以让用户实现近零改造接入全链路。 由于公司有一个封装了SpringBoot的内部框架,然后我们的starter就以最新框架所使用的SpringBoot版本为基础进行开发。所以业务系统在接入的时候需要先升级框架,然后再引入我们的starter才行无缝接入全链路。 故障描述 然后有一个业务系统就按照步骤,升级框架,引入starter就接入了全链路系统,并且功能测试压力测试都已经通过了。结果我们满怀信心地就上线了。结果,线上nginx报大量http 400错误。 故障排查 出现故障后,业务系统的研发人员查了所有的日志,包括elk以及机器上的日志,都没有发现明显的错误日志。这个就。。。 几番挣扎后还是没有在线上的日志中找到任何蛛丝马迹。这个就比较绝望了。更奇怪的是在测试环境中是正常的,这个就比较诡异了。 然后我们猜想是不是之前压力测试做得不够啊,我们还是在压测环境中再压测一下看看会不会复现。然后正好之前这个业务系统做过压测,那就赶紧找运维搭建一个压测环境。结果刚搭建完就非常给面子地复现了400错误。 然后运维同学就各种折腾,然后神奇般地在nginx中的location下加了一行配置后就好了。
然后就开始各种查这个配置是啥意思。 这个配置的主要是在nginx在转发htp请求的时候会加上实际的Host请求头。如http请求是 http://abc.com/hello,那么nginx在转发http请求的时候会原封不动的把host请求头(Host:abc.com)转发给后台服务。对于nginx而言,如果没有配置proxy_set_header HOST $host的时候会默认修改Host为upstream的名称。 然后我们又在压测环境中试了一下修改之前的版本,发现是正常的。 我们nginx的配置大体如下: 那总结一下现在的现象:
那我们到底修改了什么呢?
然后我们试了下去掉全链路starter的引用,发现还是400错误。然后再回退SpringBoot版本,发现是正常的。 综上:是因为升级了SpringBoot版本导致了该问题,又因为是http的头部变化导致的问题,故可以大胆猜测是因为升级了Tomcat版本导致的该问题。 tomcat版本从8.5.11升级到8.5.31 故障本地复现 由前面的分析可知,nginx在没有配置proxy_set_header HOST $host 的时候,在转发http请求的时候会默认把upstream的名称作为Host头部的内容。 也就是说新版的tomcat在接收Host为sc_java(带有下划线)的http请求报了400错误。 下面我们来复现一下这个错误: 如下,本地部署两个使用新版本tomcat的后台服务,端口分别为8083和8084。 nginx配置如下。重点是upstream是带下划线的。 然后使用postman请求nginx,复现400错误。 ![]() 调整nginx配置,主要修改upstream为没有下划线的。 然后再请求,发现是正常的。 故障修复方案
根因分析 我们虽然知道了故障的原因,也知道了怎么修复这个故障。但是就是不知道新版的tomcat为什么出现这个问题。带着这个疑问,我们组的同事在SpringBoot项目的issue中搜索了下400问题,发现确实有相关的issue。 https://github.com/spring-projects/spring-boot/issues/13236 (编辑:晋中站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |