問題
用戶端送出請求,通過網關通路項目A的接口擷取資源資料,通路逾時,報504
解決過程
- 第一步:在項目A中先對接口進行單測,并列印耗時時間,顯示500毫秒,故确認非接口性能問題
- 第二步:網關調用遠端調試項目A,在用戶端發起請求至項目A該接口傳回最終資料,時間隻在一瞬間,故确認問題出在網關接收傳回資料的環節
- 第三步:遠端調試網關,将斷點定位在網關擷取到項目A傳回資料的那行代碼,一步一步走下去,發現反序列傳回資料的方法抛出StackOverflowError異常
- StackOverflowError是棧溢出異常,發生原因是方法調用太多,棧空間不夠用,常見于遞歸調用
- 第四步:檢查傳回資料,發現傳回資料内部一個屬性值指向外部類的引用,發生了死循環引用,示例結構如下
data = {[email protected]}{
name = "名稱外部"
child = {[email protected]}{
name = "名稱内部"
this$0 = {[email protected]}{
name = "名稱外部"
child = {[email protected]}{
...省略...循環
}
}
}
}
- 第五步:定位到問題出在傳回資料出現了内部遞歸指向,即網關在反序列化傳回資料時,先建立了A,然後建立A的屬性name、child,但是屬性child的屬性又指向A,于是又初始化A屬性,造成了死循環調用,最終抛出StackOverflowError異常
- 第六步:回到項目A檢查傳回資料的資料結構,發現發生遞歸引用的那個屬性的類型是一個内部類,經查閱,了解到内部類在建立時會預設擁有一個外部類執行個體的引用,故将内部類改成靜态内部類,問題解決
解決思路
- 先排查項目接口本身是否有問題
- 然後網關調用接口,判斷接口傳回速度是否有問題
- 最後定位到網關傳回環節有問題
- 根據該環節所報異常排查最終問題