我有一个可重试的 REST 调用,它会在特定情况下重试。目前,它甚至在读取超时和连接超时情况下也会重试。
@Retryable(value = {RestClientException.class},maxAttempts = 2,
exclude = {HttpClientErrorException.BadRequest.class})
public ResponseEntity<String> testMethod() throws Exception {
return restTemplateRtp.exchange("http://localhost:8080/api/test", HttpMethod.POST, request, String.class);
}
在读取超时的情况下,重试重试2次,然后失败并出现此异常:
org.springframework.web.client.ResourceAccessException: I/O error
on POST request for "http://localhost:8080/api/test": Read timed
out; nested exception is java.net.SocketTimeoutException: Read timed out
我不想重试读取超时,但希望重试继续连接超时。当我尝试在
SocketTimeoutException
中添加exclude
时,它仍在重试读取超时。
如何处理这种情况?我无法将
ResourceAccessException
添加到 exclude
,然后读取和连接超时都将停止重试。
从异常堆栈跟踪我可以说
ResourceAccessException
是由于底层java.net.SocketTimeoutException
而抛出的顶级异常。
并且,从 java-docs 套接字超时将在多个用例上抛出
在套接字读取或接受时发生超时的信号。
如果建议添加自定义逻辑以排除任何潜在异常
@Retryable(value = {RestClientException.class},maxAttempts = 2,
exclude = {HttpClientErrorException.BadRequest.class})
public ResponseEntity<String> testMethod() throws Exception {
try {
return restTemplateRtp.exchange("http://localhost:8080/api/test", HttpMethod.POST, request, String.class);
}catch(ResourceAccessException ex) {
if(ex.getCause() instanceOf java.net.SocketTimeoutException
&& ex.getCause().getMessage().equals("Read timed out")) {
//exclude don't retry and return something
}
// else throw ex;
}
}
}
增加一些超时处理逻辑:
@Retryable(value = {RestClientException.class},maxAttempts = 2,
exclude = {HttpClientErrorException.BadRequest.class})
public ResponseEntity<String> testMethod() throws Exception {
try {
return restTemplateRtp.exchange("http://localhost:8080/api/test", HttpMethod.POST, request, String.class);
} catch (Exception e) {
// when timed out, what to do
}
}