Microservice Architecture design thinking


Introduction
This document explains microservices based architecture, which should be treated as reference architecture while designing microservices based architecture to solve given problem statement. Apart from explaining all component shown in architecture this document suggests some tools which can be used for those components. This document only presents a basic architecture of a imaginary problem and must not be treated as solution for any problem statement
Audience
The audience of this documents are all freshers and team lead which are being involved in solution design activities for a given problem statement.
Design Considerations
This section defines the identified major application design goals, assumptions and constraints that make the basis of the internal design and architecture of system. The technologies to be used for the development of the application are also suggested as applicable.
  • Assumptions
·         This is assumed that, this architecture design will only be used as reference not as actual solution for any problem statement. Each problem statement is unique and must have through to design and analysis phase to have a solution architecture of its own.
  • General Constraints
    • Application response should not take more time than specified in problem statement (if defined else assume it to be 5 Sec) to load.
    • If response take longer time than specified, it should return the response with some promise of delivery of actual response later (promise does not mean JavaScript “promise”).
    • Only users who are authenticated and authorised for the system can only access the system.
    • Sensitive information will be encrypted for storing in database like user password.
    • The deletion of records will be soft deletion until specified in problem statement.
Reference Architecture
Solution Architecture Diagram


  Component Description
A.            Firewall
A firewall is a network security device that monitors incoming and outgoing network traffic and decides whether to allow or block specific traffic based on a defined set of security rules.
Firewalls have been a first line of defence in network security for over 25 years. They establish a barrier between secured and controlled internal networks that can be trusted and untrusted outside networks, such as the Internet.
A firewall can be hardware, software, or both. For more please follow this Link.

B.            Load Balancer
A load balancer is a device that distributes network or application traffic across a cluster of servers. Load balancing improves responsiveness and increases availability of applications.
A load balancer sits between the client and the server farm accepting incoming network and application traffic and distributing the traffic across multiple backend servers using various methods. By balancing application requests across multiple servers, a load balancer reduces individual server load and prevents any one application server from becoming a single point of failure, thus improving overall application availability and responsiveness. For more please follow this Link

C.            Web Apps
WebApp are UI part of the application which is responsible for providing only user interface to users, where users can be human, another hardware device or any virtual system which needs to interact with system. This system holds only presentation logic and must only contain presentation logic and must not have any other responsibility. For any other responsibilities to perform they depends upon backend services which handle all business logic processes and data manipulation tasks. These web Apps communicate over http/https protocol, preferred way of communication is on https which is secured version of http - Hyper Text Transfer Protocol.
D.           Session Provider
WebApp uses http as protocol to interact with user to provide services, but http or https are stateless protocol. When we say stateless that means WebApp has no way to know if you have requested anything before or not. You can think of session as managed memory location which allows WebApp to know what you requested before.
Let’s take example of group discussion in real life when multiple people are talking to you and you are replying to everyone according to what they are talking about. This “about” is context which is made up of more than one statement they have given to you while talking you. To answer each question, you remember what they have said earlier and what they are saying now so you can respond accordingly. To remember you need your mind’s memory so that you know what they said earlier, and this is what session for WebApp.
WebApp keep talking to multiple users and number can range to 0 user to million users. Each request that came to them are transformed in suitable request object by underlying framework/library, session is also assigned to requests in this process.
As we can understand that request must be created as fast as possible because session creation/retrieval is part of that then it should be as fast as possible. To achieve this we need to store the sessions in fastest memory of computer, so that it can be created and retrieve as fast as possible. Computer’s RAM is only fastest memory available in computer, but it has one drawback that it does not retain the data if system crashes or system gets power down.
Now these days we have efficient, fast and reliable in memory NoSQL   databases and are widely used for cache management and session providers, like REDIS or GridGrain etc.
Tips: Using in-memory session provider or other providers decision should be taken as per requirement, its not universal rule that one must use In-memory provider or persistent provider. No option is bad, it just that trade off for speed, security and reliability matters along with other features that are important.
E.            Service Discovery
Services typically need to call one another. In a monolithic application, services invoke one another through language-level method or procedure calls. In a traditional distributed system deployment, services run at fixed, well known locations (hosts and ports) and so can easily call one another using HTTP/REST or some RPC mechanism. However, a modern microservice-based application typically runs in a virtualized or containerized environment where the number of instances of a service and their locations changes dynamically.
Consequently, you must implement a mechanism for that enables the clients of service to make requests to a dynamically changing set of ephemeral service instances.
·         Problem
How does the client of a service - the API gateway or another service - discover the location of a service instance?
·         Forces           
o    Each instance of a service exposes a remote API such as HTTP/REST, or Thrift etc. at a particular location (host and port)
o    The number of services instances and their locations changes dynamically.
o    Virtual machines and containers are usually assigned dynamic IP addresses.
o    The number of services instances might vary dynamically. For example, an EC2 Autoscaling Group adjusts the number of instances based on load.
·         Solution
When making a request to a service, the client makes a request via a router (a.k.a load balancer) that runs at a well known location. The router queries a service registry, which might be built into the router, and forwards the request to an available service instance. 
For more details please follow this link

Source:Google search

 F.            API Gateway
An API gateway is programming that sits in front of an application programming interface (API) and acts as a single point of entry for a defined group of microservices. Because a gateway handles protocol translation, this type of front-end programming is especially useful when clients built with microservices make use of multiple, disparate APIs.
A major benefit of using API gateways is that they allow developers to encapsulate the internal structure of an application in multiple ways, depending upon use case. This is because, in addition to accommodating direct requests, gateways can be used to invoke multiple back-end services and aggregate the results.
Because developers must update the API gateway each time a new microservice is added or removed, it is important that the process for updating the gateway be as lightweight as possible. Therefore when evaluating API gateways, it's important for developers to look at features the vendor has added to differentiate its product from the competition.
In addition to exposing microservices, popular API gateway features include functions such as:
·         Authentication
·         Security policy enforcement
·         Load balancing
·         Cache management
·         Dependency resolution
·         Contract and service level agreement (SLA) management
For more details please follow this link
For example, we can use Kong API gateway, it’s a NodeJS based open source gateway which is having multiple useful features. We can use it here as API gateway and load balancer.
G.            Microservices
This design suggests backend (Business logic and Data Access logic) should be encapsulated in microservices depending upon problem statement.
We divide different module or component to smallest service and that service is called “Microservices”, normally these services are developed to be REST services, which provide wider spectrum of client accessibility as almost all devices which has network access to service can send request via http and get response.  
According to this design we have multiple WebApp(s) deployed under load balancer and they have sole responsibility of UI handling no other processing, all required business logic processing and data related operations are handled by microservices.
We have multiple set of microservices configured under load balancer(s) which act kind of availability zones for application as if one availability zone dies or get cut off by some reason then other one can be trusted to deliver same response while suffering one can get treated and come alive again.
H.           Database - DB
All application needs to store and process data for any request made to it. Out design shows multiple DBs in “Solution Architecture Diagram”, following master- slave replication of databases.
There are number of ways that one can use databases in microservices, one suggestion which most the people follow for microservices is that “Each microservice must have it own database and must not share it with other”.  It is being followed so widely that it seems like rule for creating microservices, there is no such rules it all depends on the requirement of problem statement. If system has such requirement that need such deployment, then we can and should develop and maintain databases for each service and all complexities that are induced must be handled properly.   
There are different types of databases and each database offer specific feature very well and have proven benchmark for certain type of use case. One database can give you very robust transactions for data integrity and other can provide you flexible schema to store records. There are database which can be configured to give you different feature with trade off on feature like MySQL. Configuration
Each web application, microservices has its own set of environment related configuration and need them for providing services as per the requirement and and these configuration need to be persisted somewhere (either in file or in database) so that when application need to start or restart then these configuration can be accessed with ease.
There are number of ways this can be implemented and most widely used ways are
·         Configuration Service, this service can be either REST based or soap based exposed via tcp protocol for faster access as its clients are limited and defined.
·         Configuration Library, this library are generic library which are directly linked with its host service/application and provide a means of managing configurations
In microservice environment this design will recommend you to have configuration service if possible and can fetch configuration from database but again this largely depend on requirement how it should be.
I.             Caching
In computing, a cache is a high-speed data storage layer which stores a subset of data, typically transient in nature, so that future requests for that data are served up faster than is possible by accessing the data’s primary storage location. Caching allows you to efficiently reuse previously retrieved or computed data.
The data in a cache is generally stored in fast access hardware such as RAM (Random-access memory) and may also be used in correlation with a software component. A cache's primary purpose is to increase data retrieval performance by reducing the need to access the underlying slower storage layer.
Trading off capacity for speed, a cache typically stores a subset of data transiently, in contrast to databases whose data is usually complete and durable. We normally keep those records which are of static in nature or which are not frequent changing, because we do so, then it will add more cost as we may have to keep updating database and cache frequently more CPU and more memory for each request as we are hitting not just database but cache also.
We have in-memory database like REDIS to be used for such requirement, we should analyse requirement and then choose cache management strategy.
For more details please follow this link
J.             Logging
Logging is very important part of any application it can tell what application is doing now and what happened at what time in past. We can develop application/services to have extensive logging and then configure the level of log that should be generated, so if at times we need to have detailed logging to solve or observe application behaviour then we can use logging.
Each development environment has its set of options for logging for NodeJS we can use “Winston” logging package and it support console, file and api logging.
For more details on Winston logging please follow this link
K.            Security
This component provides encryption, encoding and other such functionality to all the web applications and services. This is used while we are dealing with sensitive information which needs to be hidden from public world and need treatment even before storing it in secure database. Only intended person should be able to get what he/she has or given ownership of.
While said that, application and services should be running on secured protocol as per requirement.
We can use JWT for authentication of user requests and authorize him/her. Authentication service will be responsible for authenticating the user and generating Jwt, sending it to user. User will send that jwt in each request header for further interaction.
L.            Exception Handling
Exception handling is one of foundation pillar of any application which is expected to be of
·         Good performance
·         Robust
·         Developer friendly
·         Maintainable
·         Scalable
And list goes on.
This design suggest that exception handling should be planned and standardized for whole application, error code must be defined and documented with their reason of happening and how/what a user should do to correct them if that applies to them, so that they can be available to not only to developer but also to the end users if they ever need to know about them, think of a case that you developed an application which has certain integration service. Now client wants to integrate third party application and while interacting with they get errors, they should be able to understand what is happening and why.
Each technology stack has its own way of handling the exceptions and reacting to it, Following are some basic rule of thumb for exception handling
·         If your functions are named well, using verbs (actions) and nouns (stuff to take action on) then throw an exception if your method can't do what it says it can. For example, SaveTransaction(). If it can't save the Transaction - it can't do what it promised - then throw an exception. That might be for a number of reasons.
·         Never duplicate exception, means you have defined an exception not sending parameter in method as argument in one module and now you need to throw exception for same scenario in other module then don’t create another exception type but use same one and for reason that exception handling library/framework should be common to all application component and it is kept in cross cutting concerns.
·         There are reasons to swallow exceptions (catch (Exception ex)) but they are few and far between and they should be logged if appropriate and documented liberally. Remember always if you do catch an exception and intend to rethrow it, then use throw; not throw ex; lest you lose your call stack and good bits of context.
·         Create a global error handler that logs everything.
M.          Communication
This design suggests us to develop multiple components having separate responsibility to perform and manage. Now they need to work together to achieve same services for which this whole solution is designed, and work together they need to communicate, they need to be able to send information/data to another component and receive response in reliable manner.
To make all these components, able to communicate each other in standard way so that communication is reliable, secure and provide required efficiency we need to have a standard generic library which should be easy to integrate and use. Below are some points which should be kept in mind while developing any library/framework for any solution (if tech stack allows)
·         Resiliency
There may be dozens of even hundreds of instances of any microservices. An instance can fail for any number of reasons. There can be node-level failure, such as hardware failure or a VM reboot. An instance might crash, or be overwhelmed with requests and unable to process any new requests. Any of these events can cause a network call to fail. There are two design patterns that can help make services-to-service network calls more resilient:
·         Retry
A network call may fail because of a transient fault that goes away by itself. Rather than fail outright, the caller should typically retry the operation a certain number of times, or until a configured time-out period elapse. However, if an operation is not idempotent, retries can cause unintended side effects. The original call might succeed, but the caller never gets a response. If the caller retries, the operation may be invoked twice. Generally, it’s not safe to retry POST or PATCH methods, because these are not guaranteed to be idempotent.
·         Circuit Breaker
Too many failed requests can cause a bottleneck, as pending request accumulate in queue. These blocked requests might hold critical system resources such as memory, threads, database connections , and so on , which can cause cascading failures. The circuit Breaker pattern can prevent a service from repeatedly trying an operation that is likely to fail.

·         Load Balancing
When service “A” calls Service “B” then it should reach to a healthy service “B” to serve the response.
·         Distributed tracing
A single transaction may span multiple services. That can make it hard to monitor the overall performance and health of the system. Even if every service generated logs and metrics, without some way to tie them together, they are of limited use.
·         Service versioning
When a team deploys a new version of a service, they must avoid breaking any other services or external clients that depend on it. In addition, you might want to run multiple versions of a service side-by-side, and route requests to a particular
·         TLS encryption and mutual TLS authentication
For security reasons, you may want to encrypt traffic between services with TLS and use mutual TLS authentication to authenticate callers.
          There are two ways to communicate among services
·         Synchronous communication
Normally services communicate using request- response manner which is called synchronous communication. It is most widely used way of communication. Client get response within acceptable timeframe and if not then request is aborted and client may try again.
·         Asynchronous Communication
While working with microservices we cannot always expect to get response within milliseconds or minutes sometimes processing can take time and that time can be from minutes to hours, for such scenarios we have option to go for “Asynchronous Communication”. According to this concept, a client sends request to another service or application and instead of final response it gets acknowledgement or request received or kind of promise to get a final response. This client does not get blocked by keep waiting for the response and keeping network connection to that service/application alive.
Queue can be used to handle request when we are using event-based communication. Event based communication are done in Publisher- Subscriber environment where one service subscribe another service to listen to event which are send in event bus (implemented via queue based solution like “RabbitMQ”,” Azure Service Bus”, Database can always act as one) But we need to make sure that queue system we are using, is matching the requirement in hand. Always remember that nothing is infinite and has cost and availability to a limited extent.
                        For more details on communication please follow below links
·         Interservice communication

Comments