RestTemplate에 대해

RestTemplate

  • Spring에서 제공하는 Rest Client
  • 현재는 Deprecated되어 WebClient로 가이드를 하고 있다.

    NOTE: As of 5.0 this class is in maintenance mode, with only minor requests for changes and bugs to be accepted going forward. Please, consider using the org.springframework.web.reactive.client.WebClient which has a more modern API and supports sync, async, and streaming scenarios.

주의할 점은 없을까?

  • 많은 요청들을 다루기 어렵다.
    • RestTemplate는 기본적으로 Connection pool을 사용하지 않는다.
    • Default로 java.net.HttpURLConnection 사용한다.
      • SimpleClientHttpRequestFactory
    • 그래서 많은 요청을 하면 TIME_WAIT로 인해 자원이 점점 부족해져 서비스에 어려움을 가져온다.
    • 이를 해결하기 위해 Connection Pool을 만들어 사용하기를 권장하고 있다.

어떻게 Connection Pool을 사용할 수 있을까?

CloseableHttpClient httpClient = HttpClientBuilder.create()
    .setMaxConnTotal(120) // maxConnTotal은 연결을 유지할 최대 숫자
    .setMaxConnPerRoute(60) // maxConnPerRoute는 특정 경로당 최대 숫자
    .setConnectionTimeToLive(5, TimeUnit.SECONDS) // keep - alive
    .build();

HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setReadTimeout(5000); // 읽기시간초과, ms
factory.setConnectTimeout(3000); // 연결시간초과, ms
factory.setHttpClient(httpClient); // 동기실행에 사용될 HttpClient 세팅

this.restTemplate = new RestTemplate(factory);

Springboot에서는 어떻게 더 쉽게 만들 수 있을까?

CloseableHttpClient httpClient = HttpClientBuilder.create()
    .setMaxConnTotal(120) // maxConnTotal은 연결을 유지할 최대 숫자
    .setMaxConnPerRoute(60) // maxConnPerRoute는 특정 경로당 최대 숫자
    .setConnectionTimeToLive(5, TimeUnit.SECONDS) // keep - alive
    .build();

HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setHttpClient(httpClient); // 동기실행에 사용될 HttpClient 세팅

 this.restTemplate = new RestTemplateBuilder()
    .rootUri("https://nesoy.github.io")
    .requestFactory(() -> factory)
    .setConnectTimeout(Duration.ofSeconds(3))
    .setReadTimeout(Duration.ofSeconds(5))
    .errorHandler(new RestResponseErrorHandler()) // ResponseErrorHandler interface
    .build();
  • ResponseErrorHandler를 상속받아도 되지만 DefaultResponseErrorHandler하면 쉽게 할 수 있다.
 public class RestResponseErrorHandler extends DefaultResponseErrorHandler {
        @Override
        public void handleError(ClientHttpResponse response) throws IOException {
            log.error("Has error response: {}", response);
            super.handleError(response);
        }

        @Override
        public boolean hasError(ClientHttpResponse response) throws IOException {
            log.error("Has error response: {}", response);
            return super.hasError(response);
        }
    }

Reference

0%