RestClientにおける接続・読み取りタイムアウト設定方法
Spring Framework 6.1で導入されたRestClient
で接続タイムアウトと読み取りタイムアウトを設定する主要な方法を、具体的なコード例とともに解説します。最新のSpringプラクティスに基づいた推奨アプローチから、注意すべきポイントまで網羅します。
問題の本質
REST API呼び出し時にネットワーク障害や応答遅延が発生すると、システム全体のパフォーマンスや信頼性が低下します。RestClient
ではデフォルトでタイムアウトが無限に設定されているため、明示的な設定が必須です。
推奨解決策:ClientHttpRequestFactorySettingsの活用
Spring 6.1以降で推奨される方法です。タイムアウト設定とSSL/TLS設定を統合して安全に扱えます。
import org.springframework.http.client.*;
import org.springframework.web.client.RestClient;
import io.netty.channel.ChannelOption;
import org.springframework.boot.ssl.SslBundles;
import java.time.Duration;
@Bean
public RestClient restClient(SslBundles sslBundles) {
// タイムアウト設定作成(接続:30秒, 読み取り:30秒)
ClientHttpRequestFactorySettings settings = ClientHttpRequestFactorySettings.DEFAULTS
.withConnectTimeout(Duration.ofSeconds(30))
.withReadTimeout(Duration.ofSeconds(30))
.withSslBundle(sslBundles.getBundle("mybundle")); // SSL設定
// RestClientビルダーで設定適用
return RestClient.builder()
.requestFactory(ClientHttpRequestFactories.get(settings))
.build();
}
ベストプラクティス
- SSL設定との連携:
withSslBundle()
で証明書管理を分離可能 - Duration型による設定: 時間単位を明確化(ミリ秒より可読性向上)
- Bean管理: Springコンテナによるライフサイクル管理
代替手法:SimpleClientHttpRequestFactory
シンプルなケースで簡易的に使用できる方法ですが、SSL設定と組み合わせる際は注意が必要です。
private ClientHttpRequestFactory createTimeoutFactory() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setConnectTimeout(5000); // 5秒
factory.setReadTimeout(10000); // 10秒
return factory;
}
public RestClient createRestClient() {
return RestClient.builder()
.requestFactory(createTimeoutFactory())
.build();
}
注意点
SSL設定競合リスク: apply()
でSSL設定を追加すると、既存のRequestFactoryが上書きされタイムアウト設定が失われます。
// 危険なパターン(タイムアウト設定が消える)
builder.apply(restClientSsl.fromBundle("myBundle"));
HttpClient(詳細制御が必要な場合)
高度なネットワーク設定が必要なケースでは、Apache HttpClientを直接制御します。
import org.apache.hc.client5.http.config.*;
import org.apache.hc.core5.util.Timeout;
private ClientHttpRequestFactory createAdvancedFactory() {
// 接続プール設定
PoolingHttpClientConnectionManager manager =
new PoolingHttpClientConnectionManager();
manager.setMaxTotal(100);
// タイムアウト設定
RequestConfig config = RequestConfig.custom()
.setConnectTimeout(Timeout.ofSeconds(5))
.setConnectionRequestTimeout(Timeout.ofSeconds(3))
.build();
CloseableHttpClient client = HttpClientBuilder.create()
.setConnectionManager(manager)
.setDefaultRequestConfig(config)
.build();
return new HttpComponentsClientHttpRequestFactory(client);
}
SSL設定時の正しい統合方法
SSLバンドルを使用中にタイムアウトを維持するには、設定オブジェクトを一元管理します。
ClientHttpRequestFactorySettings settings = ClientHttpRequestFactorySettings.DEFAULTS
.withConnectTimeout(Duration.ofMillis(30000))
.withReadTimeout(Duration.ofMillis(30000))
.withSslBundle(sslBundles.getBundle("myBundle")); // SSL統合
// 設定をまとめて適用
builder.requestFactory(ClientHttpRequestFactories.get(settings));
設定値の目安
- 接続タイムアウト: 通常3-10秒(ネットワーク品質に依存)
- 読み取りタイムアウト: APIのSLAに基づき30-60秒が主流
- 実運用必須: 未設定時のシステムハングを防ぐため本番環境では常時設定を推奨
各手法はアプリケーションの複雑性に応じて選択可能ですが、Spring 6.1+環境ではClientHttpRequestFactorySettings
を使用することで設定の整合性を確保できます。特にマイクロサービス環境では、適切なタイムアウト設定がシステム全体のレジリエンス向上に直結します。