Apache Commons Poo GenericObjectPool 避免泄漏

GenericObjectPool 是 Apache Commons Pool 提供的對象池,使用的時候需要調用 borrowObject 獲取一個對象,使用完以後需要調用 returnObject 歸還對象,或者調用 invalidateObject 將這個對象標記爲不可再用。

實際應用中由於程序實現的問題,可能造成在一些極端的情況下出現 borrowObject/invalidateObject 沒有被調用導致的泄漏問題。對象泄漏會導致對象池中的對象數量一直上升,達到設置的上限以後再調用 borrowObject 就會永遠等待或者拋出java.util.NoSuchElementException: Timeout waiting for idle object 異常。

對於這種問題,一方面是從應用實現上進行排查,另一方面可以通過 GenericObjectPool 自帶的機制進行清理。

設置自動清理

設置拋棄時間

GenericObjectPool判斷一個對象是否泄漏是根據對象最後一次使用或者最後一次borrow的時間進行判斷的,如果超出了預設的值就會被認爲是一個泄漏的對象被清理掉(PooledObjectFactory.destroyObject在這一過程中會被調用)。拋棄時間可以通過 AbandonedConfig.setRemoveAbandonedTimeout 進行設置,時間單位是秒。

打開泄漏清理

設置了拋棄時間以後還需要打開泄漏清理纔會生效。泄漏判斷的開啓可以通過兩種方式:

  1. 從對象池中獲取對象的時候進行清理如果當前對象池中少於2個idle狀態的對象或者 active數量>最大對象數-3 的時候,在borrow對象的時候啓動泄漏清理。通過 AbandonedConfig.setRemoveAbandonedOnBorrow 爲 true 進行開啓。

  2. 啓動定時任務進行清理AbandonedConfig.setRemoveAbandonedOnMaintenance 設置爲 true 以後,在維護任務運行的時候會進行泄漏對象的清理,可以通過 GenericObjectPool.setTimeBetweenEvictionRunsMillis 設置維護任務執行的時間間隔。

 
GenericObjectPool<PoolObj> pool = new GenericObjectPool<PoolObj>(new MyPooledObjectFactory(),config);
 
AbandonedConfig abandonedConfig = new AbandonedConfig();
 
abandonedConfig.setRemoveAbandonedOnMaintenance(true); //在Maintenance的時候檢查是否有泄漏
 
abandonedConfig.setRemoveAbandonedOnBorrow(true); //borrow 的時候檢查泄漏
 
abandonedConfig.setRemoveAbandonedTimeout(10); //如果一個對象borrow之後10秒還沒有返還給pool,認爲是泄漏的對象
 
pool.setAbandonedConfig(abandonedConfig);
 
pool.setTimeBetweenEvictionRunsMillis(5000); //5秒運行一次維護任務

 

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