問題出現: 視頻剪輯超時
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%左右
總結
問題的排查必須要有從點到面的思考方式,解決問題的方式有很多,但是問題的出現可能是連鎖反應,直有從頭到尾,不錯過任何細節才能發現真正的原因