Performance Comparison - RSocket Vs Webflux

Share on:

Background

In one of my previous post we saw tangible advantages (w.r.t throughput, latency and resource utilization) of refactoring existing Microservice application from imperative to reactive constructs.

So an obvious question that comes to an inquisitive mind -

Can we apply Reactive principles to the underlying communication layer

Answer to above question is - Yes and RSocket is the way to go

What is RSocket

RSocket is a binary protocol that can perform bi-directional communication via TCP. RSocket tries to overcome few of the limitations of HTTP1 and HTTP2 by providing following features -

  • Back-Pressure
  • Multiplexing
  • Resumption
  • Routing

It has been developed to match the semantics of Reactive Streams. Hence it seamlessly integrates with Project Reactor and ReactiveX

It mainly supports 4 communication models :

  1. Fire and Forget (No Response)
  2. Request Response (Single Response)
  3. Request Stream (Multiple Responses)
  4. Channel (Bi-directional Response)

Lets try to understand Request-Response model with a working example along with performance comparison w.r.t Spring Webflux APIs

Bird's eye view of demo example

Demo App - Bird's eye view

Working example (along with its source code) which we will be using for demonstration, primarily consists of 2 simple Spring Boot applications -

  1. Card Client - Public facing edge application with below endpoints. It uses WebClient to invoke downstream system's APIs and and RSocket client to communicate with downstream system's destination based on declared pattern.
 1    @GetMapping("/rsocket/card/{cardId}")
 2    public Mono<CardEntity> cardByIdWithRSocket(@PathVariable String cardId) {
 3        log.info("Entering CardClientController : cardByIdWithRSocket with path variable as {} ", cardId);
 4        Mono<CardEntity> cardEntityMono = rSocket
 5                                            .route("rsocket-find-specific")
 6                                            .data(cardId)
 7                                            .retrieveMono(CardEntity.class);
 8
 9        log.info("Card details received");
10        return cardEntityMono;
11    }

APIs exposed by application

HTTP MethodURIDescription
GETrx/card/{id}Fetches a card based on cardId by using WebClient
GETrsocket/card/{id}Fetches a card based on cardId by using RSocket
  1. Card Service - Application which not only exposes Webflux endpoint but also has a connection point for accepting RSocket client connection via @MessageMapping. It will be using  Redis as a persistent store. It also has a bulk loader which will load 5000 cards into the database whenever it bootstraps.
1    @MessageMapping("rsocket-find-specific")
2    public Mono<CardEntity> rSocketFindSpecific(String cardId) {
3        log.info("Entering CardViewController : rSocketFindSpecific with cardId : {} ", cardId);
4        return cardService
5                .getCardById(cardId)
6                //.delayElement(Duration.ofSeconds(1))
7                .doFinally(sig -> log.info("Response sent"));
8    }

Comparison based on performance metrics

Lets try to comparatively analyze RSocket Vs Webflux from performance standpoint. We will be using Gatling to simulate a load test.

Throughput & Latency

Load Testing Result

Above reports clearly shows that -

  1. 95th Percentile response time of RSocket based communication is 1/3 of Webflux based API consumption
  2. Mean response time of RSocket based communication is 1/2 of Webflux based API consumption
  3. Failures in RSocket based communication is 1/2 of WebFlux based API consumption
  4. TPS for successful requests in RSocket based communication is twice more than that of Webflux based API consumption

JVM Memory usage and Garbage Collection behavior

GC logging was enabled while performing load testing. GC logs were parsed via GC Easy to infer detailed JVM heap and GC behavior. Below are the observations w.r.t key performance parameters :

GC Pause Time

Time taken by single Stop the World (STW) GC

GC Pause Time

Object Promotion Metrics

Metrics indicating size and rate at which objects are promoted from Young Generation to Old Generation. Higher the promotion rate, higher the frequency of full GCs i.e. STW GC

Object Promotion Metrics

GC Throughput

Percentage of time spent in performing business transaction against time spent in GC activity

GC Throughput

Reference - One may want to refer my old article to understand nuances of Garbage Collection

Conclusion

As we saw in this article that along with obvious motivations behind using RSocket, there are compelling performance reasons which may incline us to leverage this protocol in justifiable way for inter service communication.

comments powered by Disqus