RestTemplate

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์—์„œ๋Š” ์–ด๋–ป๊ฒŒ ๋” ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์„๊นŒ?

  • RestTemplateCustomizer๋ฅผ ํ™œ์šฉํ•˜๋ฉด ์‰ฝ๊ฒŒ Custom ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ResponseErrorHandler๋ฅผ ํ™œ์šฉํ•˜์—ฌ error ํ•ธ๋“ค๋ง๋„ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  • RestTemplateBuilder Doc
  • Springboot RestTemplateBuilder
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