Introduction
It is architectural style of building applications that are
resilient, highly scalable and individually deployable small units that can be
maintained by small heterogeneous teams. Each service will have separate
codebase where it can be handled by individual development team. The internal
implementation of one service will not know to other services. Microservices
will have its own data store and it will act like a distributed database.
Overview of Microservices
Client applications will interact only with API Gateway and
thus it routes the call to appropriate microservices behind the scenes.
Some of the advantage of API Gateway are as follows
1.
Decouple the client from microservices. In other
words, client don’t have any awareness of microservices
2.
Facade for entire microservices.
3.
It can cover other operations like
Authentication, Authorization, Logging etc.,
Domain Driven Design (DDD)
It is an important aspect in design microservices. In order to
design loosely coupled and cohesive microservices Domain plays a vital role. We
should consider designing the bounded context for an microservices and it
should interact with another bounded context.
Pic. Simple Catalogue
Domain Design
Analyzing Domain
We should consider designing the domain and it should meet
our business functional requirements. The above picture represents the sample
Catalogue domain design of entire system. It is necessary to take cohesiveness
of microservices and it should be loosely coupled.
Bounded Context
When we think about the microservices, we should have
boundaries between microservices, and it should be loosely coupled. Each boundary
in a domain should represent the same thing and it should not overlap the representation
of other thing. In other words, it must be single unit,
In above picture, the thin line represents the boundaries
between the primary entity/domain, and it should represent the single thing.
The thin lines represent the communication between bounded context in order to
achieve the business logic.
When we think about the communication between the boundaries
directly, the system will become tightly coupled and becomes more complex.
So, we should think about in writing fine-grained
well-designed API’s in order to achieve loosely coupled highly maintainable systems.
In order to do that we must implementing some design patterns mentioned by Eric
Evans.
Glimpse of Tactical DDD
In real, a single business transaction may span into
multiple data stores of microservices. Handling such scenario must be tactical
in designing the microservices.
Entities
It is an object that represent Unique Identifier of a system
that can be persisted over time.
Value Object
It is an Object that does not have Unique Identifier which
is simply values.
Aggregates
It is boundary around one or more entities. The Root entity
must have reference to the child entity within it.
Domain and Application Services
Domain services usually means encapsulated within business
or domain logic. Application services usually don’t have domain logic and it
won’t affect any state of domain or business. Example, sending any kind of notification.
Domain Events
It is used to notify that something happened within domain.
As we know microservices are distributed across the systems and don’t share the
databases with each other. These events are came to rescue in maintain the data
integrity of microservice distributed system.
Scenario: Order Status
In our catalog system, we may have the status of Order and
it might be distributed across the entities.
We may have domain events like,
·
Order entity may sends Order Placed, Cancel
Order, In-Progress, Order Completed
·
Printer entity may send Print Label, Cancel
Print, Print Completed
·
Employee entity may send Order Review, Approve, Cancel
Order, Test and Invoice
Look at this UML Diagram, which represents the order
aggregate entity,
In above aggregation, lot of microservices involved like
Order, Customer, Payment, Printer, Employee and we think about direct
communication between microservices. Then our system will look like Chatty I/O
and we tend to build complex system. In this case, we need to have reverse
proxy server where we can accumulate data from one or more services which is
API Gateway.
Likewise, we need to handle domain logic that spread across
the microservices which is nothing but distributed transactions. Here, we
should maintain the previous state of data-store in case of any failure.so,
reverse proxy server is stateless, and it is impossible to maintain distributed
transaction. Instead, we can have event sourcing. Event sourcing is nothing,
but domain events will be treated as messages and published in queue.
Subscribers/Listeners will get the notification about the event. So,
corresponding microservice will get notified and process to fulfill the
transaction.
Distributed Transaction
In above example scenario, we have a distributed transaction
that should be consider as unit of work.
When Customer placed an order (order service), Review status
must be set (employee service) which is nothing, but distributed transaction
and it is consider as unit of work. Here is how our initial plan for handling
distributed transaction that is without resilience.
Plan without Resilience (Publisher Subscriber Pattern)
Client: Web/Mobile application from where Client can
able to place an Order.
API Gateway: Receives request from the client.
Normally performs Routing, Request aggregation for GET calls to microservices.
For POST, PUT, PATCH, DELETE kind of calls it will deal with Ingestion
microservice.
Ingestion Service: Process the domain events into
queues and store that in a service bus as Topics/Queues.
Microservices: Listen to the domain event and process
that domain event into data when it gets notification on that event.
Imagine that Order is placed, and API Gateway will route to
ingestion service and process that into messages and it gets notified to
subscribers Employee Service and Order Service. Now Order service is processed
and succeed and employee service got notification and can’t able proceed
further due to some interruption from the datastore. Then Data Integrity
problem arises, and that order will always in Placed status and will not
process further and hence data anomalies.
Scheduler Agent Supervisor Pattern (Resilience)
This pattern ensures that distributed transaction with
resilience (Recover or undo) the failed operation. Treat distributed
transaction in sequence of steps of actions in case of failure undo the entire
operation transparently.
Look at this below distributed transaction workflow
Place Order Workflow
Initially the ingestion service will inject the message of
order place event into service bus. Order scheduler will listen to the topic
message in service bus. On Notification, it will follow the following steps in
order to achieve the distributed transaction
1.
Mark Order Place status – Call the order service
REST API to Update Order Status to Order placed status.
2.
Mark Review Status – Once after step 1, call the
Employee service REST API to Update Review Status.
3.
Mark In-Progress Status – Once after step 2,
call the order service REST API to update order status In-Progress status
Compensation Transaction
In case of any failure in above mentioned workflow, the
whole set of operation must be revoked by means of compensation transaction
which means previous state of distributed data store.
This illustrates that when order is placed by client it will
be routed to ingestion service via API Gateway and thus it will store message
as topic like “order placed” in service bus.
Order Scheduler: Listener to the order placed event
in service bus. It will get notified when order is placed. This takes the
responsibility of orchestrating the steps as mentioned above workflow.
Responsibilities:
1.
Orchestrate workflow steps to agent / in our
case agents are corresponding microservices.
2.
Maintain the State store with status like step
stated, In-Progress, Completed and Failed.
3.
It should
also maintain the compensation transaction to undo the operation if transaction
is failed.
Agents: Agents are Employee and Order Service. They
handle the business logic of steps individually by means of REST API.
Order Supervisor: This is Timer based service that
run periodically and listen the status of state store. If it found any failures
of steps and it will undo compensation transaction mentioned in state store.
Conclusion
Microservices are the new world of cloud computing which
brings numerous advantages for cloud-based applications like scalability,
independent deployment, heterogeneous sub system/microservices. On the inner face
of this facade system brings lot of complexities and there are many design
patterns to overcome those. We should choose wright flavor of patterns
according to our business needs.
Comments
Post a Comment