2月11日網關在短期內出現20+的訪問出錯,查看kibina以下:java
根據trace獲得具體的堆棧異常,發現都是負載均衡同一個pod均顯示鏈接異常:api
去grafana查看該pod運行狀況,能夠發現內存忽然降低的狀況,同時該pod已經達到內存上限(8G),當資源申請不到的狀況下,該pod可能存在重啓的狀況:緩存
查看ad服務的日誌驗證了當時確實發生了重啓:app
此時能夠基本定位到由於內存問題使得服務重啓,從而網關沒法負載均衡到該服務實例致使網關報錯,接下來須要明確是什麼緣由讓該pod的內存佔用如此之高。負載均衡
非堆就是JVM留給本身用的,方法區、JVM內部處理或優化所需的內存(如JIT編譯後的代碼緩存)、每一個類結構(如運行時常數池、字段和方法數據)以及方法和構造方法 的代碼都在非堆內存中。優化
用JProfiler打開該文件(也能夠用jVisualVM),找到Biggest Objects,而後發如今存活對象中存在大量的AdDto這個類的實例,大量這些對象整整佔用了1G多:spa
回到代碼中,檢查AdDto的生成方式,發現用了以下的操做:3d
modelMapper每一次調用addMapping都將建立一份該類的結構(經過字節碼而後由類加載器加載),查閱官網相關文檔。若是轉換類型肯定,應該將ModelMapper設置成單例(modelmapper.org/user-manual…日誌
在普通接口中用這段代碼驗證猜測,能夠很明顯看到非堆內存一路猛漲,而且加載類的數量也在一路上升,基本證明了問題:code
將代碼改爲以下形式並從新壓測:
private static ModelMapper modelMapper;
static {
modelMapper = new ModelMapper();
TypeMap<Person, PersonDTO> typeMap = modelMapper.createTypeMap(Person.class, PersonDTO.class);
typeMap.addMappings(mapper -> {
mapper.skip(PersonDTO::setAge);
});
}
@GetMapping("api/benchmark/qa")
public PersonDTO qa() {
Person p = new Person();
p.setName("wangao");
p.setAge(30);
return modelMapper.map(p, PersonDTO.class);
}
複製代碼
發現非堆內存穩定,類加載數量穩定: