Async Controller Methods For Scalability

Async Controller Methods For Scalability

In API action methods, it is very common to call a database or another web resource to get requested data. Getting data from another server takes time and it is generally at least order of magnitude slower than all other processing code in the action method. If the data fetching calls are done synchronously then most of the time the request processing thread is doing nothing but waiting for data.

Let's say we have a .NET API server with 100 threads in the thread pool ready for serving requests. If we assume each request takes 200ms on average to complete, it can handle 500 request/s. But as we know most of the time threads are idle just waiting for data so potentially we should able to handle a much higher traffic with the same server.  The following shows what happens when synchronous calls are used in action methods to access data. Threads are blocked and dedicated for a request. The server is wasting its computing power most of the time for nothing.

No alt text provided for this image

Code example of a Synchronous action method.

[HttpGet]
[Produces("application/json")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public IEnumerable<Product> GetProducts()
{
	var products = dataService.GetProducts();
	if(products is null)
	 {
	    Response.StatusCode = StatusCodes.Status500InternalServerError;
	 }
	return products;
}        

Async and Await

The Async and Await key words in .NET core make it quite easy to manage async calls. Generally whenever we are doing calls with I/O we should use async methods. In the following example, the thread will be returned to the Thread pool and ready for the next request when GetProductAsync() is executed. The runtime will get a thread (may or may not be the same one) from Thread pool to continue the action method execution when the data is returned from GetProductAsync().

[HttpGet]
[Produces("application/json")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<IEnumerable<Product>> GetProducts()
{
	var products = await dataService.GetProductsAsync();
	if(products is null)
	 {
	    Response.StatusCode = StatusCodes.Status500InternalServerError;
	 }
	return products;
}        

If the action method spends 95% of time waiting for data to arrive over the wire then we can easily see the server can now serves traffic at a rate of 20 times higher. This is a big win for scalability without even adding a new server.

No alt text provided for this image

To view or add a comment, sign in

More articles by Lixin C.

  • Solution Architect - part 1

    Solution Architects (SA) are responsible for providing solutions to fulfill business requirements by working with…

  • Retrieve Data From Multiple Microservices

    In microservice pattern, microservices are suppose to own their own database to achieve best independent scalability…

  • Chaining HTTP Calls Using Observables With RxJS

    Sometimes we need to make multiple HTTP calls in a specific order to get data. The data from previous call are either…

  • RxJS Concise Demo - Creation Operators

    RxJS operators are functions that can create or process Observables. Creation operators are used to create new…

  • Angular Component Lifecycle Hooks

    Angular lifecycle hooks allows you to implement critical logic at the right time of a component's lifecycle. During the…

  • HTTP Status Code Short listed

    Commonly Used HTTP Status Codes for Web Services. 200 => OK, general indication of request success.

  • Network Layers for Software Engineers

    Sending messages to another person using web browser or mobile app is not surprisingly easy nowadays and most people…

  • Implementing a Fixed-Window Median Data Stream With Heaps

    A data stream is like a pipe with moving data inside. Here I only consider integer numbers as data and try to find the…

  • Test Your Testing Strategy with A Dice Game

    1. Project background Sometime in last year I got interested in how does the 3D web rendering engines work.

Explore content categories