Microservices Architecture - vidyasekaran/current_learning GitHub Wiki
Microservices Architecture Complete Guide -Udemy Course - Memi Lavi**
In 2014 Martin Fowler and James Lewis Published their "MicroServices" article which became the defacto standard for microservices definition
https://martinfowler.com/articles/microservices.html
which outlines the 9 attributes any microservice service architecture should follow.
9 Characteristics of MicroServices
1. Compenentization via services
2. Organized around business capabilities
3. products not projects
4. Smart endpoints and dumb pipes
5. Decentralized governance
6. Decentralized Data Management
7. Infrastructure Automation
8. Design For failure
9. Evolutionary Design.
1. Compenentization via services
KeyWord - Module, Components
Module - A Group of interrelated classes together,I call group of classes a Module, which represents some functionality of the application. Thus, module consists of components. Module can be considered a more granular layer of the application.
Components - I use term "component" to represent a class or any other element (e.g. structure or enumeration) which is grouped within a module.
a. Modular design is always a good idea b. Components are the parts that together compose the software.
a1.Modulear design Express and easily manage complex dependencies between classes and components within a single layer, by grouping them into Modules.
a2. In modular design updating it requires a small code change in a well defined part instead of touching a monstrous piece of code.
a3. In modular design we talk about components, components are the parts that together compose the software.
Modularity can be achieved using Libraries and Services
i) Libraries - called directly within the process (we use maven to resolve such dependecies and use import in our programs to use it by invoking the same). The libraries are executed within our systems process, share same compute resources and dont need any kind of mediation, such as serializer or network.
Benefits of using libraries is its performance is good as no network or external service involved.
ii) Services - called by out of process mechanism (Web API, RPC), modern systems mainly use Web API.
In Microservices we prefer using Services for the componentization. Componentization is achieved using services.
The componentization which is a process of seperating the software into 2 seperate components, thus making it modular is preferably done using services and not libraries.
If we simply want to group interrelated classes together, there is no necessity to introduce yet another layer. Instead, we can introduce a Module.
Thus this is called Componentization via services.
Motivation of componentization via services
Service inturn uses other libraries.
The modularity of system is expressed by the services and this is the componentization by Services.
why do we want to use services for the modularity of our system instead of simple fast libraries?
2 motivations for that are
a) Independent deployment. b) Well defined interface.
If we have to expose our service to outside world we have no other choice other than using web api.
2. Organized Around Business Capabilities
In traditional projects we have different teams with horizontal responsiblities - UI, API, Logic, DB, etc. Each team should collaborate to achieve desired functionality, UI need to talk to API team for endpoint and input, output values. Logic team need to talk to Database team to develop components. Inter group Communication is very slow and cumbersome.
In traditional projects we have different teams with horizontal responsiblities - UI, API, Logic, DB etc
Each team should collaborate to achieve desired functionality, UI need to talk to API team for endpoint and input, output values.
Logic team need to talk to Database team to develop components.
Inter group Communication is very slow and cumbersome.
With Microservices, every service handles a well defined business capablity.
UI - Team A API - Team A Logic - Team A Database - Team A
Team can focus on functionality instead of inner team politics and short sighted decisions.
How do we decide on the boundaries of the service?
How do we decide what service to do? How do we know when one service ends and other one begins?
So with microservices, we do that by looking at business capabilities.
We look at the overall functionality of the system and map the various business capabilities it has.
For example, an e-commerence site will have order management, inventory management, shopping, payment etc.
WE can have a service for order management which contains all of the technological layers and it is handled by single team. So we have a single team responsible for a single business capability.
instead of building horizontal service focusing on building microservices focusing on business capabilities will help make service better and with great time to market.
Motivation for service
- Quick Development - avoid inter politics as we have one team.
- Well defined boundaries - (what to include and what not).
3. Products not projects
With traditional projects, the goal is to deliver a working code. No lasting relationship with the customer Often no acquanitance with the customer After delivering - the team moves on to the next project.
With Microservices - the goal is to deliver a working product. A product needs ongoing support and requires close relationship with the customer. The team is responsible for the microservices after the delivery too.
Motivation behind not project but product
- Increase customer's satisfaction.
- Change developers mindset.
4. Smart Endpoints and dumb pipes
Traditional SOA projects used 2 complicated mechanisms
-
ESB - it mediates between the services between enterprise applications. helping with routing, authorization, validation, aggregation and more this is complex and costly so it failed utimately.
-
WS-* protocol - Original Soap - protocol that helped expose methods over internet and became 1st API. WS-* represents the collection of these extensions.
Each WS has specific goal
W has discover for locating services in the network, W security for Security, WS reliable messaging for enduring messages are actually delivered and in all.
Now, while these extensions were useful in themselves, they together with the ESB made interservice communication complicated and difficult to maintain.
Was not easy to follow all WS extension types and what they do. https://en.wikipedia.org/wiki/List_of_web_service_specifications
In short communication between services in SOA became a real pain.
MS == Microservices
With MS we use "dump pipes" - simple protocol - use simplest already availble protocol HTTP/HTTPS and leaves complexity of business functionality to MS itself.
Usually MS uses REST API, the simplest API in existence. It uses HTTP protocols verbs.
Microservices - look like various disconnected services - each exposes REST api and communicate directly with each other using nothing other than simple HTTP calls.
Important notes:
Direct connections between service is not a good idea - because this creates coupling between the services and if one service changes its location other services need to be updated.
Better use discovery service or a gateway.
In recent years more protocols were introduced (GraphQL, gRPC) some ot them quite complex
Motivation:
- Accelarate development (simple communication, rest api)
- Make app easier to maintain.
5. Decentralized Goverance
In traditional projects there is a standard for almost anything.
which dev platform, Db, logs etc..
with MS each team makes its own decision and team has authority to use which dev platform, db, logs to use..
- Which dev platform to use
- Which DB to use
- How to create logs
as each team is fully responsible for its service.
and team will make optimal decisions as they not only responsible for running code but for functionality and the MS and system they developed.
Enables the loosely coupled nature of MS. so if one MS have problem other wont get affected...
Multi dev platform is called Polygot.
Motivation:
By employing decentralized govenance
- Enables making the optimal tech decisions for the specific service.
6. Decentralized Data Management
Traditional systems have single DB Stores all the systems data from all the components. Each Ms has its own DB not sharing DB with others.
Important notes:
Most controversial attributes of MS. Not always possible as it raised problems such as distributed transactions, data duplication and more..
Think a customer detail is stored in a DB and customer order in other DB. In this case if you want to find how many orders a customer made we need data from both these databases. This leds to handling both data in a single transaction also maintain both these data all the time if there is change in one.
Motivation :
Right tool for the right task - having right DB is importand we need RDBS and also nosql.
Encourages Isolation.
https://martinfowler.com/articles/microservices.html
7. Infrastructure Automation
SOA suffered from lack of tooling. which delayed dev and deploy.
Tooling grealty helps in deployment using:
Automated testing Automated deployment
Since there are lots of microservices we cannot deploy and test each microservices manually this makes it imperative for MS automation using tools is very important
- For MS automation is essential
- Short deployment cycles are a must
- Cannot be done manually -there are lot of automation
Azure DevOPS, gitlab, Jenkins
Motivation
Short deployment cycles
8. Design for Failure
With microservices there are a lot of processes and lot of network traffic.
A lot can go wrong The code must assume failure can happen and handle it gracefully. Extensive logging and monitoring should be in place.
Mitigate it by
- Catch the Exception
- Retry
- Log the Exception
Monitoring
Checks CPU , Service up and running and raise altert if not.
popular monitoring tools
Application insights kubernetes
Motivation: Increase system's reliability.
9. Evolutionary Design
The move to Ms should be gradul no need to break everything apart start small and upgrade ech part seperately.
Summary
These are guidelines, not mandatory instructions Adopt what works for you Ms is rapidly changing follow new monitoring, logging, cloud services etc..
Important attributes
Componentization Organized around business capabilites Decentralized governance Decentralized data management when possible Infrastructure automation
Problems solved by MS
- Single Technology Platforms. Monolithy, all components must be developed using same dev platform. not always the best for the task. can't use specific platform for specific features future upgrade is a problem - need to upgrade the whole app
-> The Decentralized Governance attribute solves the single technology dev.
- Inflexible Deployment. With monolith, new deployment is always for the whole app. No way to deploy only part of app. Even when updating only one component - the whole codebase is deployed. Forces rigorous testing for every deployment Forces long dev cycles.
--> MS, the componentization via Services attributes solves it. --> Decentralized Data management - (If each ms has a single DB - we can then upgrade DB and Service so that by changing a single DB no other microservices is affected).
- Inefficient compute resources With monolith, compute resources (CPU and RAM are divided across all components. If specific component needs more resources - no way to do that Very inefficient
--> componentization via services attributes solves it. As each Ms runs in its own process We can allocate different resource to different services.
service 1 - 4 vCores, 8 GB RAM service 2 - 8 vCores, 8 GB RAM service 1 - 3 vCores, 16 GB RAM service 2 - 2 vCores, 8 GB RAM
- Large and complex With monolith, the codebase is large and complex. Every little change can affect other components Testing not always detects all the bugs. Very difficult to maintain Might make the system obsolete
--> componentization via services attributes solves it. --> Organized around business capablities - same team manages UI, API, Logic,DB.
Each Services has it well defined functionalities ie bounded code which is easier to mainain. we reduce mixing and
-
Complicated and expensive ESB.
With SOA, the ESB is one of the main components ESB can quickly become bloated and expensive as ESB tries to do everything - routing, data crunching, transformation etc.. Very difficult to maintain
--> Ms solves this as the Smart Endpoint and Dumb Pipes attributes solves it. but we should not allow service to service communication but go for application gateway & Discovery. Other APIs such as: GraphQL, gRPC
-
Lack of tooling
For SOA to be effective, short dev cycles were needed Allow for quick testing and deployment no tooling existed to support this no time saving was achieved.
how Ms solves -- the infrasture automation attribute solves it Automates testing and deployment provides short deployment cycles make arch efficient and effective.
Designing Microservices Architecture
Designing Microservices Architecture
Should be methodical Dont rush into development Plan more, code less - More you plan, the more you think about the overall system mapping, the more you know what you are going into , less u code, less bug and maintainance. Critical to the success of the system
Typical arch process
**Understand system requirement
->
**Understand non functional requirements
-
**Map the components
->
**Select the Technology stack
->
**Design the architecture
->
**Write archi document
->
**support the team
Map the components = Splitting to: Mapping, Communication Patterns.
Mapping single most important step which determines how the system will look in long run Once set - not easy to change
what exactly is the mapping the components
We define the various components of the system
Remember : Components == Service as opposed to libraries in monolith (network and its traffic is involved)
Mapping of components should be based on
- Biz requirements - So when mapping the component of the system we use the "business capability" as a frame for the component and the requirments are the actions the component can do (add order, update, delete etc)
The collection of requirements around a specific business capability
For example: The biz capablity can be - "Orders Management" meaning the system should manage orders received by a customers. This is a biz capablity and the requirements that support it, such as add new order, remove, update order calculate the amount of orders and so on. Each one of these requirements relate to the orders management capability.
So when mapping the component of the system we use the "business capability" as a frame for the component and the requirments are the actions the component can do.
- functional autonomy - The maximum functionality that does not involve other business requirements, so if our biz capablity is say, order processing, the service should handle everything related to order processing, but should not handle functionality that involve other capabilities. MS can do CRUD on order but not export all orders to other systems...as this should be done by other services...
for example : Retrieve orders made in the last week should be included. but get all the orders made by users aged 34 - 45 is a problem and should not be included - (this is not related to orders itself...and focuses on users age - but export orders to other microservices shouldnot be handled.
- data entities - Service is designed around well specified data entities. We focus developing specialized and specific entities that hold specific data and store ID's example: Order POJO holding customerId.
for example : orders, items,
--> Data can be related to other entities but just by ID Example : Order stores the customer ID. (MS can store customer ID but not Customer whole POJO itself). Example : Order stores the customer ID, so you can use this customerId and invoke customer MS to fetch customer data.
- data autonomy - Each Ms should have life on its own - relatd to data entity
Underlying data is an atomic unit. Service doesnot depend on data from other services to function properly.
Ex : employee service that relies on address service to return employee data. Everytime you have to invoke employee service you need to invoke address service to return employee's data.
solution : Store employees address as part of this service instead of seperate that makes our service fat but it is fine. ( develop MS based on business functionality)
Example:
ECommerce System
Ecom system has inventory, orders, customers , payment Lets see how these uses the above 4 rules of mapping the component
Business requirements
We have to
Inventory Order Customers Payment
Business Requirements Manage Inventory items Manage Orders Manage customer Perform payments
Functional Add, remove,update,qty Add,cancel, Add,update,remove Perform payments Autonomy calulate sum get accont details
Data Entities Items Orders,Shipping Customer,address, Payment history Address Contact details
Data autonomy none Related to Item by ID Related to orders byID None Related to customer by ID
Customers can use its ID and fetch order details from OrderService (single way) Customers can use its ID and fetch order details from OrderService (single way) and Order ID is sent to customer microservice to fetch customer details (2 way) both are fine.
How a mapping should be done - we should focus on the business requirements, functional autonomy, data entities and data autonomy.
Edge cases and how to deal :
Edge Case #1:
Retrieve all customers from NYC with total number of orders for each customer
Customer name no of orders david 16 rice 23 george 22
3 approaches
- Data Duplication - have orders data in customer service database, since data is read only it wont harm and no synchronization required.
Orders Service - Customer Service - this service having order service data.
-
Service Query - Customer service to invoke Order Service and fetch all customers from NYC with total number of orders for each customer using data autonomy ie order to have customerid and query order based on customer id.
-
Aggregation Service - Use another service ie. Aggregation Service which will invoke both Order and Customer service and use the data. (this approach need additional development)
Edge case 2 :
Retrieve list of all the orders in the system.
Problem lies here is volume of data and service wont stand.
Services are not designed for this scenario as data should be not too big.
find out whats the purpose of this query?
Use Report engine is the preferred mechanism for this and service wont suffer.
Cross Cutting Services (shoud be done early in the project)
Services that provide system wide utilities
Common examples:
Logging Caching User Management
Must be part of the mapping
Defining Communication Pattern
- Efficient communication b/w services is crucial as inter service communication b/w Ms present.
It's important to choose the correct comm pattern
Main patterns are
**1-to-1 Sync **
A service calls another service and waits for response Used mainly when 1st service needs the response to continue processing.
Is item in stock?
Orders ---------------------------------> Inventory
Pros : Immmediate response, error handling, easy to implment Cons : Performance
1-to-1 Async
Direct -- Spider Web situation may occur..Imagine what happens if one service is down...this change will impact whole system. This is against Ms loosely coupled design...
2 approach
- Service Discovery (Yello pages) - Console
- Gateway (Zuul) - service invoke gateway and gateway invokes the service. service only need to know gateway
we can either use service discovery (console) or Gateway pattern.
1-to-1 Async
Service calls another service and continues working Doesnot wait for response - Fire and Forget Used mainly when the 1st service wants to pass a message to the other service
Orders ------------handle payment---------> Payments (fire and forget)
Pros - Performance (on blocking)
Cons - needs more setup, troubleshootind difficult.
Orders Queue Payments RabbitMQ
Pub-Sub / Event Driven - A service wants to notify other services about something
The service has no idea how many services listen.
Doesnot wait for response - Fire and Forget
Used mainly when the 1st service wants to notify about an important event in the system
Orders ----------order cancelled----------> Customers, Inventory, Payment
Order service sent this cancellation to other services so payment is refunded, item is added to inventory.
Pros - perf, notify multiple service at once cons - needs more setup, difficult error handling, might cause load
how to implement pub-sub /event driven implmentation
Orders ------ > pub/sub -------------> payment ------------------>customers
Communication patterns summary
Choosing comm pattern is crucial as it affects performance, error handling, flow. impossible to reverse...
Selecting Technology Stack
The decentralized goverence allows selecting different tech stack for each service.
We will focus on backend platform and storage platforms.
there is no objective right or wrong
make it a concreate decision based on hard evidence.
Java, .net,php,python NOSQL mongodb,
Cache - stores in memory data for fast access, distributes data across nodes uses proprietary protocal, stores serializable objects.
Popular cache : redis
Object store - stores unstructured , large data Documents, Photos, Files
Popular stores : amazon s3, minio, azure blob storage
Design the Architecture
service arch is no diffeent from regular s/w based on the layers paradigm
Layers - reprsent horizontal functionality
expose user interface/api - UI
- expose api, json handling, auth
execute logic (access external system, validation) - Business Logic -valiation, enrichment, computations
save/retrieve data - Data access layer -connection handling -querying/saving data -transaction handling
why we need layers - 2 reason
-- force well formed and focused code -- modular
Code flow - UI -> BL -> Data access layer
Monolith to Microservices
Stratergies to break monlith to microservices
Shorten update cycle
Modularize the system
Save Costs
Modernize the system
Being attractive
Case Study
We need to know the functional requirments and for NRF we need ask
-
how many expected concurrent users? 1000
-
how many books will be managed? (data volumes system should support)- system storage to be planeed. 10000
-
how many borrowings in a day? 500 2 reasons if number is high - need to think about load action stored in db - datavolume in a day , month
-
what is desired SLA? mission critical? downtime of how many minutes higher the SLA the more robost the sytem and expensive hardware.
working 5 days 9 hours
Data volume
1 book record = 1KB 10,000 books=10MB 1 borrowing record = 500 bytes 500 borrowing/day -> 182k borrowing/year - 91MB/year.
Mapping the components
Ms - "organized around business capablities"
Design based on Business entities since is sucessfull
Business entitties.
Book Borrowing Customers
We can come up with Service now for Book,Borrowing and Customers
BooksService - used to manage the books inventory in the libaray do CRUD on this for Books.
a.This service manages the books just for librarian. b.Used by librarians c. has a storage db d. should be synchronous (immediate response) e.Does not depend on other service
should this be Synchronos or Async - We need immediate response
Main Functionalites:
a. Get book details b. Add new book c. remove book d. Delete book
Books Service API
get book details - GET /api/v1/book/{bookId} - 200 OK or 404 not found
Refer REST API Design Course -
Add new book POST /api/v1/book
update book PUT /api/v1/book/{bookId}
remove book DELETE /api/v1/book/{bookId}
Utilities
Notification Payment View Logging and monitoring
Borrowing Service
used to mange the borrowing of books, used by librarian, has storage synchronus/ doesnot depend on other services.
Shorten update cycle Modularize the system Save Costs Modernize the system Being attractive
Strategies for Breaking Monolith
New Modules as Services - Develop new modules as a service and expose it as REST
Pros
--Easy to Implement --Minimum code changes
Cons
--Takes time --End result is not pure microservice architecture
Separate Existing Modules to Services
Say you are seperating Shopping Cart and expose a Ms. U have Orders,Inventory Customers and Payments modules available.
If you separate existing module and wrap REST you need to consider the dependecies of other modules on this, statefullness of the module This code must be thorowly reviewed before seperate.
Pro
- End result is pure Microservices architecture
Cons
- Takes time
- A lot of code changes
- Regression testing required
Pros:
-
End result is pure Microservices arch
-
Opportunity for modernization
Cons
- Takes time
- Rigorous testing required
Complete Rewrite
Develop everything as existing system is very old and outdated technology wise. Code dependecies are too much.
AntiPatterns
No well defined services No Well Defined API Implementing cross cutting last Expanding Service Boundaries
No well defined services
- Negligent mapping results in bloated services
- Dependent functionality gets added continuously
- cretes a mini monolith
Focus on mapping and communication pattern here mapping - map coponents based on
a. business requirements b. functional autonomy c. data entities d. data autonomy
No Well Defined API
- API is the door to the service
- API Must be consistent
- API Must be versioned
- API Must be platform agnostic
- API Must be part of the design
API Design Example (providing such table help developer to understand better)
Get next list to be processed - GET /api/v1/lists/next?location=... Mark item as collected /available - PUT /api/v1/list/{listId}/item/{itemId} Export lists payment data POST /api/v1/list/{listId}/export
Implementing cross cutting last
-
Every system has cross cutting services (system-wide)
-
Logging
-
caching
-
Users Management
-
Authz & Authn
-
And more...
-
Should be implemented first
-
Other services are going to use them
-
No one likes to go back and work already developed.
Expanding Service Boundaries
- Every service has well defined boundaries
- Expanding these boundaries makes the service inefficient and bloated
- Its tempting - dont do that
- Many times new service should be used instead of expanding existing service boundaries..