読者です 読者をやめる 読者になる 読者になる

Apache HttpClient の DefaultHttpRequestRetryHandler は ConnectTimeoutException のときはリトライしない

Java

すべてドキュメントに書かれてるんですが、HttpClient はデフォルトで3回リトライする機能を持っています。しかし、コネクションタイムアウト (ConnectTimeoutException) のときはリトライしません。そのあたりを調べたときのメモ。

※以下は Apache HttpClient 4.4.1 で調べています。

HttpClientBuilder#setRetryHandler でハンドラを設定せずに HttpClient を生成すると、デフォルトで DefaultHttpRequestRetryHandler が使われます。
以下、HttpClientBuilder#build から抜粋。

if (!automaticRetriesDisabled) { // automaticRetriesDisabled は デフォルトで false
    HttpRequestRetryHandler retryHandlerCopy = this.retryHandler;
    if (retryHandlerCopy == null) {
        retryHandlerCopy = DefaultHttpRequestRetryHandler.INSTANCE; // INSTANCE は new DefaultHttpRequestRetryHandler() で初期化されている
    }
    execChain = new RetryExec(execChain, retryHandlerCopy);
}

で、DefaultHttpRequestRetryHandler のドキュメントには以下のように記載されています。

DefaultHttpRequestRetryHandler (Apache HttpClient 4.4.1 API)

Create the request retry handler with a retry count of 3, requestSentRetryEnabled false and using the following list of non-retriable IOException classes: InterruptedIOException, UnknownHostException, ConnectException, SSLException

最初、ここの non-retriable を non-retrieval と読み間違えて、全然見当違いな解釈をしていたことは内緒ですが、デフォルトコンストラクタを呼び出すと、リトライ不可能な IOException のクラスとして InterruptedIOException, UnknownHostException, ConnectException, SSLException が設定される、と書いてあります。

以下、リトライ処理の箇所、DefaultHttpRequestRetryHandler#retryRequest から抜粋。

if (this.nonRetriableClasses.contains(exception.getClass())) {
    return false;
} else {
    for (final Class<? extends IOException> rejectException : this.nonRetriableClasses) {
        if (rejectException.isInstance(exception)) {
            return false;
        }
    }
}

この this.nonRetriableClasses に InterruptedIOException, UnknownHostException, ConnectException, SSLException が設定されます。ConnectTimeoutException は InterruptedIOException のサブクラスなので、retryRequest は false を返すことになります。

したがって、コネクションタイムアウトの場合、HttpClient はリトライしません。

(参考) Chapter 1. Fundamentals

  • 1.5.3. Automatic exception recovery
  • 1.5.4. Request retry handler