Webアプリケーションで使用されるRESTサービスの接続タイムアウトを設定したいと思います。 SpringのRestTemplateを使用してサービスと通信しています。私はいくつかの調査を行い、タイムアウトを設定することを意図していると信じている以下のxmlを見つけました(私のアプリケーションxmlで)。 Spring 3.0を使用しています。
ここでも同じ問題が見られました RestTemplateを使用したSpring Webサービスのタイムアウト構成 しかし、ソリューションはcleanとは思えません。 Spring config
<bean id="RestOperations" class="org.springframework.web.client.RestTemplate">
<constructor-arg>
<bean class="org.springframework.http.client.CommonsClientHttpRequestFactory">
<property name="readTimeout" value="${restURL.connectionTimeout}" />
</bean>
</constructor-arg>
</bean>
ReadTimeoutを次のように設定したように見えます:
ネットワークケーブルが切断されました:約20秒待機し、次の例外を報告します:
org.springframework.web.client.ResourceAccessException:I/Oエラー:ホストへのルートがありません:接続;ネストされた例外はJava.net.NoRouteToHostException:ホストへのルートなし:接続
URLが正しくないため、レストサービスから404が返されました:約10秒待機し、次の例外を報告します。
org.springframework.web.client.HttpClientErrorException:404 Not Found
要件により短いタイムアウトが必要なので、これらを変更できる必要があります。私が間違っていることに関するアイデアはありますか?
どうもありがとう。
私はついにこれを機能させました。
私たちのプロジェクトにはcommons-httpclient jarの2つの異なるバージョンがあったという事実は役に立たなかったと思います。それを整理したら、次の2つのことができることがわかりました...
コードには、次のものを含めることができます。
HttpComponentsClientHttpRequestFactory rf =
(HttpComponentsClientHttpRequestFactory) restTemplate.getRequestFactory();
rf.setReadTimeout(1 * 1000);
rf.setConnectTimeout(1 * 1000);
このコードが初めて呼び出されると、HttpComponentsClientHttpRequestFactory
によって使用されるRestTemplate
クラスのタイムアウトが設定されます。したがって、RestTemplate
によって行われる後続の呼び出しはすべて、上記で定義されたタイムアウト設定を使用します。
または、より良いオプションはこれを行うことです:
<bean id="RestOperations" class="org.springframework.web.client.RestTemplate">
<constructor-arg>
<bean class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory">
<property name="readTimeout" value="${application.urlReadTimeout}" />
<property name="connectTimeout" value="${application.urlConnectionTimeout}" />
</bean>
</constructor-arg>
</bean>
コードでRestOperations
インターフェイスを使用し、プロパティファイルからタイムアウト値を取得します。
Spring Boot> = 1.4の場合
@Configuration
public class AppConfig
{
@Bean
public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder)
{
return restTemplateBuilder
.setConnectTimeout(...)
.setReadTimeout(...)
.build();
}
}
Spring Boot <= 1.の場合
@Configuration
public class AppConfig
{
@Bean
@ConfigurationProperties(prefix = "custom.rest.connection")
public HttpComponentsClientHttpRequestFactory customHttpRequestFactory()
{
return new HttpComponentsClientHttpRequestFactory();
}
@Bean
public RestTemplate customRestTemplate()
{
return new RestTemplate(customHttpRequestFactory());
}
}
その後、application.properties
custom.rest.connection.connection-request-timeout=...
custom.rest.connection.connect-timeout=...
custom.rest.connection.read-timeout=...
これは、HttpComponentsClientHttpRequestFactory
にパブリックセッターconnectionRequestTimeout
、connectTimeout
、およびreadTimeout
および@ConfigurationProperties
が設定されているために機能します。
Spring 4.1またはSpring BootなしのSpring 5XML
の代わりに@Configuration
を使用
@Configuration
public class AppConfig
{
@Bean
public RestTemplate customRestTemplate()
{
HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
httpRequestFactory.setConnectionRequestTimeout(...);
httpRequestFactory.setConnectTimeout(...);
httpRequestFactory.setReadTimeout(...);
return new RestTemplate(httpRequestFactory);
}
}
この質問は、Spring Bootの検索の最初のリンクです。したがって、ここに 公式ドキュメントで推奨されている解決策 を入れるとよいでしょう。 Spring Bootには独自の便利なBeanがあります RestTemplateBuilder :
@Bean
public RestTemplate restTemplate(
RestTemplateBuilder restTemplateBuilder) {
return restTemplateBuilder
.setConnectTimeout(500)
.setReadTimeout(500)
.build();
}
RestTemplateインスタンスの手動作成は、他の自動構成されたBeanが手動で作成されたインスタンスに挿入されないため、面倒なアプローチになる可能性があります。
タイムアウトを設定する非常に簡単な方法を次に示します。
RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory());
private ClientHttpRequestFactory getClientHttpRequestFactory() {
int timeout = 5000;
HttpComponentsClientHttpRequestFactory clientHttpRequestFactory =
new HttpComponentsClientHttpRequestFactory();
clientHttpRequestFactory.setConnectTimeout(timeout);
return clientHttpRequestFactory;
}
これが私の2セントです。新しいものはありませんが、いくつかの説明、改善、新しいコードがあります。
デフォルトでは、RestTemplate
のタイムアウトは無限です。タイムアウトには、接続タイムアウトと読み取りタイムアウトの2種類があります。たとえば、サーバーに接続できましたが、データを読み取ることができませんでした。アプリケーションがハングしていて、何が起こっているのかわからない。
アノテーションを使用します。アノテーションは最近ではXMLよりも好まれています。
@Configuration
public class AppConfig {
@Bean
public RestTemplate restTemplate() {
var factory = new SimpleClientHttpRequestFactory();
factory.setConnectTimeout(3000);
factory.setReadTimeout(3000);
return new RestTemplate(factory);
}
}
ここでは、SimpleClientHttpRequestFactory
を使用して接続を設定し、タイムアウトを読み取ります。その後、RestTemplate
のコンストラクターに渡されます。
@Configuration
public class AppConfig {
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder
.setConnectTimeout(Duration.ofMillis(3000))
.setReadTimeout(Duration.ofMillis(3000))
.build();
}
}
2番目のソリューションでは、RestTemplateBuilder
を使用します。また、2つのメソッドのパラメーターに注意してください:それらはDuration
を取ります。直接ミリ秒かかるオーバーロードメソッドは廃止されました。
編集 Spring Boot 2.1.0およびJava 11.でテスト済み.
同様のシナリオがありましたが、プロキシを設定する必要もありました。これを行うための最も簡単な方法は、プロキシの設定を容易にするためにSimpleClientHttpRequestFactory
を拡張することでした(非prodとprodで異なるプロキシ)。ただし、プロキシを必要としない場合でも、これは機能するはずです。次に、拡張クラスで source と同じものを使用してopenConnection(URL url, Proxy proxy)
メソッドをオーバーライドしますが、戻る前にタイムアウトを設定するだけです。
@Override
protected HttpURLConnection openConnection(URL url, Proxy proxy) throws IOException {
URLConnection urlConnection = proxy != null ? url.openConnection(proxy) : url.openConnection();
Assert.isInstanceOf(HttpURLConnection.class, urlConnection);
urlConnection.setConnectTimeout(5000);
urlConnection.setReadTimeout(5000);
return (HttpURLConnection) urlConnection;
}