国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > Java > 正文

Spring中@Scheduled和HttpClient的連環坑

2024-07-14 08:39:54
字體:
來源:轉載
供稿:網友

前言

本文主要給大家介紹了關于Spring中@Scheduled和HttpClient的坑,分享出來供大家參考學習,下面話不多說了,來一起看看詳細的介紹吧。

曾經踩過一個大坑:

由于業務特殊性,會定時跑很多定時任務,對業務數據進行補償操作等。

在Spring使用過程中,我們可以使用@Scheduled注解可以方便的實現定時任務。

有一天早上突然發現,從前一天晚上某一時刻開始,所有的定時任務全部都卡死不再運行了。

@Scheduled默認單線程

經排查后發現,我們使用@Scheduled注解默認的配置的話,所有的任務都是單線程去跑的。寫了一個測試的task讓它sleep住,就很容易發現,其他所有的task在時間到的時候都沒有觸發。

如果需要開啟多線程處理,則需要進行如下的配置,設置一下線程數:

@Configurationpublic 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 HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connFactory,  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一段代碼直接就用。當時可能沒問題,但是以后沒準就被坑了。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VeVb武林網的支持。


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 太和县| 曲麻莱县| 驻马店市| 建始县| 肇庆市| 昭苏县| 陕西省| 鱼台县| 磴口县| 宜城市| 石柱| 绥德县| 庆城县| 武功县| 那坡县| 沂源县| 株洲县| 满洲里市| 泽普县| 太和县| 崇仁县| 阆中市| 军事| 龙州县| 沅陵县| 渝中区| 巴青县| 金昌市| 北海市| 尼木县| 马关县| 岳阳市| 南投县| 贵德县| 孟州市| 治多县| 景洪市| 射洪县| 施甸县| 景洪市| 东阳市|