Eas*_*Ans 7 java spring httpconnection resttemplate
我正在尝试配置外部Web服务调用时的超时.我在我的服务中通过Spring Rest Template调用外部Web服务.
对于连接超时测试目的,外部Web服务已停止,应用程序服务器已关闭.
我已经为超时配置了10秒,但不幸的是我在一秒钟之后得到连接拒绝异常.
try {
final RestTemplate restTemplate = new RestTemplate();
((org.springframework.http.client.SimpleClientHttpRequestFactory)
restTemplate.getRequestFactory()).setReadTimeout(1000*10);
((org.springframework.http.client.SimpleClientHttpRequestFactory)
restTemplate.getRequestFactory()).setConnectTimeout(1000*10);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(reqJSON, headers);
ResponseEntity<String> response = restTemplate.exchange(wsURI, HttpMethod.POST, entity, String.class);
String premiumRespJSONStr = response.getBody();
}
Run Code Online (Sandbox Code Playgroud)
请更正我的理解.
and*_*eim 25
以下与connectTimeout设置有关.
案例 - 未知主持人
如果您的主机无法访问(例如:),http://blablablabla/v1/timeout那么您将UnknownHostException尽快收到.AbstractPlainSocketImpl :: connect() :: !addr.isUnresolved() :: throw UnknownHostException没有任何超时.主机使用解析InetAddress.getByName(<host_name>).
案例 - 未知端口
如果你有一台主机可到达的,但没有连接可以做到,那么你收到ConnectException- Connection refused: connect尽快.似乎这发生在DualStackPlainSocketImpl :: static native void waitForConnect(int fd, int timeout) throws IOException从中调用的本机方法中DualStackPlainSocketImpl :: socketConnect().超时未得到遵守.
代理?如果使用代理,事情可能会改变.拥有可访问的代理可能会导致超时.
相关问题请查看与您遇到的案例相关的答案.
具有映射到多个IP地址的相同域的DNS Round-Robin将导致客户端连接到每个IP,直到找到一个IP.因此,connectTimeout()将为列表中不起作用的每个IP添加自己的惩罚.阅读本文了解更多信息.
结论如果你想获得connectTimeout那么你可能需要实现自己的重试逻辑或使用代理.
测试connectTimeout你可以参考这个答案的各种方法,有一个端点,防止套接字连接完成,从而获得超时.选择解决方案,您可以在spring-boot中创建集成测试,以验证您的实现.这可以类似于用于测试的下一个测试readTimeout,只是在这种情况下,URL可以更改为防止套接字连接的URL.
测试 readTimeout
为了测试readTimeout首先需要连接,因此需要启动服务.然后,可以提供端点,对于每个请求,返回具有大延迟的响应.
可以在spring-boot中完成以下操作以创建集成测试:
1.创建测试
@RunWith(SpringRunner.class)
@SpringBootTest(
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
classes = { RestTemplateTimeoutConfig.class, RestTemplateTimeoutApplication.class }
)
public class RestTemplateTimeoutTests {
@Autowired
private RestOperations restTemplate;
@LocalServerPort
private int port;
@Test
public void resttemplate_when_path_exists_and_the_request_takes_too_long_throws_exception() {
System.out.format("%s - %s\n", Thread.currentThread().getName(), Thread.currentThread().getId());
Throwable throwable = catchThrowable(() ->
restTemplate.getForEntity(String.format("http://localhost:%d/v1/timeout", port), String.class));
assertThat(throwable).isInstanceOf(ResourceAccessException.class);
assertThat(throwable).hasCauseInstanceOf(SocketTimeoutException.class);
}
}
Run Code Online (Sandbox Code Playgroud)
2.配置RestTemplate
@Configuration
public class RestTemplateTimeoutConfig {
private final int TIMEOUT = (int) TimeUnit.SECONDS.toMillis(10);
@Bean
public RestTemplate restTemplate() {
return new RestTemplate(getRequestFactory());
}
private ClientHttpRequestFactory getRequestFactory() {
HttpComponentsClientHttpRequestFactory factory =
new HttpComponentsClientHttpRequestFactory();
factory.setReadTimeout(TIMEOUT);
factory.setConnectTimeout(TIMEOUT);
factory.setConnectionRequestTimeout(TIMEOUT);
return factory;
}
}
Run Code Online (Sandbox Code Playgroud)
3.测试开始时将运行的Spring Boot应用程序
@SpringBootApplication
@Controller
@RequestMapping("/v1/timeout")
public class RestTemplateTimeoutApplication {
public static void main(String[] args) {
SpringApplication.run(RestTemplateTimeoutApplication.class, args);
}
@GetMapping()
public @ResponseStatus(HttpStatus.NO_CONTENT) void getDelayedResponse() throws InterruptedException {
System.out.format("Controller thread = %s - %s\n", Thread.currentThread().getName(), Thread.currentThread().getId());
Thread.sleep(20000);
}
}
Run Code Online (Sandbox Code Playgroud)
配置RestTemplate的其他方法
配置现有的RestTemplate
@Configuration
public class RestTemplateTimeoutConfig {
private final int TIMEOUT = (int) TimeUnit.SECONDS.toMillis(10);
// consider that this is the existing RestTemplate
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
// this will change the RestTemplate settings and create another bean
@Bean
@Primary
public RestTemplate newRestTemplate(RestTemplate restTemplate) {
SimpleClientHttpRequestFactory factory =
(SimpleClientHttpRequestFactory) restTemplate.getRequestFactory();
factory.setReadTimeout(TIMEOUT);
factory.setConnectTimeout(TIMEOUT);
return restTemplate;
}
}
Run Code Online (Sandbox Code Playgroud)
使用RequestConfig配置新的RestTemplate
@Configuration
public class RestTemplateTimeoutConfig {
private final int TIMEOUT = (int) TimeUnit.SECONDS.toMillis(10);
@Bean
public RestTemplate restTemplate() {
return new RestTemplate(getRequestFactoryAdvanced());
}
private ClientHttpRequestFactory getRequestFactoryAdvanced() {
RequestConfig config = RequestConfig.custom()
.setSocketTimeout(TIMEOUT)
.setConnectTimeout(TIMEOUT)
.setConnectionRequestTimeout(TIMEOUT)
.build();
CloseableHttpClient client = HttpClientBuilder
.create()
.setDefaultRequestConfig(config)
.build();
return new HttpComponentsClientHttpRequestFactory(client);
}
}
Run Code Online (Sandbox Code Playgroud)
为什么不嘲讽使用MockRestServiceServer了RestTemplate,代替的要求工厂.因此,RestTemplate将替换任何设置.因此,使用真实应用程序进行超时测试可能是唯一的选择.
注意:还请查看本文关于RestTemplate配置的内容,其中还包括超时配置.
| 归档时间: |
|
| 查看次数: |
19975 次 |
| 最近记录: |