日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

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

瀏覽:25日期:2023-05-15 10:07:27

前言:

1.最近項目上在測試人員壓測過程中發現了OOM問題,項目使用springboot搭建項目工程,通過查看日志中包含信息:unable to create new native thread

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

初步分析:

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

代碼分析:

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

借此機會也學習了下SimpleAsyncTaskExecutor源碼,總結如下:

1.SimpleAsyncTaskExecutor提供了限流機制,通過concurrencyLimit屬性來控制開關,當concurrencyLimit>=0時開啟限流機制,默認關閉限流機制即concurrencyLimit=-1,當關閉情況下,會不斷創建新的線程來處理任務,核心代碼如下:

public void execute(Runnable task, long startTimeout) { Assert.notNull(task, 'Runnable must not be null'); Runnable taskToUse = (this.taskDecorator != null ? this.taskDecorator.decorate(task) : task); //判斷是否開啟限流機制 if (isThrottleActive() && startTimeout > TIMEOUT_IMMEDIATE) { //執行前置操作,進行限流 this.concurrencyThrottle.beforeAccess(); //執行完線程任務,會執行后置操作concurrencyThrottle.afterAccess(),配合進行限流 doExecute(new ConcurrencyThrottlingRunnable(taskToUse)); } else { doExecute(taskToUse); }}

2.SimpleAsyncTaskExecutor限流實現

首先任務進來,會循環判斷當前執行線程數是否超過concurrencyLimit,如果超了,則當前線程調用wait方法,釋放monitor對象鎖,進入等待

protected void beforeAccess() {if (this.concurrencyLimit == NO_CONCURRENCY) {throw new IllegalStateException('Currently no invocations allowed - concurrency limit set to NO_CONCURRENCY');}if (this.concurrencyLimit > 0) {boolean debug = logger.isDebugEnabled();synchronized (this.monitor) {boolean interrupted = false;while (this.concurrencyCount >= this.concurrencyLimit) {if (interrupted) {throw new IllegalStateException('Thread was interrupted while waiting for invocation access, ' +'but concurrency limit still does not allow for entering');}if (debug) {logger.debug('Concurrency count ' + this.concurrencyCount +' has reached limit ' + this.concurrencyLimit + ' - blocking');}try {this.monitor.wait();}catch (InterruptedException ex) {// Re-interrupt current thread, to allow other threads to react.Thread.currentThread().interrupt();interrupted = true;}}if (debug) {logger.debug('Entering throttle at concurrency count ' + this.concurrencyCount);}this.concurrencyCount++;}}}

2.SimpleAsyncTaskExecutor限流實現:首先任務進來,會循環判斷當前執行線程數是否超過concurrencyLimit,如果超了,則當前線程調用wait方法,釋放monitor對象鎖,進入等待狀態。

protected void beforeAccess() {if (this.concurrencyLimit == NO_CONCURRENCY) {throw new IllegalStateException('Currently no invocations allowed - concurrency limit set to NO_CONCURRENCY');}if (this.concurrencyLimit > 0) {boolean debug = logger.isDebugEnabled();synchronized (this.monitor) {boolean interrupted = false;while (this.concurrencyCount >= this.concurrencyLimit) {if (interrupted) {throw new IllegalStateException('Thread was interrupted while waiting for invocation access, ' +'but concurrency limit still does not allow for entering');}if (debug) {logger.debug('Concurrency count ' + this.concurrencyCount +' has reached limit ' + this.concurrencyLimit + ' - blocking');}try {this.monitor.wait();}catch (InterruptedException ex) {// Re-interrupt current thread, to allow other threads to react.Thread.currentThread().interrupt();interrupted = true;}}if (debug) {logger.debug('Entering throttle at concurrency count ' + this.concurrencyCount);}this.concurrencyCount++;}}}

線程任務執行完畢后,當前執行線程數會減一,會調用monitor對象的notify方法,喚醒等待狀態下的線程,等待狀態下的線程會競爭monitor鎖,競爭到,會繼續執行線程任務。

protected void afterAccess() {if (this.concurrencyLimit >= 0) {synchronized (this.monitor) {this.concurrencyCount--;if (logger.isDebugEnabled()) {logger.debug('Returning from throttle at concurrency count ' + this.concurrencyCount);}this.monitor.notify();}}}

雖然看了源碼了解了SimpleAsyncTaskExecutor有限流機制,實踐出真知,我們還是測試下:一、測試未開啟限流機制下,我們啟動20個線程去調用異步方法,查看Java VisualVM工具如下:

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

二、測試開啟限流機制,開啟限流機制的代碼如下:

@Configuration@EnableAsyncpublic class AsyncCommonConfig extends AsyncConfigurerSupport { @Override public Executor getAsyncExecutor() { SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor(); //設置允許同時執行的線程數為10 executor.setConcurrencyLimit(10); return executor; }}

同樣,我們啟動20個線程去調用異步方法,查看Java VisualVM工具如下:

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

通過上面驗證可知:1.開啟限流情況下,能有效控制應用線程數2.雖然可以有效控制線程數,但執行效率會降低,會出現主線程等待,線程競爭的情況。3.限流機制適用于任務處理比較快的場景,對于應用處理時間比較慢的場景并不適用。==

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

public class AsyncConfig implements AsyncConfigurer{ private Logger logger = LogManager.getLogger(); @Value('${thread.pool.corePoolSize:10}') private int corePoolSize; @Value('${thread.pool.maxPoolSize:20}') private int maxPoolSize; @Value('${thread.pool.keepAliveSeconds:4}') private int keepAliveSeconds; @Value('${thread.pool.queueCapacity:512}') private int queueCapacity; @Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(corePoolSize); executor.setMaxPoolSize(maxPoolSize); executor.setKeepAliveSeconds(keepAliveSeconds); executor.setQueueCapacity(queueCapacity); executor.setRejectedExecutionHandler((Runnable r, ThreadPoolExecutor exe) -> {logger.warn('當前任務線程池隊列已滿.'); }); executor.initialize(); return executor; } @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return new AsyncUncaughtExceptionHandler() { @Override public void handleUncaughtException(Throwable ex , Method method , Object... params) {logger.error('線程池執行任務發生未知異常.', ex); } }; }}

到此這篇關于springboot中@Async默認線程池導致OOM問題的文章就介紹到這了,更多相關springboot @Async線程池導致OOM內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Spring
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
日本一区二区高清不卡| 亚洲久久视频| 综合激情在线| 男人的天堂亚洲一区| 日本欧美在线看| 亚洲ww精品| 国产精品久久久久毛片大屁完整版| 91亚洲精品视频在线观看| 国产三级精品三级在线观看国产| 精品久久99| 蜜桃视频欧美| 日韩一区精品| 精品美女在线视频| 国产精品theporn| 中文字幕在线免费观看视频| 国产亚洲精品v| 女人天堂亚洲aⅴ在线观看| 在线一区av| 国产网站在线| 欧美日韩中文一区二区| 欧美福利一区| 美女毛片一区二区三区四区| 麻豆精品少妇| 欧美国产小视频| 亚洲欧洲美洲av| 中文亚洲欧美| 在线亚洲成人| 欧美亚洲国产激情| 国产视频一区二| 国产黄色精品| 国产不卡av一区二区| 国产精品极品国产中出| 麻豆免费精品视频| 欧美成人精品一级| 国产精品红桃| 色婷婷综合网| 日韩精品专区| 欧美日韩尤物久久| 亚洲精品888| 亚洲激情五月| 91免费精品国偷自产在线在线| 亚洲精品国模| 欧美在线黄色| 日韩超碰人人爽人人做人人添| 国产精品手机在线播放| 国产精品中文| 亚洲天堂免费| 三级精品视频| 欧美羞羞视频| 日韩在线观看| 亚洲男人在线| 婷婷成人在线| 国产精品一线| 日韩精品成人在线观看| 激情综合激情| 久久久久亚洲| 国产探花一区| 开心激情综合| 成人羞羞视频播放网站| 欧美永久精品| 亚洲狼人精品一区二区三区| 欧美激情在线精品一区二区三区| 麻豆精品在线观看| 日韩天堂av| 欧美亚洲激情| 在线手机中文字幕| 国产高清视频一区二区| 欧美在线黄色| 国产日韩中文在线中文字幕 | 国产模特精品视频久久久久| 樱桃视频成人在线观看| 久久国内精品自在自线400部| 日韩亚洲在线| 麻豆国产欧美一区二区三区 | jizzjizz中国精品麻豆| 日韩av在线免费观看不卡| 欧美国产视频| 精品在线91| 国产精品传媒麻豆hd| 午夜日韩av| 国产专区精品| 蜜臀av性久久久久蜜臀aⅴ流畅| 国产精品一区高清| 黑森林国产精品av| 欧美综合另类| 国产一区二区精品| 国产欧美自拍一区| 久久网站免费观看| 日韩高清三区| 日韩电影在线视频| 91亚洲成人| 久久高清免费观看| 日韩精品免费一区二区夜夜嗨| 视频一区视频二区中文字幕| 日本欧美国产| 久久久久久久久99精品大| 国产精品久久久久久久久久10秀| 日韩理论片av| 久久久国产亚洲精品| 99成人在线| 一区二区91| 国产一区二区三区四区大秀| 欧洲一区二区三区精品| 亚洲深夜福利| 卡一卡二国产精品| 欧美gv在线| 99国产成+人+综合+亚洲欧美| 综合干狼人综合首页| 国产一区二区三区四区| 少妇精品导航| 国产日韩在线观看视频| 国产va免费精品观看精品视频| 国产一区日韩一区| 国产欧美激情| 99在线|亚洲一区二区| 亚洲精品第一| 精品一区欧美| 麻豆精品新av中文字幕| 综合五月婷婷| 国内不卡的一区二区三区中文字幕| 国产一区91| www.com.cn成人| 国产精品一区二区三区美女 | 亚洲综合专区| 99久久婷婷这里只有精品| 久久一区亚洲| 日韩在线观看中文字幕| 亚洲精品一二三区区别| 日韩在线第七页| 91欧美国产| 日韩av有码| 国产中文欧美日韩在线| 欧美激情视频一区二区三区免费| 亚洲另类黄色| 日韩精品导航| 日本天堂一区| 9色精品在线| 首页国产欧美久久| 欧美性感美女一区二区| 亚洲国产欧美日本视频| 国产成人精品一区二区三区免费 | 免费观看不卡av| 久久www成人_看片免费不卡| 欧美91精品| 亚洲资源av| 日本va欧美va精品发布| 欧美一区不卡| 精品精品久久| 欧美aa国产视频| 男女性色大片免费观看一区二区| 黄色成人精品网站| 男人操女人的视频在线观看欧美| 亚洲人成亚洲精品| 欧美极品一区二区三区| 久久九九99| 日本成人在线不卡视频| 精品国产成人| 亚洲女人av| 国产精品s色| 日韩中文字幕1| 自拍自偷一区二区三区| 伊人精品久久| 精品欧美日韩精品| 日韩视频二区| 久久中文欧美| 136国产福利精品导航网址| 丝袜脚交一区二区| 粉嫩av一区二区三区四区五区 | 国产精品主播| 欧美日韩色图| 欧美aaaaaa午夜精品| 美女亚洲一区| 久久一区欧美| 日本视频在线一区| 在线视频精品| 日韩精品免费一区二区在线观看 | 欧美www视频在线观看| 99成人在线| 超级白嫩亚洲国产第一| 欧美亚洲网站| 石原莉奈一区二区三区在线观看| 成人台湾亚洲精品一区二区| 亚洲久草在线| 视频一区二区国产| 亚洲精品韩国| 亚洲一区二区三区四区电影| 国产91久久精品一区二区| 福利一区和二区| 精品日本视频| 精品国产乱码久久久久久樱花| 日韩高清国产一区在线| 亚洲精品美女| 综合在线一区| 91成人精品观看| 亚洲精品看片| 青草国产精品| 日韩一区网站| 日韩一级不卡| 国产日韩欧美一区二区三区| 四虎精品永久免费|