記録の再試行タイムアウトのHTTPClient

背景

オンラインサービスは、第三者に依存して、インターフェイスRTトラフィックは、応答時間に大きく、非常に長いです。以来、各タイムアウトパラメータが5秒に設定されています。

PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
// 连接池最大的连接数
connManager.setMaxTotal(6000);
// 单个路由的最大连接数,例如:www.baidu.com,图片最大高峰并发量520
connManager.setDefaultMaxPerRoute(500);

RequestConfig.Builder custom = RequestConfig.custom();
// 连接超时时间 建立连接时间 此前设置3000
custom.setConnectTimeout(800);
// 从connect Manager获取Connection 超时时间(连接池获取连接超时时间)
custom.setConnectionRequestTimeout(500);
// (获取response的返回时间)读取返回时间 此前设置40000,官方建议40s
custom.setSocketTimeout(1000);
RequestConfig config = custom.build();

// DefaultHttpRequestRetryHandler 重试策略(可自定义)
httpClient = HttpClients.custom().setRetryHandler(new DefaultHttpRequestRetryHandler(1, true)).setConnectionManager(connManager)
                .setDefaultRequestConfig(config).build();
复制代码

建設のHttpClient

あなたは、実行チェーンを指定しない場合、デバッグすることで、あなたは実行の将来のビルド方法を知ることができ、InternalHttpClientオブジェクトへのアクセスは、RetryExecアクチュエータを使用することで、デフォルトの再試行戦略はDefaultHttpRequestRetryHandlerです

public CloseableHttpClient build() {
    ... 省略部分代码
    // Add request retry executor, if not disabled
    if (!automaticRetriesDisabled) {
        HttpRequestRetryHandler retryHandlerCopy = this.retryHandler;
        if (retryHandlerCopy == null) {
            retryHandlerCopy = DefaultHttpRequestRetryHandler.INSTANCE;
        }
        execChain = new RetryExec(execChain, retryHandlerCopy);
    }
    ... 省略部分代码
}
复制代码

タイムアウトパラメータ

三次元の設定タイムアウト

  • 接続タイムアウトsetConnectTimeout
  • 読み取りタイムアウトsetSocketTimeout
  • setConnectionRequestTimeoutタイムアウト接続プールから接続を取得します

ビジネス上の再試行戦略への影響

デフォルトが再試行戦略によって、または手動で変更または再定義再試行戦略が、いくつかのケースでは、それは再試行することができ、いくつかのケースを再試行することができ、失敗です。

再試行の分析

私たちのシナリオアプリケーションがポストを得るためには、次のように要約することができます。

のみInterruptedIOExceptionではリトライのみIOExecetionが発生した場合、UnknownHostExceptionが、発生でConnectException、SSLException、異常4リトライ方法は3回再試行を得ることができない、ソケットの出力ストリームを、対応するポスト方法が正常書き込み、フラッシュされないで、重量で生じ得ます3回をテストします。

例外を再試行しません。

  • InterruptedIOExceptionでは、例外割り込みスレッド
  • UnknownHostExceptionが、対応するホストを見つけます
  • でConnectException、ホスト、コネクションの確立に失敗しました
  • SSLException、HTTPS異常認証

DefaultHttpRequestRetryHandler再試行戦略

@Override
public boolean retryRequest(
        final IOException exception,
        final int executionCount,
        final HttpContext context) {
    Args.notNull(exception, "Exception parameter");
    Args.notNull(context, "HTTP context");
    if (executionCount > this.retryCount) {
        // Do not retry if over max retry count
        return false;
    }
    // 异常类是否在禁止重试中
    if (this.nonRetriableClasses.contains(exception.getClass())) {
        return false;
    } else {
        for (final Class<? extends IOException> rejectException : this.nonRetriableClasses) {
            if (rejectException.isInstance(exception)) {
                return false;
            }
        }
    }
    final HttpClientContext clientContext = HttpClientContext.adapt(context);
    final HttpRequest request = clientContext.getRequest();

    if(requestIsAborted(request)){
        return false;
    }

    if (handleAsIdempotent(request)) {
        // Retry if the request is considered idempotent
        return true;
    }

    // 根据上下文判断请求是否发送成功了,或者根据状态为是否永远可以重复发送(默认的是否) requestSentRetryEnabled 参数可以在构建httpCLient对象设置重试策略指定此属性
    // isRequestSent 是在HttpRequestExecutor中doSendRequest方法中flush成功设置context.setAttribute("http.request_sent", Boolean.TRUE);
    if (!clientContext.isRequestSent() || this.requestSentRetryEnabled) {
        // Retry if the request has not been sent fully or
        // if it's OK to retry methods that have been sent
        return true;
    }
    // otherwise do not retry
    return false;
}

// 几种类型的异常不重试,同时判断是否与异常类型的子类,是子类的话,也不重试
复制代码

さらに2つのタイムアウト、接続タイムアウトでは、タイムアウトを読む:java.net.SocketTimeoutException:2回のタイムアウトが上記第一種の割り込みスレッドに属する、InterruptedIOExceptionではから継承されてSocketTimeoutExceptionを、あるタイムアウトし、接続:読み取りjava.net.SocketTimeoutExceptionをタイムアウトしました例外は、再試行されません。

れる状況を再試行します

出力ストリームに書き込み要求とポストフラッシュ、ときに、IOExecetion InterruptedIOExceptionでは、UnknownHostExceptionが、でConnectException、SSLExceptionが発生することに加えています。

それはおそらくあなただけwirte方法を見ることができるように内部であなたは、その操作の対象がSocketOutputStream知っている、そしてこのクラスは達成空で洗い流すことができ、)ステップHttpClientConnection.flush(で間違ったステップを行くことができます。

再試行のパラメータrequestSentRetryEnabled http.request_sent

//根据上下文判断请求是否发送成功了,或者根据状态为是否永远可以重复发送(默认的是否)
if (!clientContext.isRequestSent() || this.requestSentRetryEnabled) {
    return true;
}
复制代码

再試行を禁止

HTTPClientのいくつかのシナリオのデフォルトの再試行戦略が提供する、私たちは近く、リトライ戦略を手動ですることができます。HttpClientBuilder、RetryExecアクチュエータをビルド()メソッドを選んだされ、すなわち事前条件、禁止ないマニュアルあります。

// Add request retry executor, if not disabled
if (!automaticRetriesDisabled) {
    HttpRequestRetryHandler retryHandlerCopy = this.retryHandler;
    if (retryHandlerCopy == null) {
        retryHandlerCopy = DefaultHttpRequestRetryHandler.INSTANCE;
    }
    execChain = new RetryExec(execChain, retryHandlerCopy);
}
复制代码

参照

blog.csdn.net/gaohe7091/a...

おすすめ

転載: juejin.im/post/5dc37b6fe51d456e34358a58