In microservices the application is structured as a collection of loosely coupled indepedently deployable services. Each service can have its own logical architecture (often using hexagonal architecture) and tech stack .The connectors between sesrvices are ipc mecahnisms like rest calls or asynchronous messaging. A service has api that provides its clients access to its functionalities.
- In microservices architecture the services handle
- commands - updates data
- queries - retrieves data
- a service also publishes events which are consumed by clients.
- the requirement for service to be loosely coupled and talk only via api means they cannot communicate via database. There can be no fk to tables of another service, no direct access to data of another service. This helps tremedously as teams can function autonomously
Key points to remember for microservice decomposition
- Application can be broken into services based on business capabilities. (eg order management, inventory management). A microservice = business capability. A business capability is ofent focussed on business entity eg claim management will focus on claim business obect. The key advantage of creating services around capablities is that since capablities do not vary hence resulting architecture will also be stable.
- Typically a microservice should be handled by small team, if the team is too big or service is too big you may be building a distributed monolith.
- A service must be implement a small set of strongly coorelated business capabilities.
- During decompstion network latency has to be factored in , eg a decompstion may be bad as it is leading too many interactions between services.In that case combining the service to replace IPC with method call should be considered.
- As in microservice each service has its own database hence if very strong acid gurantees are required then services may need to be combined into a single service.
- The concept of domain driven design are very useful in microservices.Especially the concept of aggregates.An aggregate is cluster of objects that can be treated as a unit. Most business entities are aggregates, eg order, also when u wanna delete the order aggregate you have to delete other entities in the order aggregate, eg order line item. Events in microservices are often designed for aggregates . Aggregates break the domain model into chunks. Aggregates must reference each other via primary key. eg Order aggregate can only reference customer aggregate via customer id. Order object must not have customer object reference . The advantage is that now the aggregates which make the domain model are very loosely connected now. Loosely coupled aggregates let you partion your object model across microservices. Using this technique we can split the domain model which is tangled web of classess where objects are pointing to one another .This also simplifies persistence of aggregate. Scaling the database by sharding aggregates is possible.Note that the root entity should be the only part of the aggregate that can be referenced by classess outside the aggregate. This ensures that aggregates can enforce business logic. Other advantage of aggregate is
- Aggregates also make the scope of operations like load/update/delete clear. These operations act on the entire aggregate. concurrency can be handled by locking aggregate root.
- In domain driven design a transaction only create/update single aggregate. since in microservices each service has its own database and transactions cannot span microservices, hence aggregate concept fits transaction model of microservices very well. note how ever that aggregate granularity must be decide carefully. fine grained aggregates will improve the number of concurrent requests the app can handle and it also reduced chances of conflicting updates , on the other hand since the aggregate is the scope of the transaction it may be required to to define a larger aggregate to make an updat atomic.
- God classess should be eliminated using the concepts of domain driven design. God classes are key classess which represent a central concept in a domain. Examples would be order in ecommerce or policy in insurance. Each service should have its own domain model with its own version or order class. Hence a single application wide domain model is not required.For example in an ecommerce application, delivery service will have its view of the order . For delivery service pickup address, pick up time, delivery address are the key fields and it is only interested in subset of fields .The delivery servie may even call it delivery rather than order.This is preferable to
- Packaging order class as lib, and create central order database. All services that process order use this lib and access the db, but this is violation of key principle of microservice architecture, it results in tight coupling. If order schema is modified all services get impacted.
- Encapsulating order database in order service, which is invoked by other services to rerive and update orders , but then order service would be a data service this would be an anemic domain model containing very little business logic.
- Some concepts of object oriented design are critical in microservices.
- Single responsibility principle - A class should have only one reason to change, each responsibility is a reason to change so class should have just one primary responsiblity . Same principle can be applied in microservices. Small services each having a single resposiblity will reduce the size of service and increase its stablity. A service which has too many reponsibilities will often change.
- Common closure principle - If two classess change becuase of same reason they should be part of same package. Similary when requriement s change , mininum number of services should be impacted. CCP helps in avoiding the distributed monolith anti pattern.