中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

Tomcat竟然有bug,這我能信?

2019-06-18    來源:天下數(shù)據(jù)IDC資訊

容器云強勢上線!快速搭建集群,上萬Linux鏡像隨意使用

背景介紹

為了解決分布式鏈路追蹤的問題,我們引入了實現(xiàn)OpenTracing的Jaeger來實現(xiàn)。然后我們?yōu)镾pringBoot框架寫了一個starter以讓用戶實現(xiàn)近零改造接入全鏈路。

由于公司有一個封裝了SpringBoot的內(nèi)部框架,然后我們的starter就以最新框架所使用的SpringBoot版本為基礎進行開發(fā)。所以業(yè)務系統(tǒng)在接入的時候需要先升級框架,然后再引入我們的starter才行無縫接入全鏈路。

故障描述

然后有一個業(yè)務系統(tǒng)就按照步驟,升級框架,引入starter就接入了全鏈路系統(tǒng),并且功能測試壓力測試都已經(jīng)通過了。結(jié)果我們滿懷信心地就上線了。結(jié)果,線上nginx報大量http 400錯誤。

故障排查

出現(xiàn)故障后,業(yè)務系統(tǒng)的研發(fā)人員查了所有的日志,包括elk以及機器上的日志,都沒有發(fā)現(xiàn)明顯的錯誤日志。這個就。。。

幾番掙扎后還是沒有在線上的日志中找到任何蛛絲馬跡。這個就比較絕望了。更奇怪的是在測試環(huán)境中是正常的,這個就比較詭異了。

然后我們猜想是不是之前壓力測試做得不夠啊,我們還是在壓測環(huán)境中再壓測一下看看會不會復現(xiàn)。然后正好之前這個業(yè)務系統(tǒng)做過壓測,那就趕緊找運維搭建一個壓測環(huán)境。結(jié)果剛搭建完就非常給面子地復現(xiàn)了400錯誤。

然后運維同學就各種折騰,然后神奇般地在nginx中的location下加了一行配置后就好了。

proxy_set_header HOST $host 

然后就開始各種查這個配置是啥意思。

這個配置的主要是在nginx在轉(zhuǎn)發(fā)htp請求的時候會加上實際的Host請求頭。如http請求是 http://abc.com/hello,那么nginx在轉(zhuǎn)發(fā)http請求的時候會原封不動的把host請求頭(Host:abc.com)轉(zhuǎn)發(fā)給后臺服務。對于nginx而言,如果沒有配置proxy_set_header HOST $host的時候會默認修改Host為upstream的名稱。

然后我們又在壓測環(huán)境中試了一下修改之前的版本,發(fā)現(xiàn)是正常的。

我們nginx的配置大體如下:

那總結(jié)一下現(xiàn)在的現(xiàn)象:

在nginx沒有配置proxy_set_header HOST $host的時候,修改之前的版本是正常的,修改之后的版本報400錯誤。 在nginx配置了proxy_set_header HOST $host之后,兩個版本都是正常的。

那我們到底修改了什么呢?

升級SpringBoot的版本 引入全鏈路starter

然后我們試了下去掉全鏈路starter的引用,發(fā)現(xiàn)還是400錯誤。然后再回退SpringBoot版本,發(fā)現(xiàn)是正常的。

綜上:是因為升級了SpringBoot版本導致了該問題,又因為是http的頭部變化導致的問題,故可以大膽猜測是因為升級了Tomcat版本導致的該問題。

tomcat版本從8.5.11升級到8.5.31

故障本地復現(xiàn)

由前面的分析可知,nginx在沒有配置proxy_set_header HOST $host 的時候,在轉(zhuǎn)發(fā)http請求的時候會默認把upstream的名稱作為Host頭部的內(nèi)容。

也就是說新版的tomcat在接收Host為sc_java(帶有下劃線)的http請求報了400錯誤。

下面我們來復現(xiàn)一下這個錯誤:

如下,本地部署兩個使用新版本tomcat的后臺服務,端口分別為8083和8084。

nginx配置如下。重點是upstream是帶下劃線的。

然后使用postman請求nginx,復現(xiàn)400錯誤。

調(diào)整nginx配置,主要修改upstream為沒有下劃線的。

然后再請求,發(fā)現(xiàn)是正常的。

故障修復方案

回退tomcat版本。代價較大。 線上修改nginx配置:加上配置proxy_set_header HOST $host 或者修改upstream為沒有下劃線的名稱

根因分析

我們雖然知道了故障的原因,也知道了怎么修復這個故障。但是就是不知道新版的tomcat為什么出現(xiàn)這個問題。帶著這個疑問,我們組的同事在SpringBoot項目的issue中搜索了下400問題,發(fā)現(xiàn)確實有相關的issue。

https://github.com/spring-projects/spring-boot/issues/13236

雖然看上去跟我們的問題是一樣的,都是400問題,但是具體發(fā)生的原因是不一樣的。這個issue是說,如果domain name .ext 包含數(shù)字,比如 "domain.sf1m",會出現(xiàn)400問題。這個問題也已經(jīng)在tomcat的新版本中修復了。

但是即使我使用最新的8.5.x版本的tomcat,用帶有下劃線的Host的http去請求tomcat的時候依然會報400錯誤。

也就是說,帶有下劃線的Host的http請求,tomcat認為是有問題的。

那為什么之前版本的tomcat是正常的呢?帶著這個疑問我們來分析一下tomcat的源代碼。

由于之前沒有看過tomcat的源代碼,所以要分析出到底是哪一行代碼有問題是很困難的,所以我查看了下tomcat的相關的bug

https://bz.apache.org/bugzilla/show_bug.cgi?id=62371

下面是bug中的錯誤stack。

發(fā)現(xiàn)對應的代碼改動如下:

到這里我們也就知道了處理Host頭部的類就是這個HttpParser類。

然后我在本次check了下tomcat8.5.31 和8.5.11的代碼,比對了一下HttpParser以及AbstractProcessor類。

對比結(jié)果如下:

發(fā)現(xiàn)8.5.31版本的AbstractProcessor類中多了一個parseHost的方法,然后主要解析方法是Host.parse(valueMB);

到這里我們就已經(jīng)知道了為什么8.5.11版本的tomcat是正常的,主要是因為8.5.11版本的tomcat沒有對Host頭部進行校驗,而在8.5.31版本的tomcat增加了該校驗。

我們來看一下tomcat源代碼的提交記錄:

我們發(fā)現(xiàn)在 2018/4/6增加了對host/port的校驗。

根因之根因

那為什么tomcat增加了這個Host的校驗呢,而且不允許使用帶有下劃線的Host呢?實際上這個是有規(guī)范的。具體點擊這個鏈接

https://www.ietf.org/rfc/rfc1034.txt

經(jīng)驗教訓

好了,到這里我們就知道了,其實對于帶有下劃線的Host,tomcat是遵循的RFC1-1034的規(guī)范的,所以tomcat的處理是正確的。但是tomcat在處理某些其他合法的Host的時候歷史上出現(xiàn)過bug,但是對于下劃線的處理一直是正確的。

所以,以后nginx在配置upstream的時候不能使用帶有下劃線的名稱,還有最好在location位置上加上proxy_set_header HOST $host

【凡本網(wǎng)注明來源非中國IDC圈的作品,均轉(zhuǎn)載自其它媒體,目的在于傳遞更多信息,并不代表本網(wǎng)贊同其觀點和對其真實性負責!

延伸閱讀:

  • 大數(shù)據(jù)是未來金融專業(yè)人士必備的技能嗎?
  • 5G 都來了,危險的 2G 網(wǎng)絡為何“陰魂不散”?
  • 2019,Java碼農(nóng)還有必要轉(zhuǎn)型大數(shù)據(jù)開發(fā)嗎?

標簽: [db:TAGG]

版權申明:本站文章部分自網(wǎng)絡,如有侵權,請聯(lián)系:west999com@outlook.com
特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀點!
本站所提供的圖片等素材,版權歸原作者所有,如需使用,請與原作者聯(lián)系。

上一篇:比特管理瓦特 華為用AI使能數(shù)據(jù)中心智能化

下一篇:Ivanti羅琦:致力于幫助中國客戶打造現(xiàn)代化的I