Apache 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
に上記4つのクラスが設定されています。ConnectTimeoutException
は InterruptedIOException
のサブクラスなので、retryRequest
は false
を返すことになります。
したがって、ハンドラを設定していない HttpClient
では、コネクションタイムアウトのときにリトライしません。
- 1.5.3. Automatic exception recovery
- 1.5.4. Request retry handler