就在昨天線上的X服務調用的Y服務須要上線,而後Y服務的ng路由作了改動。而後A服務的RestTemplate調用Y服務的某個接口開始報400!服務器
剛剛開始咱們覺得是ng路由配置的問題,由於咱們X服務並無作上線,以前也運行平穩,因此咱們就下意識的認爲應該是Ng配置的緣由。可是當Ng配置還原以後,問題並無解決,仍舊是400!併發
而後咱們直接在X服務器上用curl訪問Y服務的接口,訪問正常!因此排除X服務問題,那麼只有多是X服務出問題。可是X服務一直並無作上線呀,爲何ng作了改動就這樣了呢!curl
後面一直沒找到問題,無奈之下重啓了服務,問題再也不出現!高併發
整個自個人測試流程下來,其實基本能夠定位到是A服務的問題,雖然他並無作改動,可是確定是外部的環境致使了A服務某個地方出現了問題。隨後,咱們定位到了RestTemplate這個點!性能
瘋狂找問題中。。。。測試
loading。。。。ui
最後發現咱們是將RestTemplate設置成了單例,而後初始化的時候用了HttpComponentsClientHttpRequestFactory。用這個是爲了配置RestTemplate調用的時候的超時配置。編碼
這個時候問題就來了!url
HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
因爲我是這樣實例化HttpComponentsClientHttpRequestFactory,能夠看到源碼是:3d
由圖可知HttpComponentsClientHttpRequestFactory默認用的是HttpClient,而後他的一個構建工廠HttpClientBuilder有一個屬性是systemProperties。再看下面的源碼:
當systemProperties這個屬性爲true的時候,HttpClient保持長鏈接了,並且接下去他會使用默認一個重用策略DefaultClientConnectionReuseStrategy。。。
坑爹啊,留下悔恨的眼淚。。。。
因此也就是說當我使用默認的初始化HttpComponentsClientHttpRequestFactory的時候,他默認會使用HttpClient的長鏈接。此時若是一旦出現調不通的狀況,長鏈接在超時的時間內還會一直保持着鏈接,並且還會複用上一次錯誤的鏈接信息。所以咱們纔會後續一直是400的狀況,到咱們重啓以後,長鏈接所有重置,又恢復如初。
因此解決這個問題只要在初始化HttpComponentsClientHttpRequestFactory的時候,傳入自定義的HttpClient來實例HttpComponentsClientHttpRequestFactory,這樣他就不會默認使用HttpClient的長鏈接,問題便可解決!
HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
同時記得配置HttpClient最大鏈接數以及同路由併發數,防止高併發的時候RestTemplate的性能!
// 開始設置鏈接池 PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(); // 最大鏈接數 poolingHttpClientConnectionManager.setMaxTotal(maxTotal); // 同路由併發數 poolingHttpClientConnectionManager.setDefaultMaxPerRoute(maxPerRoute);、
當編碼的時候,必定要思考詳細,注意細節,要多看源碼!不要想固然的直接引用公共的方法或類,當使用的時候應該看看源碼,瞭解他的原理,是怎麼運行的,必要的配置是否配齊!
同時加入詳細全面的測試,如果詳細的自測,這個問題也是會顯露出來的!
今天記錄下來這個問題,時刻勉勵本身,細節必決定成敗!