17.How to stop a Spring Boot based microservices at startup if it can not connect to the Config server during bootstrap?
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.
19
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.
20. How do microservices communicate with each other?
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.
21. What should be preferred communication style in microservices: synchronous or asynchronous?
You must use asynchronous communication while handling HTTP POST/PUT (anything that modifies the data) requests, using some reliable queue mechanism (RabbitMQ, AMQP, etc.)
It's fine to use synchronous communication for Aggregation pattern at API Gateway Level. But this aggregation should not include any business logic other than aggregation. Data values must not be transformed at Aggregator, otherwise, it defeats the purpose of Bounded Context. In Asynchronous communication, events should be published into a Queue. Events contain data about the domain, it should not tell what to do (action) on this data.
If microservice to microservice communication still requires synchronous communication for GET operation, then seriously reconsider the partitioning of your microservices for bounded context, and create some tasks in backlog/technical debt.
22.What is the difference between Orchestration and Choreography in microservices context?
In Orchestration, we rely on a central system to control and call other Microservices in a certain fashion to complete a given task. The central system maintains the state of each step and sequence of the overall workflow. In Choreography, each Microservice works like a State Machine and reacts based on the input from other parts. Each service knows how to react to different events from other systems. There is no central command in this case.
Orchestration is a tightly coupled approach and is an anti-pattern in a microservices architecture. Whereas, Choreography’s loose coupling approach should be adopted where-ever possible.
Example
Let’s say we want to develop a microservice that will send product recommendation email in a fictitious e-shop. In order to send Recommendations, we need to have access to user’s order history which lies in a different microservices.
In Orchestration approach, this new microservice for recommendations will make synchronous calls to order service and fetch the relevant data, then based on his past purchases we will calculate the recommendations. Doing this for a million users will become cumbersome and will tightly couple the two microservices.
In Choreography approach, we will use event-based Asynchronous communication where whenever a user makes a purchase, an event will be published by order service. Recommendation service will listen to this event and start building user recommendation. This is a loosely coupled approach and highly scalable. The event, in this case, does not tell about the action, but just the data.
23.How frequent a microservice be released into production?
There is no right answer to this question, there could be a release every ten minutes, every hour or once a week. It all depends on the extent of automation you have at a different level of the software development lifecycle - build automation, test automation, deployment automation and monitoring. And of course on the business requirements - how small low-risk changes you care making in a single release.
In an ideal world where boundaries of each microservices are clearly defined (bounded context), and a given service is not affecting other microservices, you can easily achieve multiple deployments a day without major complexity.
Examples of deployment/release frequency
Amazon is on record as making changes to production every 11.6 seconds on average in May of 2011.
Github is well known for its aggressive engineering practices, deploying code into production on an average 60 times a day.
Facebook releases to production twice a day.
Many Google services see releases multiple times a week, and almost everything in Google is developed on mainline.
Etsy Deploys More Than 50 Times a Day.
24.What are Cloud-Native applications?
Cloud-Native Applications (NCA) is a style of application development that encourages easy adoption of best practices in the area of continuous delivery and distributed software development. These applications are designed specifically for a cloud computing architecture (AWS, Azure, CloudFoundary, etc).
DevOps, continuous delivery, microservices, and containers are the key concepts in developing cloud-native applications.
Spring Boot, Spring Cloud, Docker, Jenkins, Git are a few tools that can help you write Cloud-Native Application without much effort.
Microservices It is an architectural approach for developing a distributed system as a collection of small services. Each service is responsible for a specific business capability, runs in its own process and communicates via HTTP REST API or messaging (AMQP).
DevOps It is a collaboration between software developers and IT operations with a goal of constantly delivering high-quality software as per customer needs.
Continuous Delivery Its all about automated delivery of low-risk small changes to production, constantly. This makes it possible to collect feedback faster.
Containers Containers (e.g. Docker) offer logical isolation to each microservices thereby eliminating the problem of "run on my machine" forever. It’s much faster and efficient compared to Virtual Machines.
25.How will you develop microservices using Java?
Spring Boot along with Spring Cloud is a very good option to start building microservices using Java language. There are a lot of modules available in Spring Cloud that can provide boiler plate code for different design patterns of microservices, so Spring Cloud can really speed up the development process. Also, Spring boot provides out of the box support to embed a servlet container (tomcat/jetty/undertow) inside an executable jar (uber jar), so that these jars can be run directly from the command line, eliminating the need of deploying war files into a servlet container.
You can also use Docker container to ship and deploy the entire executable package onto a cloud environment. Docker can also help eliminate "works on my machine" problem by providing logical separation for the runtime environment during the development phase. That way you can gain portability across on-premises and cloud environment.
26.What is Spring Boot?
Spring Boot makes it easy to create stand-alone, production-grade Spring-based applications that you can "just run" with an opinionated view of the Spring platform and third-party libraries so you can get started with minimum fuss.
Main features of Spring Boot
Create stand-alone Spring applications (12-factor app style)
Embed Tomcat, Jetty or Undertow directly (no need to deploy WAR files)
Provide opinionated starter POMs to simplify your Maven or Gradle configuration
Automatically configure Spring whenever possible
Provide production-ready features such as metrics, health checks, and externalized configuration
Absolutely no code generation and no requirement for XML configuration
You can create a Spring Boot starter project by selecting the required dependencies for your project using online tool hosted at https://start.spring.io/
Bare minimum dependency for any spring boot application is:
dependencies {
compile("org.springframework.boot:spring-boot-starter-web:2.0.4.RELEASE")
}
The main java class for Spring Boot application will look something like the following:
import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.*; import org.springframework.stereotype.*;
import org.springframework.web.bind.annotation.*;
@Controller @EnableAutoConfiguration
public class HelloWorldController {
@RequestMapping("/") @ResponseBody
String home() {
return "Hello World!";
}
public static void main(String[] args) throws Exception { SpringApplication.run(SampleController.class, args);
} }
You can directly run this class, without deploying it to a servlet container.
Useful References
Spring Boot Project
Spring Boot Starter
Building an Application with Spring Boot
27.What is API Gateway?
API Gateway is a special class of microservices that meets the need of a single client application (such as android app, web app, angular JS app, iPhone app, etc) and provide it with single entry point to the backend resources (microservices), providing cross-cutting concerns to them such as security, monitoring/metrics & resiliency.
Client Application can access tens or hundreds of microservices concurrently with each request, aggregating the response and transforming them to meet the client application’s needs. Api Gateway can use a client-side load balancer library (Ribbon) to distribute load across instances based on round-robin fashion. It can also do protocol translation i.e. HTTP to AMQP if necessary. It can handle security for protected resources as well.
Features of API Gateway
Spring Cloud DiscoveryClient integration
Request Rate Limiting (available in Spring Boot 2.x)
Path Rewriting
Hystrix Circuit Breaker integration for resiliency
28.How to achieve zero-downtime during the deployments?
As the name suggests, zero-downtime deployments do not bring outage in a production environment. It is a clever way of deploying your changes to production, where at any given point in time, at least one service will remain available to customers.
Blue-green deployment
One way of achieving this is blue/green deployment. In this approach, two versions of a single microservice are deployed at a time. But only one version is taking real requests. Once the newer version is tested to the required satisfaction level, you can switch from older version to newer version.
You can run a smoke-test suite to verify that the functionality is running correctly in the newly deployed version. Based on the results of smoke-test, newer version can be released to become the live version.
Changes required in client code to handle zero-downtime
Lets say you have two instances of a service running at the same time, and both are registered in Eureka registry. Further, both instances are deployed using two distinct hostnames:
/src/main/resources/application.yml
spring.application.name: ticketBooks-service
spring.profiles: blue
eureka.instance.hostname: ticketBooks-service -blue.example.com
---
spring.profiles: green
eureka.instance.hostname: ticketBooks-service -green.example.com
Now the client app that needs to make api calls to books-service may look like below:
@RestController
@SpringBootApplication
@EnableDiscoveryClient
public class ClientApp {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate(); }
@RequestMapping("/hit-some-api")
public Object hitSomeApi() {
return restTemplate().getForObject("https://ticketBooks-service/some-uri", Object.class); }
Now, when ticketBooks-service-green.example.com goes down for upgrade, it gracefully shuts down and delete its entry from Eureka registry. But these changes will not be reflected in the ClientApp until it fetches the registry again (which happens every 30 seconds). So for upto 30 seconds, ClientApp’s @LoadBalanced RestTemplate may send the requests to ticketBooks-service-green.example.com even if its down.
To fix this, we can use Spring Retry support in Ribbon client-side load balancer. To enable Spring Retry, we need to follow the below steps:
Add spring-retry to build.gradle dependencies
compile("org.springframework.boot:spring-boot-starter-aop")
compile("org.springframework.retry:spring-retry")
Now enable spring-retry mechanism in ClientApp using @EnableRetry annotation, as shown below:
@EnableRetry @RestController @SpringBootApplication @EnableDiscoveryClient public class ClientApp {
... }
Once this is done, Ribbon will automatically configure itself to use retry logic and any failed request to ticketBooks-service-green.example.com com will be retried to next available instance (in round-robins fashion) by Ribbon. You can customize this behaviour using the below properties:
/src/main/resources/application.yml
ribbon:
MaxAutoRetries: 5
MaxAutoRetriesNextServer: 5
OkToRetryOnAllOperations: true
OkToRetryOnAllErrors: true
29.How to achieve zero-downtime deployment(blue/green) when there is a database change?
The deployment scenario becomes complex when there are database changes during the upgrade. There can be two different scenarios: 1. database change is backward compatible (e.g. adding a new table column) 2. database change is not compatible with an older version of the application (e.g. renaming an existing table column)
Backward compatible change: This scenario is easy to implement and can be fully automated using Flyway. We can add the script to create a new column and the script will be executed at the time of deployment. Now during blue/green deployment, two versions of the application (say v1 and v2) will be connected to the same database. We need to make sure that the newly added columns allow null values (btw that’s part of the backward compatible change). If everything goes well, then we can switch off the older version v1, else application v2 can be taken off.
Non-compatible database change: This is a tricky scenario, and may require manual intervention in-case of rollback. Let's say we want to rename first_name column to fname in the database. Instead of directly renaming, we can create a new column fname and copy all existing values of first_name into fname column, keeping the first_name column as it is in the database. We can defer non-null checks on fname to post-deployment success. If the deployment goes successful, we need to migrate data written to first_name by v1 to the new column (fname) manually after bringing down the v1. If the deployment fails for v2, then we need to do the otherwise.
Complexity may be much more in a realistic production app, such discussions are beyond the scope of this book.
30. How to maintain ACID in microservice architecture?
ACID is an acronym for four primary attributes namely atomicity, consistency, isolation, and durability ensured by the database transaction manager.
Atomicity In a transaction involving two or more entities, either all of the records are committed or none are.
Consistency A database transaction must change affected data only in allowed ways following specific rules including constraints/triggers etc.
Isolation Any transaction in progress (not yet committed) must remain isolated from any other transaction.
Durability Committed records are saved by a database such that even in case of a failure or database restart, the data is available in its correct state.
In a distributed system involving multiple databases, we have two options to achieve ACID compliance:
One way to achieve ACID compliance is to use a two-phase commit (a.k.a 2PC), which ensures that all involved services must commit to transaction completion or all the transactions are rolled back.
Use eventual consistency, where multiple databases owned by different microservices become eventually consistent using asynchronous messaging using messaging protocol. Eventual consistency is a specific form of weak consistency.
2 Phase Commit should ideally be discouraged in microservices architecture due to its fragile and complex nature. We can achieve some level of ACID compliance in distributed systems through eventual consistency and that should be the right approach to do it.
31.What is Spring Cloud ?
Spring team has an integrated number of battle-tested open-source projects from companies like Pivotal, Netflix into a Spring project known as Spring Cloud. Spring Cloud provides libraries & tools to quickly build some of the common design patterns of a distributed system, including the following:
| Pattern Type | Pattern Name | Spring Cloud Library |
|---|---|---|
| Development Pattern | Distributed/versioned configuration management | Spring Cloud Config Server |
| — | Core Microservices Patterns | Spring Boot |
| — | Asynchronous/Distributed Messaging | Spring Cloud Stream (AMQP and Kafka) |
| — | Inter-Service Communication | RestTemplate and Spring Cloud Feign |
| Routing Pattern | Service Registration & Discovery | Spring Cloud Netflix Eureka & Consul |
| Routing Pattern | Service Routing/ API Gateway Pattern | Spring Cloud Netflix Zuul |
| Resiliency Pattern | Client-side load balancing | Spring Cloud Netflix Ribbon |
| — | Circuit Breaker & Fallback Pattern | Spring Cloud Netflix Hystrix |
| — | Bulkhead pattern | Spring Cloud / Spring Cloud Netflix Hystrix |
| Logging Patterns | Log Correlation | Spring Cloud Sleuth |
| — | Microservice Tracing | Spring Cloud Sleuth/Zipkin |
| Security Patterns | Authorization and Authentication | Spring Cloud Security OAuth2 |
| — | Credentials Management | Spring Cloud Security OAuth2/ JWT |
| — | Distributed Sessions | Spring Cloud OAuth2 and Redis |
Spring Cloud makes it really easy to develop, deploy and operate JVM applications for the Cloud.
