由Premature end of Content-Length delimited message body因發的問題排查


問題出現: 視頻剪輯超時

   1。檢查系統日志

 

 發現這個報錯信息,導致接口訪問超時獲取數據失敗。

2。經過對網上信息梳理,發現這個超時是在用域名訪問nginx時候,有一個send_timeout超時時間,超過這個時間nginx將連接斷開了。代碼會報錯

     (如果有遇到相同問題的同學,並且正好是域名訪問接口報錯,可以直接更改配置,調整超時時間。 但同樣也要反思,這個接口響應這么久真的沒問題嗎?)

 

3。由於這個請求的數據大小只有2M,大概四千條數據,響應不應該這么慢,然后開始debug查詢問題。

4。看圖

 

這個是httpUtil的一個工具類,可以看到這行代碼是有問題的。

 

原因:

使用+拼接字符串的實現原理,基於jdk1.8

 

下面一段代碼。把他生成的字節碼進行反編譯,看看結果。

String testJoin = "testJoin";
String introduce = "測試數據拼接";
String result =
testJoin + "," + introduce;

反編譯后的內容如下,反編譯工具為jad。

String testJoin= "testJoin";
String introduce = "\u6BCF\u65E5\u66F4\u65B0Java\u76F8\u5173\u6280\u672F\u6587\u7AE0";
String
result= (new StringBuilder()).append(testJoin).append(",").append(introduce).toString();

通過查看反編譯以后的代碼,可以發現,原來字符串常量在拼接過程中,是將String轉成了StringBuilder后,使用其append方法進行處理的。

 

 

 

改動代碼為如下:

 

 這樣處理數據的時候就非常快,問題看似已經解決。

問題擴展:

我這里經過測試,發現只有請求我寫的新系統時候,才會發生這種響應慢的問題。然后繼續打斷點調試。

發現同一個json數據結構體,其他系統在這里只需要遍歷一次就可以。

 

 自我反思:

為什么只需要遍歷一次? 數據傳輸的時候是一行? 為什么我的是多行? 同樣是json體為什么我的就需要遍歷多次?

 

排查繼續:

檢查使用的JSON序列化工具,發現其他系統用的是jackson,而我使用的是fastjson。 

 

 將這個配置注釋掉,再次調用接口發現循環遍歷的時候變成了一次。

繼續反思:

springBoot項目中返回數據的時候我用到了@ResponseBody, 這個注解是用的那個JSON序列化工具?

這里就開始查詢源碼,自我debug過程不再論述,網上源碼講解很多,直接貼出來給大家參考。

https://www.cnblogs.com/HHR-SUN/p/11639801.html

https://www.jianshu.com/p/2f633cb817f5

核心點就是spring MVC有HttpMessageConverter這個消息轉換器,我們的請求與返回數據的響應都經過這里,經過debug發現@ResponseBody默認采用的是jackson。

 

難道和這個序列化有關系? 

這個關鍵是HTTP獲取流,還沒有對此進行反序列化等操作。然后在一個接口中直接用fastjson轉換了一下結果,發現數據返回並沒有問題,也是遍歷一次就可以。

 

最后:

上面引用了fastjson的時候做了一下配置,懷疑是某個配置造成。(這個 配置文件直接拷貝其他項目,具體配置並不了解。自己坑自己)

 

 

查找各配置含義:

 

 

懷疑是這個格式化原因,將其注釋掉,再次調用接口,發現問題解決。

 

擴展:

 

 下面數據為格式化后的樣子,比格式化前數據大了18%左右

 

 

總結

問題的排查必須要有從點到面的思考方式,解決問題的方式有很多,但是問題的出現可能是連鎖反應,直有從頭到尾,不錯過任何細節才能發現真正的原因

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM