Akash Sateesh
Akash Sateesh

Reputation: 812

How to increase the performance in reactive programming with single core cpu

I have an application which connects to third party service and gets the result back to client. Inside , app make an GET request to third party service and gets the result. I have used Reactor and reactive code to scale the application at heavy loads. This is a Spring Boot project which runs embedded Tomcat and relies on Web Client( Reactive netty for making request to third party). Somehow , CPU Utilization and response times are worse than blocking mode. The hardware setup has single core running in Kubernetes.

The project is set up inside Kubernetes and running on single pod with one core. I tried in reactive way , but the app is much slower and even CPU Utilization is high when compared to blocking architecture.

 public Mono<ResponseEntity<?>> get(HttpServletRequest request)
   {
      return Mono.create ( callback -> {
         Mono<Response> response = Make HTTP GET Call using webClient.
         response.subscribe(response -> {
         callback.success(response);
         },error -> {
         callback.error(error);
         }
       });
    }

With Traditional Blocking mode , I am ble to see better performance and decreased CPU usage when comapred to reactive approach. What could be the reason for this disparity ? Is it because of context switching as there is only one core ? If yes , how do we attain better performance through single core architecture ?

Upvotes: 2

Views: 3001

Answers (2)

Prashant Pandey
Prashant Pandey

Reputation: 4642

There should be just one subscription in your entire reactive chain. Delay it as much as possible - one subscription at the end. Let us re-write your code:

public Mono<ResponseEntity<?>> get(HttpServletRequest request) {
      return Mono.just(requestObject)
                 .flatmap(a -> makeAsyncCall(a))
                 .doOnError(err -> doSomethingOnError());
}

You can subscribe where are you starting your reactive chain. Typically, this would be the controller.

This would be:

Mono.just(request)
    .flatMap(request -> get(request))
    .subscribe(response -> setDeferredResult(response));

return deferredResult;

Upvotes: 1

Toerktumlare
Toerktumlare

Reputation: 14732

i don't really understand why you subscribe in the middle to extract the response. Subscribing i think is an expensive process and should only be done once by the calling client.

This is an example of how i would do it using the doOnError method to handle errors and mapping the response.

public Mono<Foo> bar() {
    return client.get()
            .uri("/something")
            .accept(MediaType.APPLICATION_JSON)
            .exchange()
            .flatMap(response -> response.bodyToMono(Foo.class))

}

public Mono<Bar> foo() {
    return bar()
        .flatMap(stuff -> {
         return // Map it here to something else that 
                // is getting returned to the calling client
        })
        .doOnError(FooBarException::new);

Upvotes: 2

Related Questions