Performance comparison: REST vs gRPC vs asynchronous communication

Tim Bastin
l3montree TechBlog
8 min readFeb 1, 2022

--

The communication method between microservices has a significant impact on a variety of software quality factors within a microservice architecture (more information on the crucial role of communication inside a microservice network). The communication style influences functional requirements like the performance and the efficiency of the software, as well as non-functional requirements like changeability, scalability and maintainability. Therefore, it is necessary to consider all pro and cons of the different methods to make a reasoned choice of the correct communication style in a concrete use case.

This article compares the styles: REST, gRPC and an asynchronous communication using a message broker (RabbitMQ), inside a microservice network regarding their performance impact on the software. Some of the most important properties of the communication style (which in turn are influencing the overall performance) are:

  1. Data transmission format
  2. Connection-Handling
  3. Message serialization
  4. Caching
  5. Load-Balancing

Data transmission format

While asynchronous communication using the AMQP protocol (Advanced Message Queuing Protocol) and gRPC communication is performed using binary protocols for data transfer, REST-APIs are usually transmitting data in text-format. Binary protocols are much more efficient compared to text-based protocols [1,2]. Thus, communication using gRPC and AMQP results in a lower network load, while one can expect a higher network load when using REST APIs.

Connection-Handling

REST-APIs are often built on top of the HTTP/1.1 protocol, while gRPC relies on the use of the HTTP/2 protocol. HTTP/1.1, HTTP/2, and also AMQP are using TCP at the transport level to ensure a stable connection. To establish such a connection, elaborate communication between client and server is required. These performance implications apply equally to all communication styles. However, the initial establishment of the communication connection only needs to be performed once for an AMQP or HTTP/2 connection, since requests can be multiplexed for both protocols. This means that existing connections can be reused for subsequent requests using the asynchronous or gRPC communication. A REST-API which is using HTTP/1.1, on the other hand, establishes a new connection for each request with the remote server.

Necessary communication to establish a TCP-Connection

Message serialization

Typically, REST and asynchronous communication is performed using JSON for message serialization before transmitting messages over a network. gRPC on the other hand transmits data by default in protocol buffer format. Protocol buffers increase the speed of communication by allowing more advanced serialization and de-serialization methods to be used for encoding and consuming the message content [1]. Nevertheless, it is up to the engineer, to choose the right message serialization format. Regarding performance protocol buffers are having numerous advantages, but when one has to debug the communication between microservices, relying on the human-readable JSON format might be the better choice.

Caching

An efficient caching strategy can significantly reduce the load on servers and the necessary computing resources. REST-APIs are the only communication style which allow an efficient caching due to their architecture. REST-API responses can be cached and replicated by other servers and caching proxies like Varnish. This reduces the load on the REST service and allows large amounts of HTTP traffic to be processed [1]. However, this is only possible after deploying more services (caching proxies) on the infrastructure or using third-party integration. Neither the official gRPC documentation, nor the documentation of RabbitMQ, introduce any forms of caching.

Load-Balancing

In addition to temporary storage of responses, there are other technologies that can increase the speed of services. Load balancers such as mod_proxy can distribute HTTP traffic between services in an efficient and transparent way [1]. This enables horizontal scaling of the services which are using REST APIs. Kubernetes, as a container orchestration solution, performs load balancing of HTTP/1.1 traffic without any adjustments. For gRPC, on the other hand, another service (linkerd) needs to be provisioned on the network [3]. Asynchronous communication supports load balancing without further aids. The message broker itself takes the role of the load balancer, as it is capable of distributing requests to multiple instances of the same service. Message brokers are optimized for this purpose, and their design already took into account the fact that they must be particularly scalable [1].

Experiment

To be able to evaluate the individual communication methods in terms of their impact on the software quality characteristics, four microservices were developed to simulate the order scenario of an e-commerce platform.

Communication during the experiment

The microservices are deployed on a self-hosted Kubernetes cluster consisting of three different servers. The servers are connected via a Gigabit (1000 Mbit/s) network and are located in the same data center, with an average latency between servers of 0.15ms. The individual services are deployed on the same servers for each experiment run. This behavior is achieved by a pod affinity.

All microservices are implemented in the GO programming language. The actual business logic of the individual services, such as communication with a database, was deliberately not implemented in order not to falsify the results of the experiment by other influences apart from the selected communication method. Thus, the results collected are not representative of a microservice architecture of this type, but make the communication methods within the experiment comparable. Instead, the implementation of the business logic was simulated by delaying the program flow by 100 milliseconds. Within the communication, there is consequently a total delay of 400 milliseconds.

The open-source software k6 is used to implement the load testing.

Implementation

The net/http module included in the Golang standard library is used to provide a REST interface. Requests are serialized and de-serialized using the encoding/json module also included in the standard library. All requests use the HTTP POST method.

“Talk is cheap. Show me the code.”
- Linus Torvalds

Golang REST-Server implementation

A RabbitMQ message broker is used for asynchronous communication and is deployed on the same Kubernetes cluster. Communication between the message broker and the individual microservices takes place using the github.com/spreadway/amqp library. This library is recommended by the official documentation for the GO programming language.

Golang AMQP Server implementation

The gRPC clients and servers use the google.golang.org/grpc library recommended by the gRPC documentation. Serialization of data is done using protocol buffers.

Golang gRPC Server implementation

Collecting Data

The number of successful and failed order processes is examined regarding the time elapsed until their confirmation. An order process is interpreted as failed if the duration until confirmation exceeds 900 milliseconds. This duration was chosen because infinitely long waiting times can occur within the experiment, especially when using asynchronous communication. The number of failed and successful orders is reported for each trial.

A total of twelve different measurements are taken for each architecture, with different numbers of simultaneous requests and varying amounts of data transmitted in each case. First, each communication method is tested under low load, then under medium load, and finally under high load. A low load is simulated with ten, a medium load with 100 and a high load with 300 simultaneous requests to the system. After these six test runs, the amount of data to be transferred is increased to gain knowledge about the efficiency of the serialization method of the respective interface. The increase in the amount of data is achieved by placing an order for several products.

Results

The gRPC API architecture is the best performing communication method studied within the experiment. Under low load, it can accept 3.41 times as many orders as the system using REST interfaces. Also, the average response time is 9.71 milliseconds lower compared to REST-APIs and 9.37 milliseconds lower compared to AMQP-APIs.

10 simultaneous request, low bandwidth usage. x: Communication Method (Number of Requests), y: Duration in milliseconds
10 simultaneous request, high bandwidth usage. x: Communication Method (Number of Requests), y: Duration in milliseconds
Average handled requests per second based on the communication method and the bandwidth usage

Overall, this trend continues in the experiments with a larger amount of concurrent requests. Regarding 100 concurrent requests, 3.7 times as many orders can be processed using a gRPC-API architecture compared to a REST-API. The difference to AMQP is much smaller. GRPC is capable of processing 8.06% (1170 orders) more, than AMQP. While gRPC can process 95% of requests within 418.99 milliseconds, AMQP is only capable of doing so in 557.39 milliseconds and REST in 1425.13 milliseconds.

100 simultaneous requests, low bandwidth usage. x: Communication Method (Number of Requests), y: Duration in milliseconds
100 simultaneous requests, high bandwidth usage. x: Communication Method (Number of Requests), y: Duration in milliseconds
Average handled requests per second based on the communication method and the bandwidth usage

In the third run under high load, the microservice architecture with gRPC APIs can successfully confirm 43122 orders. This is 4.8 times more than the same architecture with REST-APIs, and 2.02 times more than the architecture using asynchronous communication.

300 simultaneous requests, low bandwidth usage. x: Communication Method (Number of Requests), y: Duration in milliseconds
300 simultaneous requests, high bandwidth usage. x: Communication Method (Number of Requests), y: Duration in milliseconds
Average handled requests per second based on the communication method and the bandwidth usage

Looking at the size of the client request in JSON format compared to the size in protocol buffer format, for a single product, the amount of data transferred using gRPC is 34.202% less compared to REST. This difference can be justified by the optimized protocol-buffer serialization, which offers a more efficient encoding than JSON.

Conclusion

gRPC proved to be the most efficient API architecture, followed by AMQP with a message broker. gRPC offers a more efficient serialization method than JSON with protocol buffers. Overall, about 3.4–4.03 more orders can be processed compared to REST. Especially in situations with many concurrent connections, gRPC can offer an advantage over REST-APIs because TCP connections can be reused. Compared to asynchronous communication 1.0–2.2 more orders can be processed. Another advantage of gRPC that emerged through the experiment is that gRPC provides predictable performance without large outliers in response time. During the experiment, AMQP, and REST in particular, showed a large discrepancy between the average response time and the 95% quantile. The experiment examined how each communication style performed under a variable number of concurrent requests and transmitted data, but this study can only approximate the complexity of reality. Supporting technologies such as load balancers and caching proxies can have significant impacts, especially when using REST APIs. The results of this experiment must be evaluated considering the experiment setup.

A statement that gRPC allows the most efficient communication within a microservice network cannot be made.

If you enjoyed this article and would like to learn more about us, visit: l3montree.com

References

[1]
Sam Newman.Building Microservices: Designing Fine-Grained Systems. Vol. 2. O’ReillyMedia, Inc, 2015.

[2]
Jim Webber, Savas Parastatidis, and Ian Robinson. REST in Practice: Hypermedia andSystems Architecture. O’Reilly Media, Inc., 2010, p. 448.

[3]
William Morgan.gRPC Load Balancing on Kubernetes without Tears. https://kubernetes.io/blog/2018/11/07/grpc-load-balancing-on-kubernetes-without-tears/. (Accessed on 09/15/2021). Nov. 2018.

--

--

Tim Bastin
l3montree TechBlog

I am a Full-Stack software engineer with a passion for high software quality. Chief Technical Officer & Co-Founder of l3montree