springboot-@Async默認線程池導致OOM問題


內存溢出的三種類型:

  • 第一種OutOfMemoryError: PermGen space,發生這種問題的原意是程序中使用了大量的jar或class
  • 第二種OutOfMemoryError: Java heap space,發生這種問題的原因是java虛擬機創建的對象太多
  • 第三種OutOfMemoryError:unable to create new native thread,創建線程數量太多,占用內存過大

初步分析:

初步懷疑是線程創建太多導致,使用jstack 線程號 > /tmp/oom.log將應用的線程信息打印出來。查看oom.log,發現大量線程處於Runnable狀態,基本可以確認是線程創建太多了。

代碼分析:

1.出問題的微服務是日志寫庫服務,對比日志,鎖定在writeLog方法上,wirteLog方法使用spring-@Async注解,寫庫操作采用的是異步寫入方式。
2.之前沒有對@Async注解深入研究過,只是知道可以自定義內部線程池,經查看,日志寫庫服務並未自定義異步配置,使用的是spring-@Async默認異步配置
3.網上提到@Async默認異步配置使用的是SimpleAsyncTaskExecutor,該線程池默認來一個任務創建一個線程,在壓測情況下,會有大量寫庫請求進入日志寫庫服務,這時就會不斷創建大量線程,極有可能壓爆服務器內存。

最終解決辦法:

1.自定義線程池,使用LinkedBlockingQueue阻塞隊列來限定線程池的上限
2.定義拒絕策略,如果隊列滿了,則拒絕處理該任務,打印日志,代碼如下:


免責聲明!

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



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