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.

http://www.tutisani.com/software-architecture/modular-software-architecture.html#:~:text=Express%20and%20easily%20manage%20complex,by%20grouping%20them%20into%20Modules.

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

  1. Quick Development - avoid inter politics as we have one team.
  2. 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

  1. Increase customer's satisfaction.
  2. 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..

  1. Which dev platform to use
  2. Which DB to use
  3. 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

  1. 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

  1. Catch the Exception
  2. Retry
  3. 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

  1. 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.

  1. 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).

  1. 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

  1. 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

  1. 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

  2. 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

  1. 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.

  1. 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.

  1. 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.

  1. 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

  1. 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.

  1. 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.

  2. 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

  1. Service Discovery (Yello pages) - Console
  2. 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

  1. how many expected concurrent users? 1000

  2. how many books will be managed? (data volumes system should support)- system storage to be planeed. 10000

  3. 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

  4. 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..