Saturday, November 16, 2019

Spring 5: WebClient vs RestTemplate

In today's micro-services world, where almost everything is exposed as REST endpoints, we are bound to call these REST services.

How do we call ?

We have a convenient class called RestTemplate, provided by Spring. However this is synchronous in nature, it uses Thread-per-Request method. Until each request is completed and response is sent back to user or service erred out, the thread will be blocked out for that user.

Just assume this for heavy traffic but slow response application, within seconds the app will be sending 404 or 500 as it can't handle the request anymore as well as so many existing requests (threads) will degrade the performance of the application.


@GetMapping("/employees")
public List<Employee> getEmployeesBlocking() {
    log.info("Starting BLOCKING Controller!");
    final String uri = getSlowServiceUri();

    RestTemplate restTemplate = new RestTemplate();
    ResponseEntity<List<Employee>> response = restTemplate.exchange(
      uri, HttpMethod.GET, null,
      new ParameterizedTypeReference<List<Employee>>(){});

    List<Employee> result = response.getBody();
    result.forEach(employee -> log.info(employee.toString()));
    log.info("Exiting BLOCKING Controller!");
    return result;

}

is it worth for thread to be blocked, waiting for response from called endpoint ?

can't we free up the thread and queue the task, which can be picked up when we get the response ?

With RestTemplate answer is no... as it is Synchronous in nature, however Spring 5 has new class called WebClient, which can do the job for us.

WebClient works on the concept of Asynchronous and non blocking strategy. it is part of WebFlux Project which is reactive programming extension provided by Spring.

Basically behind the scene it will treat each request as task and queue them when they are waiting for response. The serving thread will be unblocked to serve other requests and once response received for that task, webclient will activate the task by assigning thread to it and finish rest of the execution as programmed.


@GetMapping(value = "/employees",
            produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<Employee> getEmployeesNonBlocking() {
    log.info("Starting NON-BLOCKING Controller!");
    Flux<Employee> employeeFlux = WebClient.create()
      .get()
      .uri(getSlowServiceUri())
      .retrieve()
      .bodyToFlux(Employee.class);

    employeeFlux.subscribe(employee -> log.info(employee.toString()));
    log.info("Exiting NON-BLOCKING Controller!");
    return employeeFlux;

}

RestTemplate is getting deprecated and will not be supported in future versions of Spring. We should start using WebClient. It not only supports Asynchronous it also supports Synchronous calls so we call use WebClient as a replacement for RestTemplate.

No comments: