“不敢去懷疑代碼,又不得不懷疑代碼”記一次網絡請求超時分析

摘要:此次定位,頗爲複雜,而且有時讓人沒有思路,因爲同一個接口,換一個環境又好使了,又不敢去懷疑代碼;然而有問題的環境,換一個接口也好使了,又不得不懷疑代碼

本文分享自華爲雲社區《一次網絡請求超時分析》,作者:xiewenci 。

問題現象

發起http請求,後端服務接口/v5/iot/11c9c88e6fb26bead43b75514dc380eb/routing-rule/rules?limit=10&marker=ffffffffffffffffffffffff&offset=0,一直等待,一分鐘後返回響應,且中文亂碼顯示

分析過程

1.首先定界,在正常環境和異常環境換一樣的版本代碼,測試同樣接口,但是正常環境正常,異常環境還是等待1分鐘,所以覺得是環境問題,於是下一步,抓包

2.分別再異常環境和正常環境抓包,具體流信息見下圖:

異常環境的流信息

正常環境的流信息

從圖中看出正常環境是,服務端發送響應完成之後,由客戶端正常返回ACK,然後由客戶端發起FIN斷鏈請求。而異常環境則是服務端發送響應完成之後,客戶端也回了ACK,但是沒有主動發起斷鏈請求,直到超過keep-alive時間之後,由服務端發起了斷鏈請求(因爲超時主動斷鏈)。現象是客戶端一直在等服務端發送響應(可能沒有發送完),所以懷疑服務端有緩存之類,沒有及時將響應流發送出去,所以繼續查看代碼

3.查看代碼,在返回客戶端的時候,沒有flush和close操作,代碼如下

然後以爲找到問題原因所在了,就嘗試修改代碼,如下:

增加了flush操作和close操作(放在了try語快中),最後測試執行,還是跟最初的現象一致,還是會等待1分鐘後纔會返回響應。這時就有點納悶了,再重新仔細分析下流,其實從流中可以看出來,服務端的響應是立馬返回給了客戶端的,如下圖

既然給了響應,那爲什麼客戶端爲什麼還要繼續等待呢?這裏有注意到圖中有幾個問號,這其實是中文字符亂碼了,所以這裏又懷疑是不是編碼格式導致客戶端收到的Content-Length長度和收到的響應的長度不一致,也就是客戶端實際收到的響應的長度小於Content-Length的長度,然後一直等待下去,所以繼續修改代碼

4.修改代碼,指定編碼格式爲UTF-8,代碼如下:

替換環境版本,測試執行,響應就立馬返回了,果然是這個編碼格式的鍋

原因回顧

1.編碼格式不一致就會導致響應流的實際長度不一致?答案是一定的,編碼格式不一致,實際長度就是會不一致,測試結果如下:

2.爲什麼之前的沒有出現過這個問題?是什麼原因導致編碼格式丟失的

查看後端服務jar包,發現spring版本已經升級到5.2.21.RELEASE,此版本中沒有指定默認編碼格式爲UTF-8

所以需要後端服務去指定編碼格式,或者網關服務統一處理

總結與思考

此次定位,頗爲複雜,而且有時讓人沒有思路,因爲同一個接口,換一個環境又好使了,又不敢去懷疑代碼;然而有問題的環境,換一個接口也好使了,又不得不懷疑代碼;還有就是在容器中去調用接口,也是一樣的問題,所以感覺又跟網絡沒啥關係。其實應該靜下心來去思考爲什麼客戶端那裏一直等待,沒有主動發起斷鏈,這裏還是說明了對HTTP協議細節,不夠熟練掌握,才導致中間走了一些誤區,需要去鞏固和加深對http協議的理解。

 

點擊關注,第一時間瞭解華爲雲新鮮技術~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章