天天看點

RestClient的TimeOut和Can't assign requested address問題排查及解決RestClient的TimeOut和Can’t assign requested address問題排查及解決

RestClient的TimeOut和Can’t assign requested address問題排查及解決

問題背景

TimeOut問題

在項目中用到了es,因為請求比較簡單,是以使用了官方提供的Elasticsearch Java Low Level REST Client作為用戶端,但在最近優化es操作的過程中,使用了并行操作+異步請求的方式,在請求數量較大時,performRequestAsync方法的失敗回調中報錯:TimeOut,第一反應是連接配接逾時,但經過斷點調試,連接配接并沒有異常,在github上client項目的iisue中找到了原因,RestClient内部使用了連接配接池,在請求連接配接逾時時會報錯,是以TimeOut并不是連接配接逾時,而是連接配接池逾時的異常,通過在初始化client時設定參數為0的方式,可以關閉連接配接池逾時機制。如下所示。

RestClient restClient = RestClient.builder( )
  .setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() {
                @Override
                public RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder requestConfigBuilder) {
                    requestConfigBuilder.setConnectTimeout(3000); // 連接配接逾時
                    requestConfigBuilder.setSocketTimeout(4000); // 資料請求逾時
                    requestConfigBuilder.setConnectionRequestTimeout(0); // 連接配接池逾時設定
                    return requestConfigBuilder;
                }
            }).setMaxRetryTimeoutMillis(5*60*1000).build();
           

Can’t assign requested addres問題

TIME_WAIT狀态

解決了連接配接逾時的問題,再次運作時,發現同一時間的請求數量較大時,又抛出了Can’t assign requested addres的異常,經過查閱,這個異常一般會在無可用端口時出現。在httpClient中出現這個異常一般是因為連接配接不是長連接配接,是以不斷地斷開重連,但關閉連接配接需要時間,是以在并發時出現無可用端口。我記得官方文檔中提到了RestClient預設是長連接配接,但以防萬一,在請求參數中加入了keepalive選項,結果問題不再出現,看來RestClient中預設并不是長連接配接。此處還需要繼續考證。

private static final RequestOptions COMMON_OPTIONS;

    static {
        RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
        builder.addHeader("Connection", "keepalive");
        COMMON_OPTIONS = builder.build();
    }