摘要:在使用過程中,我們可以使用注解可以方便的實現定時任務。默認單線程經排查后發現,我們使用注解默認的配置的話,所有的任務都是單線程去跑的。參數其實代表了每個路由的最大連接數。怪不得當時在高并發情況下總會出現超時,明明已經設的很高。
前言
本文主要給大家介紹了關于Spring中@Scheduled和HttpClient的坑,分享出來供大家參考學習,下面話不多說了,來一起看看詳細的介紹吧。
曾經踩過一個大坑:
由于業務特殊性,會定時跑很多定時任務,對業務數據進行補償操作等。
在Spring使用過程中,我們可以使用@Scheduled注解可以方便的實現定時任務。
有一天早上突然發現,從前一天晚上某一時刻開始,所有的定時任務全部都卡死不再運行了。
@Scheduled默認單線程
經排查后發現,我們使用@Scheduled注解默認的配置的話,所有的任務都是單線程去跑的。寫了一個測試的task讓它sleep住,就很容易發現,其他所有的task在時間到的時候都沒有觸發。
如果需要開啟多線程處理,則需要進行如下的配置,設置一下線程數:
@Configuration public class ScheduleConfig implements SchedulingConfigurer { @Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { taskRegistrar.setScheduler(Executors.newScheduledThreadPool(5)); } }
這樣就解決了如果一個task卡住,會引起所有task全部卡住的問題。
但是為什么會有task卡住呢?
HttpClient默認參數配置
原來,有些task會定時請求外部服務的restful接口,而HttpClient的配置如下:
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(); connManager.setMaxTotal(maxConnection); httpClient = HttpClients.custom() .setConnectionManager(connManager) .build();
在最開始使用HttpClient的時候,根本沒有想這么多,基本也都是用用默認配置。
追蹤源碼可以發現,在使用上述方式進行配置的時候,HttpClient的timeout時間竟然全部都是-1,也就是說如果對方服務有問題,HttpClient的請求會永不超時,一直等待。源碼如下:
Builder() { super(); this.staleConnectionCheckEnabled = false; this.redirectsEnabled = true; this.maxRedirects = 50; this.relativeRedirectsAllowed = true; this.authenticationEnabled = true; this.connectionRequestTimeout = -1; this.connectTimeout = -1; this.socketTimeout = -1; this.contentCompressionEnabled = true; }
所以我們這時候必須手動指定timeout時間,問題就解決了。例如:
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(); connManager.setMaxTotal(maxConnection); RequestConfig defaultRequestConfig = RequestConfig.custom() .setSocketTimeout(3000) .setConnectTimeout(3000) .setConnectionRequestTimeout(3000) .build(); httpClient = HttpClients.custom() .setDefaultRequestConfig(defaultRequestConfig) .setConnectionManager(connManager) .build();
聯想到另一個問題
其實HttpClient的使用過程中也遇到過另外一個配置的問題,就是defaultMaxPerRoute這個參數。
最開始使用的時候也沒有注意過這個參數,只是設置過連接池的最大連接數maxTotal。
defaultMaxPerRoute參數其實代表了每個路由的最大連接數。比如你的系統需要訪問另外兩個服務:google.com 和 bing.com。如果你的maxTotal設置了100,而defaultMaxPerRoute設置了50,那么你的每一個服務的最大請求數最大只能是50。
那么如果defaultMaxPerRoute沒有設置呢,追蹤源碼:
public PoolingHttpClientConnectionManager( final HttpClientConnectionOperator httpClientConnectionOperator, final HttpConnectionFactoryconnFactory, final long timeToLive, final TimeUnit tunit) { super(); this.configData = new ConfigData(); //這里使用的CPool構造方法,第二個參數即為defaultMaxPerRoute,也就是默認為2。 this.pool = new CPool(new InternalConnectionFactory( this.configData, connFactory), 2, 20, timeToLive, tunit); this.pool.setValidateAfterInactivity(2000); this.connectionOperator = Args.notNull(httpClientConnectionOperator, "HttpClientConnectionOperator"); this.isShutDown = new AtomicBoolean(false); }
這里發現,原來默認值竟然只有2。怪不得當時在高并發情況下總會出現超時,明明maxTotal已經設的很高。
所以如果你的服務訪問很多不同的外部服務,并且并發量比較大,一定要好好配置maxTotal和defaultMaxPerRoute兩個參數。
所以后來再使用任何新的東西,都有好好看下都什么配置,有疑問的一定要先查一下,不要網上copy一段代碼直接就用。當時可能沒問題,但是以后沒準就被坑了。
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/74399.html
摘要:前言在使用整合定時任務,發現當某個定時任務執行出現執行時間過長的情況時會阻塞其他定時任務的執行。問題定位后續通過翻查的文檔以及打印日志輸出當前線程信息得知問題是由于默認使用只要個線程處理定時任務。問題復盤需要注意示例的版本為。 前言 在使用Springboot整合定時任務,發現當某個定時任務執行出現執行時間過長的情況時會阻塞其他定時任務的執行。 問題定位 后續通過翻查Springboo...
摘要:表示起始時間開始觸發,然后每隔固定時間觸發一次如在域使用則意味著分鐘觸發一次,而,等分別觸發一次表示列出枚舉值值。 showImg(https://segmentfault.com/img/remote/1460000015852353); 文章鏈接:https://liuyueyi.github.io/hexblog/2018/08/01/180801-Spring之定時任務基本使用...
摘要:也是自帶的一個基于線程池設計的定時任務類。其每個調度任務都會分配到線程池中的一個線程執行,所以其任務是并發執行的,互不影響。 原創不易,如需轉載,請注明出處https://www.cnblogs.com/baixianlong/p/10659045.html,否則將追究法律責任!!! 一、在JAVA開發領域,目前可以通過以下幾種方式進行定時任務 1、單機部署模式 Timer:jdk中...
摘要:多線程并發定時任務剛剛看了下實現定時任務的文章,感覺還不錯。存在問題但是后來發現個問題,通過同時測試幾個任務發現,所有的任務都是在同一個線程池中的同一個線程來完成的。 spring-boot | 多線程并發定時任務 剛剛看了下Spring Boot實現定時任務的文章,感覺還不錯。Spring Boot 使用Spring自帶的Schedule來實現定時任務變得非常簡單和方便。在這里個大家...
閱讀 1368·2021-09-13 10:25
閱讀 552·2019-08-30 15:53
閱讀 2265·2019-08-30 15:44
閱讀 2026·2019-08-29 17:20
閱讀 1594·2019-08-29 16:36
閱讀 1795·2019-08-29 14:10
閱讀 1785·2019-08-29 12:44
閱讀 1166·2019-08-23 14:13