MicroServices In Brief
Why do we need MicroServices?
A quick view (gist of earlier articles) of the current world and business need..
With an enormous hardware capacity at affordable price, abundance of data/information, organizations keen to build creative products, people need of quick, smart and personalized apps to make life easier.
As an aggregation of what business precisely want is
- a reliable piece of software that is easy to add features on,
- should serve growing customer base,
- an ability to bring ideas to life quickly,
- a service that is available at all times with access to global market.
What is a MicroService after all?
Micro Services allows all of this by adhering to certain key principles. Lets see how does it do it in details.
First lets check the best definition available on Micro Services
In short, the microservice architectural style is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are built around business capabilities and independently deployable by fully automated deployment machinery. There is a bare minimum of centralized management of these services, which may be written in different programming languages and use different data storage technologies.
— James Lewis and Martin Fowler
The definition may appear difficult but below explanation will make it easy to understand. Remember micro services characteristics are the crux so for every role it is important understand the crux.
We will see micro services key characteristics and how they map to and serve needed business results.
Mind your business 🙂 Micro Services are business focused.
At a very high level (enterprise level), think of different independent verticals first. E.g. in Banking we saw different verticals, personal banking, lending etc. Those could form the domain boundaries.
Then it be further logically categorized as sub divisions within the given domain. E.g. Retail personal banking will have sub divisions such as account creation/maintenance department, term deposit department & locker department. Similarly lending vertical will have several departments like loan underwriting, loan servicing & loan takeover.
In such a structure, a single cohesive and independent service represents a specific business function within a department. E.g. Issue a credit card, authorize a credit card, charge a credit card could be separate individual services.
This way a service represents a function within a business domain or a sub domain. This service has a bounded context within the given domain.
This helps in having a service single responsibility which it can do well. Also in controlling scope of service. It can quickly respond to the feature changes.This is because with logical categorization of the domain, identifying which service to change is easily possible. Since each service has small function to perform building additional features is quick as well.
In general in monoliths, there could be a similar analogy painted that applications are developed and maintained domain or sub domain wise.
However, adding new feature or changing existing feature is categorized in different layers of application i.e. UI, API, database, application server.These teams (usually operate in isolation) work on the same application component for building multiple different features for the same or different sub domain. Every business unit has its own context baked into the application and hence making code/feature changes for one BU can affect others. There are many horror stories around this in almost all organizations 🙂
With micro services every service or component is treated as a product which has definite offering through business contracts exposed for consumption. And the product teams are perpetual and cross functional. Meaning product teams like micro services are cohesive and will undertake all work i.e. designing a user interface to writing APIs to creating a persistence and facilitating deployment. Team takes the responsibility of guarding the product and not letting it pollute with the responsibilities and features it should not support. Also maintain it throughout.
Services are the first class citizen
In the Micro services world, services are the first class citizens; meaning that all business components are represented and built as a service.
Although a Micro service may use common or specific libraries for fulfilling its own function, when it is interacting with other function its always a service call. Instead of using a module or library within the client application build, use a service.
Communication happens over the network and it is not an in memory procedure (library) call.
Beauty of the approach is, this provides all the benefits that a ‘service’ aspect brings. A client (other service or software component) can consume the service without any change in its code or deployment since they are interacting with the service API with a standardized contract. Individual micro-service components are designed, developed, deployed and consumed as black boxes for other application. Since the communication over the network is more expensive than in an memory call, the service is expected to have cohesive boundaries.
Service has a single focus, it serves one purpose and it must do it well. This makes the service autonomous.
Service can be changed and deployed independently. This makes the overall system loosely coupled.
Micro services use service discovery mechanism. Meaning services declare their existence and responsibilities to the world and other services can explore and discover the capabilities. This approach promotes service reuse and in cases where business flows need multiple services to be used then respective services can be composed and orchestrated as well.
This provides benefits, changes to services can be done independently. It does not adversely impact overall business work flow or applications. Since service is an autonomous unit, it can be scaled independently. Also changes to part of the business can be done in much confident and reliable manner. Changes can be released in an incremental manner too. A given functionality or subset of it can be enhanced independently.
Self governed components
Services aka components are self governed i.e. no information or logic resides outside of the service which it is dependent upon to perform its function or complete its responsibility. Services own functional knowledge to fulfill a business capability as well all technical/operational dependencies such as libraries, configurations, database and run time environment too. Its a completely ready to use package.
Communication pattern within this a key aspect which would let us know how micro services are self governed.
In monolith applications, capabilities are implemented either as libraries or a remote call. These patterns create hard wired dependencies for the consumption so consumer is impacted when change is made. Also the application itself needs to be redeployed/rewired for a change in the library. Dependency on low level code components/details prevent applications to be self governed.
In SOA based structured backed by a message broker (ESB), message broker plays many major roles i.e.
- Message broker routes the communication/message
- It can transform the message (format),
- Since individual services are not programmed to communicate with other services message broker has business logic to orchestrate the business flow execution where it interacts with different services. Also known as service choreography
- It can apply business rules.
- Message broker supports versioning (multiple versions of a service for backwards compatibility), provides interfaces to allow multiple channels (e.g. flat file or SOAP/XML) to talk to the same underlying components.
In essence, ESB is doing lot of heavy lifting i.e implementing the business flows/features and services doing lighter operations. This again makes services too dependent on ESB and thereby are not self governed.
Micro services on the other hand, use light weight communication mechanism. Services have all the intelligence and use the message bus (RabbitMQ, AMPQ etc) merely for passing on the message. Message bus in this case does not act in any way on the same, its as dumb as its usage pattern. However message bus does enable asynchronous communication.
Synchronous communication between two services/components establishes dependency between consumer and producer(servicing component). Unless producer finishes its job, consumer really cant proceed.
Asynchronous communication, allows consumer and producer to function independently. Consumer would let producer know what it needs and proceeds with next steps. Producer when called provides acknowledgement of the request and once it is done with the respective function, provides result to the consumer. This greatly reduces the dependency and makes services self governing.
Resilience – Design for failure
Resilience is the capacity to recover quickly from difficulties or toughness.
How much applications are resilient determines the quality of services.
In MicroServices architecture one or more micro services choreograph or orchestrate the complete business work flow. Hence in this entire chain of services if one service fails or does not respond in time it would impact a to business. It is very essential that the design considers and guards itself against such failures. There are multiple aspects to this. Monitoring all the systems. Systems emitting and communicating their health periodically. Failed services either self heal or are taken out of the system and new healthy functioning systems replace those.
Each of the service design must consider and embrace failures from downstream services.
Automated tests should guarantee the quality of the build promoted to production. In production environment there should be period synthetic tests run to ensure that all the necessary applications and infrastructure components are up and running.
It is suggested to test the system with production like load, setup, traffic and duration to ensure the stable application behavior.
Sufficient logging and monitoring would give enough information to the product development team to further improve and make the system resilient.
Automation is one of the key pillars in the micro-services architecture. Automation is the technique of making an a process, or a system operate automatically.
In our context, do any software build, test, deploy tasks without any manual intervention. Automation is important to bring in agility in software development life cycle. Automation increases speed of delivery i.e. speed to market. Automation can be achieved from an end to end perspective i.e. from development to deployment.
There came a time where development build process was given a shape to be automated. Downloading the necessary libraries for the code, compile the code and create a consolidated build artifact. This then was extended to do builds upon successful unit test results. Similarly from manual testing, there was a transition to make use of UI, API test automation. QA Automation provided a quick way to validate the build and promote it further.
Providing quick and early feedback (especially on the failure) is necessary to correct mistakes and replay the respective activity i.e. build, test or deploy.
From testing perspective, functional, regression, acceptance, performance and security automated test tools evolved, improved and gotten matured to be used.
Continuous Integration and Continuous Deployment are the mechanisms which reveal the strength of automation.
Continuous Integration (CI) is a development practice where developers integrate code into a shared repository frequently, preferably several times a day. Each integration can then be verified by an automated build and automated tests.
With micro-service architecture development, where each function is a micro-service and each of the service changing, enhancing, there are lots of moving parts of the overall system. Hence having continuous integration, automated tests are necessary to get the overall system tested well and quicker as well. Else system may remain in broken shape.
Deployment automation allows applications to be deployed across the various environments used in the development process, and in the test as well as production environments. This greatly reduces the manual blocking efforts for deployment and reduces manual errors/inconsistencies in the process.
Reduction of manual efforts, elimination of human/accidental errors and repetitive accuracy are the core benefits of automation across any process, be it development, testing or deployment. It greatly improves the productivity of the Dev & Ops teams.
Each of the major steps with its sub-steps and preliminary checks for a pipeline i.e. build steps followed by test steps and then deployment tasks form a delivery pipeline. This pipeline is moves from source (source code version control tool) to destination (test or prod environment) in a uni directional fashion.
Continuous Deployment is a software development practice in which every code change goes through the entire pipeline (build, different types of rigorous automated tests and automated deployment) and is put into production, automatically typically resulting in many production deployments every day.
With cloud infrastructures, where the servers are provisioned on the fly on demand, automated deployment is essential. Since in automated deployment the configuration is done once and then it runs an autopilot mode thereafter.
As the process is configurable, all the process once created for an application can be reused for different other applications. This greatly saves time.
As there are many applications and environments, there is a need for automated monitoring and alerting mechanisms.
Especially on production, there are automated synthetic tests in place to continuously check the health of the system and take necessary actions if any e.g. replacing a faulty server instance with healthy one. Alerting mechanisms on lower environments could be sending an email on build or test failure, however in production it can be configured to page or phone call a person on support to act on failures.
Decentralization is another beauty of micro-services.
Decentralization is the process by which the activities of an organization, particularly those regarding planning and decision-making, are distributed or delegated away from a central, authoritative location or group.
In an enterprise, there are different business flows, use cases. Today there are many technology & tools options available which can help in specific use case. Hence using different choices of technology is possible and needed as well.
With the monolithic applications or centralized and standardized tools/tech approach a specific option is finalized and followed there onward. There are cases where the selected option is not a good fit but since entire application wears a particular choice it is not possible to use another option.
Since micro-services are autonomous and independent, every micro-service can neatly evaluate its use case, different flows catering a functionality and then decide the implementation choice. E.g. using a SQL database vs a NOSQL or using Scala vs java vs C#. Imagine these decision being taken at a team level vs at higher level in the organization hierarchy.
In micro-services architecture you will find Polyglot teams working on different technologies of UI, API, persistence etc.
Decentralization enables using best tool for the given scenario. This happens across development,QA, operations activities. It also allows to embrace upcoming and latest choices for new feature development. Upon learning, the same success and learning can be applied to other services built earlier.
With decentralization, persistence needs a deep thought and plan. Since persistence is something that every business falls back on when it comes to having a source of truth. Transnational data, reporting data, fulfillment functions, analytics reports etc. Each of these have a different nature and purpose. Some need real time processing, some need aggregated analysis etc. For each of these there is a possible different data model and different database as well.
Another important aspect is, in micro-services transaction is distributed across different services hence maintaining consistency is essential.
Ownership: You build and you run it.
In many cases, it is like you build it and someone else runs and curses you 🙂
In micro-services, a team owns an individual micro-service meaning the team is composed of different roles, a business analyst, designer, developers, automation testers . Referred all of the roles and personas together as a development team. We will talk about the team traits and functions in Agile practices section.
Development is involved in discussion which formulate the need of the product and its features.
Yes product and not an application or module. There is a difference in perception, position and approach with these.
Product is perpetual. Its constantly being work upon and taken care after it is live to customer (i.e. reaching production) Unlike application where its build by someone, maintained by some other team and supported by the another team, product is owned by team. The team builds it, takes it to production, maintains and supports as well.
This approach allows development team to participate from product inception to its behavior and usage pattern after it goes to production. It also enables them to understand the consumption pattern, tune & optimize the service in its performance, operational aspects.
The team knows the functions of the micro-service in detail and rationale of design & code inline with the functions. This helps in addressing customer needs in a better way and double check on if customers expectations are met.
This way, a piece of software is not disowned and thrown in different departments (Dev, Support etc.), and it gets love, care and affection from day one as it born.
Lets explore each area which makes transformation possible.