The microservice architecture has the database per service pattern, which means it has an independent database for every dependent or independent service:
- Dependent service: Our application would require a few external services (third- party services or components, and so on) and/or internal services (these are our own services) to work or function as expected. For instance, CHECKOUT-SERVICE requires CUSTOMER-SERVICE; also, CHECKOUT-SERVICE requires an external (third-party) service to verify a customer's identity (such as Aadhaar card ID in the case of Indian customers). Here, our CHECKOUT-SERVICE is a dependent service, as it requires two services (an internal service and external service) to function as expected. Dependent services do not work if any or all the services on which the service is dependent on do not work properly (there are a lot of reasons a service would not work, including network failure, unhandled exception, and so on).
- Independent service: In our application, we have services that do not require any other service to work properly. Services that do not need any other service to work in order to function are called independent services; these services can be self-hosted. Our CUSTOMER-SERVICE does not require any other service to function properly, but other services may or may not require this service.
The main challenge is to maintain business transactions to ensure data consistency across these services. For instance, when and how CUSTOMER-SERVICE would know that CHECKOUT-SERVICE has functioned; now it requires the functionality of CUSTOMER-SERVICE. There may be several services in an application (services may be self-hosted). In our case, when CHECKOUT-SERVICE is triggered and CUSTOMER-SERVICE is not invoked, then how will our application identify the customer’s details?
ASP.NET WebHooks can also be used for providing event notifications; refer to the WebHooks documentation for more information.
To overcome the related problems/challenges we've discussed (for CHECKOUT-SERVICE and CUSTOMER-SERVICE), we can use an event-driven pattern (or the eventual consistency approach) and use distributed transactions.
A document on MSDN (https://msdn.microsoft.com/en-us/library/windows/desktop/ms681205(v=vs.85).aspx) says the following:
The following diagram describes an actual implementation of the event-driven pattern in our application, where PRODUCT-SERVICE subscribes to the events and Event-Manager manages all the events:
In an event-driven pattern, we implement a service in such a way that it publishes an event whenever a service updates its data, and another service (dependent service) subscribes to this event. Now, whenever a dependent service receives an event, it updates its data. This way, our dependent services can get and update their data if required. The preceding diagram shows an overview of how services subscribe to and publish events. In the diagram, Event-Manager could be a program running on a service or a mediator helping you manage all the events of the subscribers and publishers.
It registers an event of the Publisher and notifies a Subscriber whenever a specific event occurs/is triggered. It also helps you to form a queue and wait for events. In our implementation, we will use Azure Service Bus queues for this activity.
Let's consider an example. In our application, this is how our services will publish and receive an event:
- CUSTOMER-SERVICE performs a few checks for the users, namely login check, customer details check, and so on; after these necessary checks are conducted, the service publishes an event called CustomerVerified.
- CHECKOUT-SERVICE receives this event and, after performing the necessary operations, it publishes an event called ReadyToCheckout.
- ORDER-SERVICE receives this event and updates the quantity.
- As soon as the checkout is performed, CHECKOUT-SERVICE publishes an event. Whatever result is received from the external service, either CheckedoutSuccess or CheckedoutFailed, it is used by CHECKOUT-SERVICE.
- When InventoryService receives these events, it updates the data to make sure the exact item is added or removed.
With the use of event-driven patterns, services can automatically update the database and publish an event.