Microservices Architecture is one of the methods for implementing a service-oriented architecture.
This training helps you gain expertise in developing a Microservices Architecture-based solution. Apply Microservices principles to specific business requirements to build a scalable & performing solution. After completing this training, you will have gained the knowledge about various Microservices architectural styles, how to select the appropriate architecture design and how Netflix has used Microservices to scale.

Evolution of Microservices

Learning Objectives: In this Module, you will learn how Microservices have evolved over time and how different is Microservices from SOA. In addition, you will get to know about different architectures and where does Microservices architecture fit.
Topics:
  • Monolithic Architecture
  • Distributed Architecture
  • Service oriented Architecture
  • Microservice and API Ecosystem
  • Microservices in nutshell
  • Point of considerations
  • SOA vs. Microservice
  • Microservice & API
Learning Objectives: Learn the various principles of REST, the various characteristics of Microservices, the importance of messaging in Microservices architecture, and the concept of distributed transactions.
Topics:
  • REST Architecture principles
  • Microservice Characteristics
  • Inter-Process Communications
  • Microservice Transaction Management
Learning Objectives: This Module gives you an insight into Domain Driven Design, the approach called Big Ball of Mud, the approaches and their strategies that can be used while moving from Monolithic to Microservices.
 Topics:
  • Domain Driven Design
  • Big Mud Ball to Sweet Gems
  • Untangling the Ball of MUD
  • Kill the MUD Ball growth
  • Repackaging/Refactoring
  • Decouple the User interface and Backend Business Logic
  • MUD Ball to Services
  • Microservice Design Patterns
  • Microservice Architecture Decisions
Hands-on:
  • Setting up the root project
  • Spring Boot – Hello World
  • Returning json entity as response
  • Spring Boot dev tools
  • Intro to Lombok
  • Adding Items to Mongo DB
  • Querying Mongo
  • Accessing an SQL database
  • Spring Data Rest and HATEOAS
  • Connecting to an Elasticsearch Server
  • Searching our Elasticsearch Server
Learning Objectives: Know why security is an important factor to be considered in Microservices. Learn what are the various best practices in Microservice security design, and what techniques can be used to implement security.
Topics:
  • Why is Security important?
  • Microservice Security Principles
  • Microservice Security techniques
  • Access Tokens
  • Oauth 2.0
  • How to secure a Microservice using OAuth 2.0
Learning Objectives: Learn the different testing strategies that can be implemented in Microservices, how Spring Boot features help in testing Microservices, and the various testing tools that are available to be used.
Topics:
  • Testing scenarios and strategy
  • Test at Different Levels
  • Testing Best Practice for Microservices
 
Skills:
  • Testing methodology
  • How to test Microservices

Microservices is an architectural style which structures and application as a collection of loosely coupled, independently maintainable, testable and deployable services which are organized around business capabilities.

If you have a business focus and you want to solve a use case or a problem efficiently without the boundaries of technology, want to scale an independent service infinitely, highly available stateless services which are easy to maintainable and managed as well as independently testable then we would go ahead and implement Microservices architecture.

There are two cases.

  • If you already have a monolith application and it grows to an extent where there are problems in scaling or we are not able to reutilize the components/modules/services across different projects/platforms and there is a need to do so. As well as at the same time implementing new features is painful and more error-prone and it is difficult to scale further.
  • For new applications where implementation has not started yet started, we can think of a business case to be efficiently implemented, which can be easily maintainable, testable and scalable in the future and might be used across other projects/products/platforms at the same time.

One should have unit and integration tests where all the functionality of a microservice can be tested. One should also have component based testing.

One should have contract tests to assert that the expectations by the client is not breaking. End-to-end test for the microservices, however, should only test the critical flows as these can be time-consuming. The tests can be from two sides, consumer-driven contract test and consumer-side contract test.

You can also leverage Command Query Responsibility Segregation to query multiple databases and get a combined view of persisted data.

In a cloud environment where docker images are dynamically deployed on any machine or IP + Port combination, it becomes difficult for dependent services to update at runtime. Service discovery is created due to that purpose only.

Service discovery is one of the services running under microservices architecture, which registers entries of all of the services running under the service mesh. All of the actions are available through the REST API. So whenever the services are up and running, the individual services registers themselves to service discovery service and service discovery services maintains heartbeat to make sure that those services are alive. That also serves the purpose of monitoring services as well. Service discovery also helps in distributing requests across services deployed in a fair manner.

Instead of clients directly connecting to load balancer, in this architectural pattern the client connects to the service registry and tries to fetch data or services from it.

Once it gets all data, it does load balancing on its own and directly reaches out to the services it needs to talk to.

This can have a benefit where there are multiple proxy layers and delays are happening due to the multilayer communication.

In server-side discovery, the proxy layer or API Gateway later tries to connect to the service registry and makes a call to appropriate service afterward. Over here client connects to that proxy layer or API Gateway layer.

Assuming that the majority of providers using microservices architecture,

  • One can scale the system by increasing the number of instances of service by bringing up more containers.
  • One can also apply to cache at microservice layer which can be easy to manage as an invalidation of the cache can be done very easily as the microservice will be the single source of truth.
  • Caching can also be introduced at the API Gateway layer where one can define caching rules like when to invalidate the cache.
  • One can also shut down some containers when the requirement is less. That is, scale down.

Microservices Architecture is a style of developing a scalable, distributed & highly automated system made up of many small autonomous services. It is not a technology but a new trend evolved out of SOA.

There is no single definition that fully describes the term “microservices”. Some of the famous authors have tried to define it in the following way:

  1. Microservices are small, autonomous services that work together.
  2. Loosely coupled service-oriented architecture with bounded contexts.
  3. Microservice architecture is a natural consequence of applying the single responsibility principle at the architectural level.

Microservices are a continuation to SOA.

SOA started gaining ground due to its distributed architecture approach and it emerged to combat the problems of large monolithic applications, around 2006.

Both (SOA and Microservices) of these architectures share one common thing that they both are distributed architecture and both allow high scalability. In both, service components are accessed remotely through remote access protocol (RMI, REST, SOAP, AMQP, JMS, etc.). both are modular and loosely coupled by design and offer high scalability. Microservices started gaining buzz in late 2000 after the emergence of lightweight containers, Docker, Orchestration Frameworks (Kubernetes, Mesos). Microservices differ from SOA in a significant manner conceptually –

  1. SOA uses Enterprise Service Bus for communication, while microservices uses REST or some other less elaborate messaging system (AMQP, etc). Also, microservice follow “Smart endpoints and dumb points”, which means that when a microservice needs another one as a dependency, it should use it directly without any routing logic/components handling the pipe.
  2. In microservices, service deployment and management should be fully automated, whereas SOA services are often implemented in deployment monoliths.
  3. Generally, microservices are significantly smaller than what SOA tends to be. Here we are not talking about the codebase here because few languages are more verbose than the other ones. We are talking about the scope (problem domain) of the service itself. Microservices generally do one thing in a better way.
  4. Microservices should own their own data while SOA may share a common database. So one Microservices should not allow another Microservices to change/read its data directly.
  5. Classic SOA is more platform-driven, while we have a lot of technology independence in case of microservices. Each microservice can have its own technology stack based on its own functional requirements. So microservices offers more choices in all dimensions.
  6. Microservices make an as little assumption as possible on the external environment. A Microservice should manage its own functional domain and data model.

Bounded Context is a central pattern in Domain-Driven Design. In Bounded Context, everything related to the domain is visible within context internally but opaque to other bounded contexts. DDD deals with large models by dividing them into different Bounded Contexts and being explicit about their interrelationships.

Monolithic Conceptual Model Problem 

A single conceptual model for the entire organization is very tricky to deal with. The only benefit of such a unified model is that integration is easy across the whole enterprise, but the drawbacks are many, for example:

  1. At first, it’s very hard to build a single model that works for the entire organization.
  2. It’s hard for others (teams) to understand it.
  3. It’s very difficult to change such a shared model to accommodate the new business requirements. The impact of such a change will be widespread across team boundaries.
  4. Any large enterprise needs a model that is either very large or abstract.
  5. Meaning of a single word may be different in different departments of an organization, so it may be really difficult to come up with a single unified model. Such a model, even if created, will lead to a lot of confusion across the teams.
  1. High Cohesion – Small and focussed on doing one thing well. Small does not mean less number of lines of code because few programming languages are more verbose than others, but it means the smallest functional area that a single microservices caters to.
  2. Loose Coupling – Autonomous – the ability to deploy different services independently, and reliability, due to the ability for a service to run even if another service is down.
  3. Bounded Context – A Microservice serves a bounded context in a domain. It communicates with the rest of the domain by using an interface for that Bounded context.
  4. Organisation around business capabilities instead of around technology.
  5. Continuous Delivery and Infrastructure automation.
  6. Versioning for backward compatibility. Even multiple versions of same microservices can exist in a production environment.
  7. Fault Tolerance – if one service fails, it will not affect the rest of the system. For example, if a microservices serving the comments and reviews for e-commerce fails, the rest of the website should run fine.
  8. Decentralized data management with each service owning its database rather than a single shared database. Every microservice has the freedom to choose the right type of database appropriate for its business use-case (for example, RDBMS for Order Management, NoSql for catalogue management for an e-commerce website)
  9. Eventual Consistency – event-driven asynchronous updates.
  10. Security – Every microservice should have the capability to protect its own resources from unauthorized access. This is achieved using stateless security mechanisms like JSON Web Token (JWT pronounced as jot) with OAuth2.
Microservices Architecture training introduces you to the concept of Microservices that are small, lightweight, process-driven components. So, Microservices are the next important thing in designing scalable, easy-to-maintain applications. This not only makes application development easier but also offers great flexibility and lets you utilize various resources optimally. If you want to build an enterprise-ready implementation of the Microservices architecture, then this course is the first step for you!
In this Microservices Architecture training, we will start by giving you a deep understanding of the core Microservices concepts and principle with insight in how they have evolved. We will walk you through the complete life cycle – from design to development to testing; including cross-layer concepts such as how to secure Microservices.
After completing, coursesit Microservice training, you will be able to:
  • Understand and differentiate between various Microservices Architectural styles
  • Apply Microservices Architecture principles
  • Know how to make the appropriate Microservice Architecture decision
  • Develop and test a Microservice
  • Know what technologies can be used to enable Microservices with an example

Microservices Architecture, or simply Microservices, is a unique method of developing software systems as a suite of independently deployable, small, modular services in which each service runs a unique process and communicates through a well-defined, lightweight mechanism to serve a business goal.  Thanks to its scalability, this architectural method is considered ideal when you have to enable support for a range of platforms and devices—spanning across the web, mobile, Internet of Things, and so on. Because of its flexibility, you can also use this method when you’re not sure what kind of devices you’ll need to support in an increasingly Cloud-based future.

There are no prerequisites for attending this Microservice course. Understanding of programming languages such as Java, basic understanding and familiarity with Spring Boot framework and building  Java applications would be useful to execute Case Study and Project.

  • Application Architects
  • Software Architects
  • Application Developers
  • Developer working on Web, Cloud, Mobile, and other social technologies

Embracing microservices architecture brings many benefits compared to using monolith architecture in your application, including:

  • Autonomous Deployments

The decentralized teams working on individual microservices are mostly independent of each other, so changing a service does not require coordination with other teams. This can lead to significantly faster release cycles. It is very hard to achieve the same thing in a realistic monolithic application where a small change may require regression of the entire system.

  • Culture Shift

Microservices style of system architecture emphasizes on the culture of freedom, single responsibility, autonomy of teams, faster release iterations and technology diversification.

  • Technology Diversification

Unlike in monolithic applications, microservices are not bound to one technology stack (Java, .Net, Go, Erlang, Python, etc). Each team is free to choose a technology stack that is best suited for its requirements. For example, we are free to choose Java for a microservice, c++ for others and Go for another one.

  • DevOps Culture

The term comes from an abbreviated compound of “development” and “operations”. It is a culture that emphasizes effective communication and collaboration between product management, software development, and operations team. DevOps culture, if implemented correctly can lead to shorter development cycles and thus faster time to market.

Polyglot persistence is all about using different databases for different business needs within a single distributed system. We already have different database products in the market each for a specific business need, for example:

  • RDBMS

Relational databases are used for transactional needs (storing financial data, reporting requirements, etc.)

  • MongoDB

Documented oriented databases are used for documents oriented needs (for e.g. Product Catalog). Documents are schema-free so changes in the schema can be accommodated into the application without much headache.

  • Cassandra/Amazon DynamoDB

Key-value pair based database (User activity tracking, Analytics, etc.). DynamoDB can store documents as well as key-value pairs.

  • Redis

In memory distributed database (user session tracking), its mostly used as a distributed cache among multiple microservices.

  • Neo4j 

Graph DB (social connections, recommendations, etc)

Benefits of Polyglot Persistence are manifold and can be harvested in both monolithic as well as microservices architecture. Any decent-sized product will have a variety of needs which may not be fulfilled by a single kind of database alone. For example, if there are no transactional needs for a particular microservice, then it’s way better to use a key-value pair or document-oriented NoSql rather than using a transactional RDBMS database.

The Twelve-Factor App is a recent methodology (and/or a manifesto) for writing web applications which run as a service.

  • Codebase

One codebase, multiple deploys. This means that we should only have one codebase for different versions of a microservices. Branches are ok, but different repositories are not.

  • Dependencies

Explicitly declare and isolate dependencies. The manifesto advises against relying on software or libraries on the host machine. Every dependency should be put into pom.xml or build.gradle file.

  • Config

Store config in the environment. Do never commit your environment-specific configuration (most importantly: password) in the source code repo. Spring Cloud Config provides server and client-side support for externalized configuration in a distributed system. Using Spring Cloud Config Server you have a central place to manage external properties for applications across all environments.

  • Backing services 

Treat backing services as attached resources. A microservice should treat external services equally, regardless of whether you manage them or some other team. For example, never hard code the absolute url for dependent service in your application code, even if the dependent microservice is developed by your own team. For example, instead of hard coding url for another service in your RestTemplate, use Ribbon (with or without Eureka) to define the url:

  • Release & Run 

Strictly separate build and run stages. In other words, you should be able to build or compile the code, then combine that with specific configuration information to create a specific release, then deliberately run that release. It should be impossible to make code changes at runtime, for e.g. changing the class files in tomcat directly. There should always be a unique id for each version of release, mostly a timestamp. Release information should be immutable, any changes should lead to a new release.

  • Processes 

Execute the app as one or more stateless processes. This means that our microservices should be stateless in nature, and should not rely on any state being present in memory or in the filesystem. Indeed the state does not belong in the code. So no sticky sessions, no in-memory cache, no local filesystem storage, etc. Distributed cache like memcache, ehcache or Redis should be used instead

  • Port Binding 

Export services via port binding. This is about having your application as standalone, instead of relying on a running instance of an application server, where you deploy. Spring boot provides a mechanism to create a self-executable uber jar that contains all dependencies and embedded servlet container (jetty or tomcat).

  • Concurrency 

Scale-out via the process model. In the twelve-factor app, processes are a first-class citizen. This does not exclude individual processes from handling their own internal multiplexing, via threads inside the runtime VM, or the async/evented model found in tools such as EventMachine, Twisted, or Node.js. But an individual VM can only grow so large (vertical scale), so the application must also be able to span multiple processes running on multiple physical machines. Twelve-factor app processes should never write PID files, rather it should rely on operating system process manager such as systemd – a distributed process manager on a cloud platform.

  • Disposability 

The twelve-factor app’s processes are disposable, meaning they can be started or stopped at a moment’s notice. This facilitates fast elastic scaling, rapid deployment of code or config changes, and robustness of production deploys. Processes should strive to minimize startup time. Ideally, a process takes a few seconds from the time the launch command is executed until the process is up and ready to receive requests or jobs. Short startup time provides more agility for the release process and scaling up; and it aids robustness because the process manager can more easily move processes to new physical machines when warranted.

  • Dev/Prod parity 

Keep development, staging, and production as similar as possible. Your development environment should almost identical to a production one (for example, to avoid some “works on my machine” issues). That doesn’t mean your OS has to be the OS running in production, though. Docker can be used for creating logical separation for your microservices.

  • Logs 

Treat logs as event streams, sending all logs only to stdout. Most Java Developers would not agree to this advice, though.

  • Admin processes 

Run admin/management tasks as one-off processes. For example, a database migration should be run using a separate process altogether.

  1. DevOps is a must, because of the explosion of a number of processes in a production system. How to start and stop the fleet of services?
  2. The complexity of distributed computing such as “network latency, fault tolerance, message serialization, unreliable networks, handling asynchronous o/p, varying loads within our application tiers, distributed transactions, etc.”
  3. How to make configuration changes across the large fleet of services with minimal effort?
  4. How to deploy multiple versions of single microservice and route calls appropriately?
  5. How to disconnect a microservice from ecosystem when it starts to crash unexpectedly?
  6. How to isolate a failed microservice and avoid cascading failures in the entire ecosystem?
  7. How to discover services in an elastic manner considering that services may be going UP or DOWN at any point in time?
  8. How to aggregate logs/metrics across the services? How to identify different steps of a single client request spread across a span of microservices?

Microservices architecture is meant for developing large distributed systems that scale with safely. There are many benefits of microservices architecture over monoliths, for example:

  1. Monolith application is built as a single unit, it is usually composed of 3 components – a database (usually a RDBMS), a server-side executable (war file deployed in tomcat, websphere etc) and a client interface (JSP, etc.)
  2. Whenever we want to add/update functionality, developers need to change at least one of these three components and deploy the new version to production. The entire system is tightly coupled, have limitations in choosing technology stack, have low cohesion.
  3. When we need to scale a monolith, we deploy the same version of the monolith on multiple machines, by copying the big war/ear file again and again. Everything is contained into a single executable file.
  4. Microservices Architecture, on the other hand, is composed of small autonomous services, divided over business capabilities that communicate with each other over network mostly in async fashion.

As illustrated in the above example, a typical monolith eShop application is usually a big war file deployed in a single JVM process (tomcat/jboss/websphere, etc). Different components of a monolith communicate with each other using in-process communication like direct method invocation. One or more databases are shared among different components of a monolith application.

Microservices should be autonomous and divided based on business capabilities. Each software component should have single well-defined responsibility (a.k.a Single Responsibility Principle) and the principle of Bounded Context (as defined by Domain Driven Design) should be used to create highly cohesive software components.

For example, an e-commerce site can be partitioned into following microservices based on its business capabilities:

  • Product catalogue

Responsible for product information, searching products, filtering products & products facets.

  • Inventory

Responsible for managing inventory of products (stock/quantity and facet).

  • Product review and feedback

Collecting feedback from users about the products.

  • Orders

Responsible for creating and managing orders.

  • Payments

Process payments both online and offline (Cash On Delivery).

  • Shipments

Manage and track shipments against orders.

  • Demand generation

Market products to relevant users.

  • User Accounts

Manage users and their preferences.

  • Recommendations

Suggest new products based on the user’s preference or past purchases.

  • Notifications

Email and SMS notification about orders, payments, and shipments.

The client application (browser, mobile app) will interact with these services via API gateway and render the relevant information to the user.

If you want to halt the service when it is not able to locate the config-server during bootstrap, then you need to configure the following property in microservice’s bootstrap.yml:

spring:
      cloud:
         config:
             fail-fast: true 

Using this configuration will make microservice startup fail with an exception when config-server is not reachable during bootstrap.

We can enable a retry mechanism where microservice will retry 6 times before throwing an exception. We just need to add spring-retry and spring-boot-starter-aop to the classpath to enable this feature.

build.gradle:-

...
 dependencies {
   compile('org.springframework.boot:spring-boot-starter-aop')
   compile('org.springframework.retry:spring-retry')
   ...}

Microservices should be autonomous and divided based on business capabilities. Each software component should have single well-defined responsibility (a.k.a Single Responsibility Principle) and the principle of Bounded Context (as defined by Domain Driven Design) should be used to create highly cohesive software components.

For example, an e-shop can be partitioned into following microservices based on its business capabilities:

  • Product catalogue

Responsible for product information, searching products, filtering products & products facets.

  • Inventory 

Responsible for managing inventory of products (stock/quantity and facet).

  • Product review and feedback 

Collecting feedback from users about the products.

  • Orders 

Responsible for creating and managing orders.

  • Payments

Process payments both online and offline (Cash On Delivery).

  • Shipments 

Manage and track shipments against orders.

  • Demand generation 

Market products to relevant users.

  • User Accounts 

Manage users and their preferences.

  • Recommendations 

Suggest new products based on the user’s preference or past purchases.

  • Notifications 

Email and SMS notification about orders, payments, and shipments.
The client application (browser, mobile app) will interact with these services via the API gateway and render the relevant information to the user.

A good, albeit non-specific, rule of thumb is as small as possible but as big as necessary to represent the domain concept they own said by Martin Fowler

Size should not be a determining factor in microservices, instead bounded context principle and single responsibility principle should be used to isolate a business capability into a single microservice boundary.

Microservices are usually small but not all small services are microservices. If any service is not following the Bounded Context Principle, Single Responsibility Principle, etc. then it is not a microservice irrespective of its size. So the size is not the only eligibility criteria for a service to become microservice.

In fact, size of a microservice is largely dependent on the language (Java, Scala, PHP) you choose, as few languages are more verbose than others.

Microservices are often integrated using a simple protocol like REST over HTTP. Other communication protocols can also be used for integration like AMQP, JMS, Kafka, etc.

The communication protocol can be broadly divided into two categories- synchronous communication and asynchronous communication.

  • Synchronous Communication

RestTemplate, WebClient, FeignClient can be used for synchronous communication between two microservices. Ideally, we should minimize the number of synchronous calls between microservices because networks are brittle and they introduce latency. Ribbon – a client-side load balancer can be used for better utilization of resource on the top of RestTemplate. Hystrix circuit breaker can be used to handle partial failures gracefully without a cascading effect on the entire ecosystem. Distributed commits should be avoided at any cost, instead, we shall opt for eventual consistency using asynchronous communication.

  • Asynchronous Communication

In this type of communication, the client does not wait for a response, instead, it just sends the message to the message broker. AMQP (like RabbitMQ) or Kafka can be used for asynchronous communication across microservices to achieve eventual consistency.