외부기관 API를 호출할 때 응답에 대한 timeout을 설정해줘야했다
HttpClient 또는 Webclient를 생성할 때 설정해도 되지만,
우리는 API건마다 다른 timeout을 가져가야하기 때문에 호출 시점에 timeout을 설정하는 방법을 선택했다
두 가지 방법이 있는데 ..
1. HttpClientRequest
2. Reactor Core
webClient.get()
.uri("https://baeldung.com/path")
.httpRequest(httpRequest -> {
HttpClientRequest reactorRequest = httpRequest.getNativeRequest();
reactorRequest.responseTimeout(Duration.ofSeconds(2));
});
webClient.get()
.uri("https://baeldung.com/path")
.retrieve()
.bodyToFlux(JsonNode.class)
.timeout(Duration.ofSeconds(5));
@RequestMapping(value = "/timeout")
public ResponseEntity<?> timeout() throws InterruptedException {
log.info("timeout test");
Thread.sleep(5000);
log.info(LocalDateTime.now().toString());
return ResponseEntity.ok().build();
}
HttpClient httpClient = HttpClient.create();
WebClient client = WebClient.builder()
.baseUrl("http://localhost:8080")
.clientConnector(new ReactorClientHttpConnector(httpClient))
.filter(
(req, next) -> next.exchange(
ClientRequest.from(req).header("from", "webclient").build()
)
)
.filter(
ExchangeFilterFunction.ofRequestProcessor(
clientRequest -> {
log.info(">>>>>>>>>> REQUEST <<<<<<<<<<");
log.info("Request: {} {}", clientRequest.method(), clientRequest.url());
clientRequest.headers().forEach(
(name, values) -> values.forEach(value -> log.info("{} : {}", name, value))
);
return Mono.just(clientRequest);
}
)
)
.filter(
ExchangeFilterFunction.ofResponseProcessor(
clientResponse -> {
log.info(">>>>>>>>>> RESPONSE <<<<<<<<<<");
clientResponse.headers().asHttpHeaders().forEach((name, values) -> values.forEach(value -> log.info("{} : {}", name, value)));
return Mono.just(clientResponse);
}
)
)
.build();
// HttpClientRequest 사용
Mono<?> stringMono = client
.get()
.uri("/timeout")
.httpRequest(httpRequest -> {
HttpClientRequest reactorRequest = httpRequest.getNativeRequest();
reactorRequest.responseTimeout(Duration.ofSeconds(timeout));
})
.exchangeToMono(clientResponse -> {
log.info("Success!");
return clientResponse.toEntity(ResponseDto.class);
})
// Reactor Core 사용
Mono<?> stringMono = client
.get()
.uri("/timeout")
.exchangeToMono(clientResponse -> {
log.info("Success!");
return clientResponse.toEntity(ResponseDto.class);
})
.timeout(Duration.ofSeconds(timeout))
2023-10-08T16:13:41.130+09:00 INFO 79925 --- [nio-8080-exec-1] com.example.localtest.Controller : test
2023-10-08T16:13:41.130+09:00 INFO 79925 --- [nio-8080-exec-1] com.example.localtest.Controller : 2023-10-08T16:13:41.130468
2023-10-08T16:13:41.202+09:00 INFO 79925 --- [nio-8080-exec-1] com.example.localtest.Controller : >>>>>>>>>> REQUEST <<<<<<<<<<
2023-10-08T16:13:41.202+09:00 INFO 79925 --- [nio-8080-exec-1] com.example.localtest.Controller : Request: GET http://localhost:8080/timeout
2023-10-08T16:13:41.202+09:00 INFO 79925 --- [nio-8080-exec-1] com.example.localtest.Controller : from : webclient
2023-10-08T16:13:41.395+09:00 INFO 79925 --- [nio-8080-exec-2] com.example.localtest.Controller : timeout test
2023-10-08T16:13:46.401+09:00 INFO 79925 --- [nio-8080-exec-2] com.example.localtest.Controller : 2023-10-08T16:13:46.401034
2023-10-08T16:13:46.428+09:00 INFO 79925 --- [ctor-http-nio-2] com.example.localtest.Controller : >>>>>>>>>> RESPONSE <<<<<<<<<<
2023-10-08T16:13:46.431+09:00 INFO 79925 --- [ctor-http-nio-2] com.example.localtest.Controller : Date : Sun, 08 Oct 2023 07:13:46 GMT
2023-10-08T16:13:46.431+09:00 INFO 79925 --- [ctor-http-nio-2] com.example.localtest.Controller : content-length : 0
2023-10-08T16:13:46.431+09:00 INFO 79925 --- [ctor-http-nio-2] com.example.localtest.Controller : Success!
2023-10-08T16:16:01.816+09:00 INFO 79945 --- [nio-8080-exec-1] com.example.localtest.Controller : test
2023-10-08T16:16:01.816+09:00 INFO 79945 --- [nio-8080-exec-1] com.example.localtest.Controller : 2023-10-08T16:16:01.816840
2023-10-08T16:16:01.879+09:00 INFO 79945 --- [nio-8080-exec-1] com.example.localtest.Controller : >>>>>>>>>> REQUEST <<<<<<<<<<
2023-10-08T16:16:01.879+09:00 INFO 79945 --- [nio-8080-exec-1] com.example.localtest.Controller : Request: GET http://localhost:8080/timeout
2023-10-08T16:16:01.880+09:00 INFO 79945 --- [nio-8080-exec-1] com.example.localtest.Controller : from : webclient
2023-10-08T16:16:02.064+09:00 INFO 79945 --- [nio-8080-exec-2] com.example.localtest.Controller : timeout test
2023-10-08T16:16:05.070+09:00 WARN 79945 --- [ctor-http-nio-2] r.netty.http.client.HttpClientConnect : [699c5c07-1, L:/127.0.0.1:62710 - R:localhost/127.0.0.1:8080] The connection observed an error
io.netty.handler.timeout.ReadTimeoutException: null
HttpClientRequest를 사용시 WebClientRequestException ReadTimeoutExeption 발생
Reactor Core 사용시 TimeoutException 발생
Exception Handling은 나중에~.~