如何使用 Spring RestTemplate 在 POST 请求上设置超时?

问题描述

我想在通过 Spring RestTemplate 发送 POST 请求的过程中设置超时。例如,如果请求没有在 X 秒内完成,无论什么原因,如果可能,我希望它抛出异常并停止执行/释放资源。

最初,我尝试使用 HttpComponentsClientHttpRequestFactory,但没有成功并降级为 SimpleClientHttpRequestFactory。现在我只想让它在所有情况下都与 SimpleClientHttpRequestFactory 一起工作,然后尝试更复杂的解决方案。

我有以下配置:

@Bean
public RestTemplate restTemplate() {
    SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
    requestFactory.setConnectTimeout(3_000);
    requestFactory.setReadTimeout(30_000);
    return new RestTemplate(requestFactory);
}

我的用法如下:

HttpHeaders headers = new HttpHeaders();
headers.set("Content-Type","text/xml;charset=UTF-8");
httpentity<String> requestEntity = new httpentity<>(xmlMsgAsstring,headers);
ResponseEntity<String> response = restTemplate.postForEntity(url,requestEntity,String.class);

我有一个目标服务器,目前无法访问,我有一堆 XML 消息需要 POST 到该服务器。使用上面的代码,对于大多数消息它按预期工作,它会在 30 秒后抛出以下异常:

org.springframework.web.client.ResourceAccessException: I/O error on POST request for "http://X:Y/Z": Read timed out; nested exception is java.net.socketTimeoutException: Read timed out
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:744)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:670)
    at org.springframework.web.client.RestTemplate.postForEntity(RestTemplate.java:445)
    ...
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.net.socketTimeoutException: Read timed out
    at java.net.socketInputStream.socketRead0(Native Method)
    at java.net.socketInputStream.socketRead(SocketInputStream.java:116)
    at java.net.socketInputStream.read(SocketInputStream.java:171)
    at java.net.socketInputStream.read(SocketInputStream.java:141)
    at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
    at java.io.BufferedInputStream.read1(BufferedInputStream.java:286)
    at java.io.BufferedInputStream.read(BufferedInputStream.java:345)
    at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:735)
    at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:678)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1593)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1498)
    at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
    at org.springframework.http.client.SimpleClientHttpResponse.getRawStatusCode(SimpleClientHttpResponse.java:55)
    at org.springframework.web.client.DefaultResponseErrorHandler.hasError(DefaultResponseErrorHandler.java:55)
    at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:766)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:736)
    ... 18 common frames omitted

但是,对于一条特定的消息,它会卡住约 955 秒,然后抛出以下异常:

org.springframework.web.client.ResourceAccessException: I/O error on POST request for "http://X:Y/Z": Unexpected end of file from server; nested exception is java.net.socketException: Unexpected end of file from server
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:744)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:670)
    at org.springframework.web.client.RestTemplate.postForEntity(RestTemplate.java:445)
    ...
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.net.socketException: Unexpected end of file from server
    at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:851)
    at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:678)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1593)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1498)
    at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
    at org.springframework.http.client.SimpleClientHttpResponse.getRawStatusCode(SimpleClientHttpResponse.java:55)
    at org.springframework.web.client.DefaultResponseErrorHandler.hasError(DefaultResponseErrorHandler.java:55)
    at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:766)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:736)
    ... 26 common frames omitted

前一条30秒后成功抛出的消息和最后一条是类似的XML消息,目标相同。我想到的唯一区别是消息的大小,最后一个是~204KB,而以前的所有消息都小得多。为什么会出现最后一个异常,这种情况下如何设置时间限制?

在 Jetty 上运行的 Spring Boot 2.1.10

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...