There has been a paradigm shift in the software industry lately where the microservice architecture is now replacing the general monolithic application architecture for server apps. The concept of a set of loosely coupled, independent, lightweight modules with each module representing a single functionality and running in their own processes has been selling like hotcakes and rightly so. The microservice architecture enables scalability, reliability, and high availability as each independent service is developed, managed and tested individually without any dependency.
Since microservices are loosely coupled, it makes sense that a message broker is fit into this infrastructure to allow asynchronous microservice communication, while maintaining decoupling. Asynchronous communication means that either service does not have to wait for the other. For this, the publish-subscribe model has been widely adopted as the medium for communication among the microservices.
NCache is an in-memory distributed data store for .NET, and provides feature-rich, in-memory pub/sub for event driven communication. Hence, NCache can easily be configured as a messaging broker for asynchronous communications between microservices using the Pub/Sub model.
Using NCache In-Memory Pub/Sub for Microservices
Pub/Sub is enabled in NCache by defining a topic on which the microservices (built in .NET/.NET Core) can publish events as well as subscribe to it. The events are published outside the microservice, to the NCache message broker. Each subscriber microservice contains an event handler to handle the appropriate event once the publisher microservice has published it. A simple, logical diagram of this architecture is highlighted in Figure 1:
For .NET/.NET Core microservices, NCache acts as an event bus or message broker through which the messages are relayed to one or more subscribers. For more detail on the NCache Pub/Sub model, refer to the NCache documentation or our blog on Using NCache as In-Memory Pub/Sub.
This blog post uses the eShopOnContainers sample application extended with NCache and uploaded on GitHub. The project injects NCache as an event bus for the app-coordination between the .NET microservices. NCache’s role in this application is shown in Figure 2.
Quick Example of Using NCache In-Memory Pub/Sub
Using the eShopOnContainers application, NCache acts as a messaging broker in multiple scenarios. One scenario highlighted here is the user checkout event where the basket details are published to the NCache event bus, and the order application may have subscribed to any incoming baskets on user checkout to process the order.
- Publish: This simplified code snippet shows a portion of the basket checkout logic in the Basket.API microservice where the user ID and all basket details like address, card number and more are added as a message payload and published on the event bus. The Basket.API code can be found in BasketController.cs class on GitHub.
public async Task<ActionResult> CheckoutAsync([FromBody]BasketCheckout basketCheckout, [FromHeader(Name = "x-requestid")] string requestId)
var userId = GetUserIdentity();
basketCheckout.RequestId = GetRequestID();
var basket = await GetBasketAsync(userId);
var userName = User.FindFirst(x => x.Type == "unique_name").Value;
var eventMessage = new UserCheckoutAcceptedIntegrationEvent(userId, userName,
basketCheckout.Address, basketCheckout.CardNumber, basketCheckout.RequestId, basket);
// This message is published to the NCache Pub/Sub store
- Subscribe: The following code snippet is from the Ordering.API microservice, the code for which is uploaded at GitHub. This contains subscription to the UserCheckout event where once a user checks out the basket, an event is published as a message and the handler from the subscriber is called to process the order further.
var eventBus = app.ApplicationServices.GetRequiredService<IEventBus>();
Pub/Sub Message Durability with Durable Subscriptions
Since microservices are loosely coupled, it means microservices might be joining or leaving the application at any time. Moreover, what if you experience any network glitch during high traffic message passing? This means that the microservice connection with the event bus has to be resilient enough, so messages are not lost even if the network has temporarily gone down.
NCache offers two types of durable subscriptions to accommodate your message durability among your .NET/.NET Core microservices:
- Shared Durable Subscriptions: Multiple subscribers can subscribe to one subscription. The Round Robin method is used to send messages to multiple subscribers. Even if any subscriber leaves the network, the messages between active subscribers continue to be distributed.
- Exclusive Durable Subscriptions: One subscription only has one active subscriber at a time. No new subscriber request is accepted on the same subscription until the connection is active.
Communication Reliability with Connection Retries
As microservices rely on the network for communication, there can be uncalled-for network fails which would require having a connection establishing mechanism. Thus, NCache maintains a reliable communication platform with connection retries and keep-alive features to make sure that your .NET/.NET Core services automatically attempt to connect to the cache in case of network failure. This eliminates the need for retry policies by any third-party library such as Polly.
As organizations are now adopting the microservice architecture over monolithic applications, NCache becomes your go-to in-memory distributed data store to be used as an intermediary medium for your .NET/.NET Core microservice applications.
- Extremely Fast and Linearly Scalable: Being in-memory, NCache provides faster communication than other Pub/Sub solutions. Besides, being distributed allows NCache to let you scale on the go as you add more servers to the Message Broker cluster to handle greater loads.
- High Availability: NCache provides a dynamic, self-healing peer-to-peer clustered architecture that ensures no single point of failure. Moreover, NCache smartly replicates the messages and also provides durable subscriptions so there is no message loss in case a cache server goes down, guaranteeing high availability to your microservices for communication. NCache also provides high availability when you need to grow the number of servers in the cluster by letting you add these servers at runtime without stopping the cluster.
- Native .NET Core: For microservices built in .NET/.NET Core, NCache provides a 100% .NET / .NET Core native stack to integrate into your application stack seamlessly.
To sum up, while microservices simplify your application into logical units, it also becomes difficult to manage communication among them. Hence, NCache takes away the added complexity of introducing a highly available messaging broker that also respects decoupling at the same time.
We have another blog on Scaling Microservices Performance with Distributed Caching. Go check that out!