Spring

RestTemplate vs web client 차이

기록만이살길 2021. 8. 20. 17:33
반응형

1. 소개

이 튜토리얼에서는 Spring의 두 가지 웹 클라이언트 구현인 RestTemplate 과 새로운 Spring 5의 반응적 대안 WebClient 를 비교할 것 입니다.

2. 차단 vs. 비차단 클라이언트

다른 서비스에 대한 HTTP 호출을 만드는 것은 웹 응용 프로그램의 일반적인 요구 사항입니다. 따라서 웹 클라이언트 도구가 필요합니다.

2.1. RestTemplate 차단 클라이언트

오랫동안 Spring은 RestTemplate 을 웹 클라이언트 추상화로 제공했습니다. 내부적으로 RestTemplate 은 요청당 스레드 모델을 기반으로 하는 Java Servlet API를 사용합니다 .

즉, 웹 클라이언트가 응답을 받을 때까지 스레드가 차단됩니다. 차단 코드의 문제는 각 스레드가 일정량의 메모리와 CPU 주기를 소비하기 때문입니다.

결과를 생성하는 데 필요한 느린 서비스를 기다리는 많은 수신 요청이 있다고 가정해 보겠습니다.

머지 않아 결과를 기다리는 요청이 쌓일 것입니다. 결과적으로 응용 프로그램은 스레드 풀을 소진하거나 사용 가능한 모든 메모리를 차지하는 많은 스레드를 생성합니다 . 빈번한 CPU 컨텍스트(스레드) 전환으로 인해 성능이 저하될 수도 있습니다.

2.2. WebClient 비차단 클라이언트

반면 WebClient 는 Spring Reactive 프레임워크에서 제공하는 비동기식 비차단 솔루션을 사용합니다 .

RestTemplate 이 각 이벤트(HTTP 호출)에 대해 호출자 스레드를 사용하는 동안 WebClient 는 각 이벤트에 대해 "작업"과 같은 것을 생성합니다. 이면에서 Reactive 프레임워크는 해당 "작업"을 대기열에 넣고 적절한 응답을 사용할 수 있을 때만 실행합니다.

Reactive 프레임워크는 이벤트 기반 아키텍처를 사용합니다. Reactive Streams API를 통해 비동기 로직을 구성하는 수단을 제공합니다 . 결과적으로 반응적 접근 방식은 동기/차단 방식에 비해 더 적은 스레드와 시스템 리소스를 사용하면서 더 많은 논리를 처리할 수 있습니다.

WebClientSpring WebFlux 라이브러리의 일부입니다 . 따라서 선언적 구성 으로 반응 유형( MonoFlux )이 있는 기능적이고 유창한 API를 사용하여 클라이언트 코드를 추가로 작성할 수 있습니다 .

3. 비교예

이 두 접근 방식의 차이점을 보여주기 위해 많은 동시 클라이언트 요청으로 성능 테스트를 실행해야 합니다. 특정 수의 병렬 클라이언트 요청 후에 차단 방법으로 상당한 성능 저하를 볼 수 있습니다.

반면, Reactive/Non-blocking 방식은 요청 횟수에 관계없이 일정한 성능을 제공해야 합니다.

이 기사의 목적을 위해 하나는 RestTemplate 을 사용하고 다른 하나 는 WebClient를 사용하는 두 개의 REST 엔드포인트를 구현해 보겠습니다 . 그들의 임무는 트윗 목록을 반환하는 또 다른 느린 REST 웹 서비스를 호출하는 것입니다.

시작하려면 Spring Boot WebFlux 스타터 종속성 이 필요합니다 .

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

또한 느린 서비스 REST 엔드포인트는 다음과 같습니다.

@GetMapping("/slow-service-tweets")
private List<Tweet>getAllTweets() {
    Thread.sleep(2000L); // delay
return Arrays.asList(
new Tweet("RestTemplate rules", "@user1"),
new Tweet("WebClient is better", "@user2"),
new Tweet("OK, both are useful", "@user1"));
}

3.1. RestTemplate 을 사용 하여 느린 서비스 호출

이제 웹 클라이언트를 통해 느린 서비스를 호출하는 또 다른 REST 끝점을 구현해 보겠습니다.

먼저 RestTemplate을 사용합니다 .

@GetMapping("/tweets-blocking")
public List<Tweet>getTweetsBlocking() {
    log.info("Starting BLOCKING Controller!");
final String uri = getSlowServiceUri();
    RestTemplate restTemplate =new RestTemplate();
    ResponseEntity<List<Tweet>> response = restTemplate.exchange(
      uri, HttpMethod.GET,null,
new ParameterizedTypeReference<List<Tweet>>(){});
    List<Tweet> result = response.getBody();
    result.forEach(tweet -> log.info(tweet.toString()));
    log.info("Exiting BLOCKING Controller!");
return result;
}

이 끝점을 호출하면 RestTemplate 의 동기 특성으로 인해 코드가 느린 서비스의 응답을 기다리는 것을 차단합니다. 응답을 받은 경우에만 이 메서드의 나머지 코드가 실행됩니다. 로그에서 다음을 확인할 수 있습니다.

Starting BLOCKING Controller!
Tweet(text=RestTemplate rules, username=@user1)
Tweet(text=WebClient is better, username=@user2)
Tweet(text=OK, both are useful, username=@user1)
Exiting BLOCKING Controller!

3.2. WebClient 를 사용 하여 느린 서비스 호출

둘째, WebClient 를 사용 하여 느린 서비스를 호출해 보겠습니다 .

@GetMapping(value = "/tweets-non-blocking",
            produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<Tweet>getTweetsNonBlocking() {
    log.info("Starting NON-BLOCKING Controller!");
    Flux<Tweet> tweetFlux = WebClient.create()
      .get()
      .uri(getSlowServiceUri())
      .retrieve()
      .bodyToFlux(Tweet.class);
    tweetFlux.subscribe(tweet -> log.info(tweet.toString()));
    log.info("Exiting NON-BLOCKING Controller!");
return tweetFlux;
}

이 경우 WebClientFlux 게시자를 반환 하고 메서드 실행이 완료됩니다. 결과가 나오면 게시자는 구독자에게 트윗을 보내기 시작합니다. 이 /tweets-non-blocking 끝점을 호출하는 클라이언트(이 경우 웹 브라우저) 도 반환된 Flux 개체에 가입됩니다 .

이번에는 로그를 관찰해 보겠습니다.

Starting NON-BLOCKING Controller!
Exiting NON-BLOCKING Controller!
Tweet(text=RestTemplate rules, username=@user1)
Tweet(text=WebClient is better, username=@user2)
Tweet(text=OK, both are useful, username=@user1)

이 끝점 메서드는 응답을 받기 전에 완료되었습니다.

4. 결론

이 기사에서 우리는 Spring에서 웹 클라이언트를 사용하는 두 가지 다른 방법을 탐구했습니다.

RestTemplate 은 Java Servlet API를 사용하므로 동기적이고 차단됩니다. 반대로 WebClient 는 비동기식이며 응답이 돌아올 때까지 기다리는 동안 실행 스레드를 차단하지 않습니다. 응답이 준비된 경우에만 알림이 생성됩니다.

RestTemplate 은 계속 사용됩니다. 어떤 경우에는 비차단 접근 방식이 차단 접근 방식에 비해 훨씬 적은 시스템 리소스를 사용합니다. 따라서 이러한 경우 WebClient 가 선호되는 선택입니다.

기사에서 언급한 모든 코드 조각 은 GitHub 에서 찾을 수 있습니다 .

반응형