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

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

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

瀏覽:28日期: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久久,三上悠亚国产精品一区二区三区
亚洲a级精品| 欧美激情另类| 香蕉成人av| 久久不见久久见国语| 欧美一区91| 国产精品一区二区三区美女 | 国产美女高潮在线| 欧美好骚综合网| 天堂资源在线亚洲| 欧美精品羞羞答答| 亚洲作爱视频| 伊人久久大香伊蕉在人线观看热v| 天堂va蜜桃一区二区三区| 首页国产欧美久久| 欧美专区一区| 久久久久伊人| 欧美aaaaaa午夜精品| 国产在线日韩精品| 久久婷婷激情| 国产一区成人| 日韩国产在线观看一区| 国产精品亚洲人成在99www| 美女久久99| 99精品小视频| 亚洲精品无播放器在线播放| 国产欧美日韩免费观看| 国精品产品一区| 国产高清久久| 日本一区二区中文字幕| 麻豆高清免费国产一区| 亚洲天堂1区| 另类av一区二区| 国产亚洲高清一区| 午夜欧美巨大性欧美巨大| 欧美日韩国产免费观看| 日韩精品福利一区二区三区| 欧美激情aⅴ一区二区三区| 日韩电影免费网址| 久久国产99| 美女视频免费精品| 自由日本语亚洲人高潮| 日本免费新一区视频| 精品美女在线视频| 国产婷婷精品| 久久伊人亚洲| 夜夜嗨一区二区| 日韩精品免费视频人成 | 欧美视频精品全部免费观看| 成人国产精品一区二区免费麻豆| 欧美1区2区3区| 日韩国产高清在线| 欧美羞羞视频| 日韩国产在线观看一区| 久久久久久久久丰满| 日本aⅴ亚洲精品中文乱码| 波多野结衣久久精品| 亚洲人妖在线| 日韩成人亚洲| 国产三级一区| 在线精品小视频| 国产精品久久久久久久久久齐齐 | 国产精品精品国产一区二区| 久热re这里精品视频在线6| 国产成人精品一区二区免费看京| 日韩中文字幕一区二区三区| 国产一区二区三区日韩精品| 亚洲毛片网站| 99久久精品费精品国产| 久久av日韩| 男女男精品网站| 在线天堂中文资源最新版| 亚洲人成毛片在线播放女女| 亚洲www免费| 国产精品巨作av| 亚洲一区二区三区免费在线观看| 精品三级在线| 日韩在线麻豆| 亚洲成人一区| 超碰99在线| 国产视频一区二| 夜夜嗨一区二区三区| 日韩av福利| 精品亚洲成人| 国产欧美一区二区三区国产幕精品 | 国产精品久久久亚洲一区| 国产美女精品| 久久婷婷久久| 国产a亚洲精品| 欧美一区精品| 中文字幕成人| 夜夜嗨av一区二区三区网站四季av| yellow在线观看网址| 国产伦精品一区二区三区千人斩 | 羞羞答答国产精品www一本| 日韩中文在线电影| 久久久久久夜| 欧美激情日韩| 国产精品欧美在线观看| 日韩三区四区| 亚洲精品日本| 亚洲资源网站| 免费在线看一区| 在线视频精品| 黄页网站一区| 久久久国产亚洲精品| 国产精品99在线观看| 美女高潮久久久| 免费日韩成人| 麻豆成人在线观看| 美女久久精品| 久久久国产精品入口麻豆| 国产精品sm| 国产精品久久久久久av公交车| 欧美日韩亚洲三区| 欧美三区不卡| 久久国产三级精品| 国产欧美一区二区色老头| 91精品丝袜国产高跟在线| 日韩av一级片| 日韩va欧美va亚洲va久久| 日韩精品中文字幕一区二区| 在线精品亚洲| 亚洲ww精品| 日本va欧美va精品发布| 日韩va亚洲va欧美va久久| 青青伊人久久| 国产精品久久久久9999高清| 久久99青青| 国产66精品| 亚洲精品一区三区三区在线观看| 日韩精品欧美| 91精品电影| 亚洲一区二区成人| 亚洲欧美网站在线观看| 亚洲tv在线| 国产精品一区二区三区美女| 久久免费视频66| 成人精品久久| 久久精品中文| 亚洲免费影院| 日韩av一区二区在线影视| 久久av免费看| 成人羞羞在线观看网站| 亚洲经典在线| 亚洲人妖在线| 免费观看亚洲天堂| 亚洲精品在线影院| 亚洲成人精选| 日韩有码av| 国产精品115| 国产精品xx| 婷婷六月综合| 午夜视频一区二区在线观看| 国产精品蜜月aⅴ在线| 97在线精品| 亚洲欧洲另类| 69堂精品视频在线播放| 精品亚洲二区| 精品91久久久久| 欧美日韩亚洲三区| 久久影院午夜精品| 国产亚洲在线观看| 国产精品66| 婷婷综合在线| 91精品福利观看| 成人黄色av| 久久国产高清| 久久久久久亚洲精品美女| 亚洲特级毛片| 欧美亚洲综合视频| 欧美亚洲国产精品久久| 香蕉久久夜色精品国产| 国产黄色精品| 伊人精品视频| 久久这里只有| 丝袜美腿亚洲一区二区图片| 日本欧美一区| 日本а中文在线天堂| 亚洲一区二区三区四区电影 | 中文一区一区三区免费在线观| 欧美国产另类| 亚洲一区二区动漫| 国产成人精品一区二区免费看京| 丝袜a∨在线一区二区三区不卡| 国产激情久久| 亚洲综合国产| 国产一区二区三区91| 在线亚洲激情| 麻豆国产欧美一区二区三区| 午夜久久黄色| 欧美国产不卡| 中文在线日韩| 日韩高清不卡| 亚洲一区二区日韩| zzzwww在线看片免费| 婷婷视频一区二区三区| 国产suv精品一区| 日本中文字幕视频一区| 99精品在线观看| 国产精品宾馆|