Spring Cloud
◦ Client-side discovery: In the Client-side discovery, client
is responsible for determining the network location of
available services. The client uses a load-balancing
algorithm to select one of the available services and
make a request. Netflix OSS is an example of a client-
side discovery pattern.
◦ Server-side discovery: In the server-side discovery, the
client makes an HTTP request to a service through a load
balancer. The load balancer contacts to service registry
and route each request to an available service instance.
Similar to client-side discovery, service instances are
registered and deregistered with the service registry.
The AWS ELB (Elastic Load Balancer) is an example of
server-side discovery. ELB balances the external traffic
from the internet.
Spring Cloud Config Server
◦ A d d t h e S p r i n g B o o t D e v T o o l s a n d C o n fi g
Server dependencies.
◦ Add the annotation @EnableConfigServer in the
SpringCloudConfigServerApplication.java
Connect limits-service to Spring Cloud
Config Server
We will connect limits-service to pick up the configuration from
the spring-cloud-config-server. We do not need to configure
values in the application.properties file.
Move to the limits-service project and rename
the application.properties file to bootstrap.properties. We
do not need to configure values in the bootstrap.properties. All
the configuration values picked from the spring-cloud-config-
server. Specify the URI in the bootstrap.properties.
1. spring.application.name=limits-service
2. spring.cloud.config.uri=http://localhost:8888
Spring Cloud OpenFeign
Spring Cloud OpenFeign provides OpenFeign integrations for
Spring Boot apps through auto-configuration and binding to
the Spring Environment.
It integrates with the Ribbon (client-side load balancing
framework).
When we define Feign, we need only to define a proxy and
define a single method into it. Feign helps us to simplify client
code to talk to the RESTful web services.
1. <dependency>
2. <groupId>org.springframework.cloud</groupId>
3. <artifactId>spring-cloud-starter-feign</artifactId>
4. <version>1.4.4.RELEASE</version>
5. </dependency>
Once the dependency is added, enable the Feign to scan the
clients by adding the annotation @EnableFeignClients.
Define an attribute in the @EnableFeignClients annotation.
The attribute is the name of the package that we want to scan.
@EnableFeignClients("com.javatpoint.microservices.currencyc
onversionservice")
We have enabled the Feign in our project. Now, we will use the
Feign to invoke the service.
Step: Create a Feign proxy that enables us to talk to external
microservices. Let’s create an interface with the
name CurrencyExchangeServiceProxy.
Step: Add an annotation @FeignClient. Pass the
attributes name and URL.
@FeignClient(name="currency-exchange-
service", url="localhost:8000")
Step: Now, we need to define a method that talks to
the currency-exchange-controller.
Open the Currency-ConverterController.java file. Copy
the currency-converter mapping and paste it in the same file.
Step : Change the mapping name to /currency-converter-
feign/from/{from}/to/{to}/quantity/{quantity} and the method
name to convertCurrencyFeign.
Step : Make the use
of CurrencyExchangeServiceProxy and autowired it.
@Autowired
private CurrencyExchangeServiceProxy proxy;
Step : First, run the currency-exchange-service by invoking
the URL http://localhost:8000/currency-exchange/from/USD/
to/INR after that run the currency-conversion-service by
using the URL http://localhost:8100/currency-converter/from/
USD/to/INR/quantity/1000.
If we do not run the services in the order, the currency-
conversion-service shows Whitelabel Error Page. It is
because the currency-conversion-service uses the
conversionMultiple of currency-exchange-service.
Step : Execute the feign service by using the URL http://
localhost:8100/currency-converter-feign/from/USD/to/INR/
quantity/1000. It returns the same response as currency-
converter-service.
Client-Side Load Balancing with
Netflix Ribbon
N e t fl i x R i b b o n i s a P a r t o f N e t fl i x O p e n S o u r c e
Software (Netflix OSS). It is a cloud library that provides
the client-side load balancing.
I t a u t o m a t i c a l l y i n t e r a c t s w i t h N e t fl i x S e r v i c e
Discovery (Eureka) because it is a member of the Netflix
family.
The Ribbon mainly provides client-side load balancing
algorithms. It is a client-side load balancer that provides
control over the behavior of HTTP and TCP client.
The important point is that when we use Feign,
the Ribbon also applies.
1. <dependency>
2. <groupId>org.springframework.cloud</groupId>
3. <artifactId>spring-cloud-starter-netflix-ribbon</
artifactId>
4. </dependency>
After adding the dependency, we need to enable ribbon on the
proxy.
Step : Open the CurrencyExchangeServiceProxy.java file.
Enable Ribbon by adding an annotation @RibbonClient and
specify the name of the service which we want to talk to.
Ribbon client provide the declarative configuration for a client.
@RibbonClient(name="currency-exchange-
service")
Step : In the annotation @FeignClient, remove the
attribute URL. Because we do not need to talk with one
particular service. We will configure that URL in
the application.properties
1. spring.application.name=currency-conversion-service
2. server.port=8100
3. currency-exchange-service.ribbon.listOfServers=http://
localhost:8000, http://localhost:8001
Naming server
The naming server is a computer application that implements
a network service for responding to queries against a directory
service.
Eureka naming server
Eureka naming server is a REST-based server that is used in
the AWS Cloud services for load balancing and failover of
middle-tier services.
Eureka naming server is an application that holds information
about all client service applications. Each micro service
registers itself with the Eureka naming server.
The naming server registers the client services with their port
numbers and IP addresses. It is also known as Discovery
Server.
Eureka naming server fills the gap between the client and
the middle tier load balancer.
If the Ribbon wants to distribute the load to the new server, we
need to add it to the configuration.
Based on the load, we can increase or decrease the number of
instances of the services.
With Eureka naming server, we will be able to increase or
decrease the number of instances dynamically.
If we keep on changing in the CurrencyCalulationService,
based on how many CurrenyExchangeService are active right,
then, it becomes very difficult to maintain.
The Eureka naming server comes into existence when we want
to make maintenance easier. All the instances of all
microservices will be register with the Eureka naming server.
Whenever a new instance of a microservice comes up, it would
register itself with the Eureka naming server.
The registration of microservice with the naming server is
called Service Registration.
Whenever a service wants to talk with another service,
suppose CurrencyCalculationService wants to talk to the
CurrencyExchangeService.
The CurrencyCalculationService first talk with the Eureka
naming server.
The naming server provides the instances of
CurrencyExchangeService that are currently running.
The process of providing instances to other services is
called Service Discovery.
Add the following dependencies: Eureka Server, Config
Client, Actuator, and DevTools.
Open the NetflixEurekaNamingServerApplication.java file
and enable Eureka naming server by using an
annotation @EnableEurekaServer
Open the application.properties file and configure
the application name, port, and eureka server.
1. spring.application.name=netflix-eureka-naming-server
2. server.port=8761
3. eureka.client.register-with-eureka=false
4. eureka.client.fetch-registry=false
Open the browser and type the URL http://localhost:8761. It
shows the Eureka server UI.
Connecting Microservices to
Eureka naming server
Step : Select the currency-conversion-service project.
Step : Open the pom.xml file and add the eureka-
client dependency.
1. <dependency>
2. <groupId>org.springframework.cloud</groupId>
3. <artifactId>spring-cloud-starter-netflix-eureka-client</
artifactId>
4. </dependency>
Open CurrencyConversionServiceApplication.java file and
enable discovery client by using the
annotation @EnableDiscoveryClient.
After enabling the discovery client, configure the URL for the
Eureka naming server.
Step : Open the application.properties file and configure the
URL for the Eureka naming server.
1. spring.application.name=currency-conversion-service
2. server.port=8100
3. e u r e k a . c l i e n t . s e r v i c e - u r l . d e f a u l t - z o n e = h t t p : / /
localhost:8761/eureka
4. currency-exchange-service.ribbon.listOfServers=http://
localhost:8000, http://localhost:8001
If we look at the Eureka UI, we see that there is no instance
registered with the Eureka server.
Distributing calls using Eureka and
Ribbon
Instead of hardcoding the URLs for Ribbon, the Ribbon talks
to the Eureka naming server and retrieve the details of all the
instances of microservices.
we have configured the Eureka naming server and disable the
list of servers that we have configured earlier
API Gateway
API Gateway encapsulates the internal system architecture. It
provides an API that is tailored to each client. It also has other
responsibilities such as authentication, monitoring, load
balancing, caching, request shaping and
management, and static response handling.
API Gateway is also responsible for request routing,
composition, and protocol translation. All the requests made
by the client go through the API Gateway. After that, the API
Gateway routes requests to the appropriate microservice.
◦ Rather than invoking the specific service, the client
directly talks to the API Gateway.
◦ It reduces the number of round trips between client and
application.
We can implement common features like authentication,
routing, rate limiting, auditing, and logging in the API
Gateway.
Consider a scenario in which we do not want to call a
microservice more than five times by a particular client. We
can do it as a part of the limit in the API Gateway
Zuul API Gateway
Zuul is built to enable dynamic routing, monitoring,
resiliency, and security. It can also route the requests to
multiple Amazon Auto Scaling Groups.
For Example, /api/products are mapped to
the product service and /api/user is mapped to
the user service. The Zuul Server dynamically routes the
requests to the respective backend application.It handles all
the requests and performs the dynamic routing of microservice
applications.
Add the following dependencies: Zuul, Eureka Discovery,
Actuator, and DevTools.
1. @EnableZuulProxy
2. @EnableDiscoveryClient
3. @SpringBootApplication
4. public class NetflixZuulApiGatewayServerApplication
application.properties
1. spring.application.name=netflix-zuul-api-gateway-server
2. server.port=8765
3. e u r e k a . c l i e n t . s e r v i c e - u r l . d e f a u l t - z o n e = h t t p : / /
localhost:8765/eureka
Distributed Tracing
Distributed tracing is a technique to monitor and profile the
applications, especially those built using microservice
architecture. It is also known as distributed request tracing.
Developers use distributed tracing to debug and optimize the
code.
We will use Spring Cloud Sleuth with Zipkin. Spring Cloud
Sleuth assigns a unique Id to each request that we have
made. We can trace all the requests based on unique Ids
across all the components.
Spring Cloud Sleuth
Spring Cloud Sleuth is a Spring Cloud library that provides
the ability to track the progress of subsequent microservices
by adding trace and span Ids on the appropriate HTTP
request headers. The Sleuth library is based on
the MDC (Mapped Diagnostic Context) concept, where we can
easily extract values, put to context, and display them in the
log.
Zipkin
Zipkin is an open-source, Java-based distributed tracing
system. It has a management console that provides a
mechanism for sending, receiving,
storing, and visualizing traces details of the subsequent
services.
With the help of the Zipkin server, we can put all the logs of all
the components in the MQ (RabbitMQ). We send the logs to
the Zipkin server where the logs consolidate.
Implementing distributed tracing Using
Spring Cloud Sleuth
The Spring Cloud Sleuth token has the following components:
◦ Application name: The name of the application that is
defined in the properties file.
◦ Trace Id: The Sleuth adds the Trace Id. It remains the
same in all services for a given request.
◦ Span Id: The Sleuth also adds the Span Id. It remains the
same in a unit of work but different for different services
for a given request.
◦ Zipkin Export Flag: It indicates a boolean value.
1. <dependency>
2. <groupId>org.springframework.cloud</groupId>
3. <artifactId>spring-cloud-starter-sleuth</artifactId>
4. </dependency>
Now, we need to trace all the requests. If we want to trace all
the requests, we would need to create ALWAYS_SAMPLE.
We can create a Sampler by using a Bean
Spring Cloud Sleuth provides a Sampler strategy. With the
help of Sampler, we can implement the sampling algorithm
that provides control of the algorithm. By default, we get a
procedure that continuously performs the tracing if
a span (correlation: is an individual operation) is already
active
1. @Bean
2. public Sampler defaultSampler()
3. {
4. return Sampler.ALWAYS_SAMPLE;
5. }
Distributed Tracing with Zipkin
We have seen that a unique Id was being assigned to each
request. We use these Id to trace the request across the logs
of these multiple services.
However, we face a challenge in tracing. If we want to trace a
request, we have to check the log of the individual application.
The solution to this problem is called centralized logs.
We need to centralize all the logs from all the microservices.
We can search through Id assigned by Spring Cloud Sleuth. At
the centralized place, we will able to search and find out what
is happening to a specific request.
The Zipkin server collects the log messages. All the
microservices puts the log messages on the queue
called RabbitMQ, and the Zipkin picks these log messages
from the RabbitMQ. The Zipkin tracing server is connected
with the database.
Download the Zipkin server.
Open the Command Prompt and run the following
commands:
C:\> java -jar zipkin-server-2.12.9-exec.jar The command
launches the Zipkin server
Let’s check the Zipkin server is running or not.
Step : Open the browser and type http://localhost:9411/
zipkin/. It shows the dashboard of the Zipkin server. Here, the
port 9411 is the default port of the Zipkin server.
Here, the most important thing is that the Zipkin server must
listen over the RabbitMQ server. So we have to start the
RabbitMQ server in the background.
Step : Kill the Zipkin server by pressing the keys Ctrl+c.
Step : Run the following commands in the Command Prompt:
1. C:\>SET RABBIT_URI=amqp://localhost
2. C:\> java -jar zipkin-server-2.12.9-exec.jar
Connecting Microservices to Zipkin
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
We will send the message to Zipkin that uses amqp message
protocol. So we need to add the amqp dependency. Adding
the dependency of amqp, we get the connection of RabbitMQ
into all services
Understanding the need for Spring
Cloud Bus
If you are invoking the URL http://localhost:8080/limits and it does
not return the new values. So to get the new values on invoking the
URL http://localhost:8081/limits, you have to do the following:
Open the Postman and send a POST request with the URL http://
localhost:8081/application/refresh.
We have created the two instances of the limits-service.
Suppose there are a hundred instances of the limits-services
that are running in parallel. We need to invoke a hundred URLs
to refresh the configuration from the Git repository.
Invoking a hundred URLs is not as easy as the number of
limits-service increases.
Whenever we make the changes in the configurations, it must
reflect changes in the microservices. Here, the Spring Cloud
Bus provides the solution for this, so we do not need to call
hundred URLs.
Spring Cloud Bus provides a URL for all the hundred
instances. When we invoke that URL, all the instances of the
microservices would be updated with the latest values from
the Git configuration.
Implementing Spring Cloud Bus
When we make the changes in the Git repository, we have to
hit multiple instances of the limits-service to refresh the
configuration.
We will invoke one URL, and it will reflect all the hundred
instances of the microservices. Here we will use Spring Cloud
Bus. In this section, we will use RabbitMQ
Add the amqp dependency and save the file to reflect the
changes.
1. <dependency>
2. <groupId>org.springframework.cloud</groupId>
3. <artifactId>spring-cloud-starter-bus-amqp</artifactId>
4. </dependency>
Open the Postman and send a POST request with the
URL http://localhost:8080/bus/refresh.
Note: If you are using Spring Boot 2.0.0 or above versions, use the
following URL:
http://localhost:8080/actuatror/bus-refresh
In the specific instance, we have run the Spring Cloud Bus
over RabbitMQ. When we start the application, it also starts
with that. After starting the Spring Cloud Bus, all the
microservices registers with the Bus.
When we make changes in configuration, and the changes are
called on any of the instances, the microservice sends an
event over the Spring Cloud Bus. The Spring Cloud Bus
propagates that event to all the microservice instances that are
registered with it.
Fault Tolerance with Hystrix
Fault tolerance can be achieved with the help of a circuit
breaker. It is a pattern that wraps requests to external services
and detects when they fail.
If a failure is detected, the circuit breaker opens. All the
subsequent requests immediately return an error instead of
making requests to the unhealthy service.
It monitors and detects the service which is down and
misbehaves with other services. It rejects calls until it becomes
healthy again.
1. <dependency>
2. <groupId>org.springframework.cloud</groupId>
3. <artifactId>spring-cloud-starter-netflix-hystrix</
artifactId>
4. </dependency>
Step : Open LimitsServicesApplication.java file and
enable Hystrix by using the annotation @EnableHystrix.
1. @GetMapping("/fault-tolerance-example")
2. //configuring a fallback method
3.
@HystrixCommand(fallbackMethod="fallbackRetrieveCon
figurations")
4. public LimitConfiguration retrieveConfigurations()
5. {
6. throw new RuntimeException("Not Available");
7. }
8. //defining the fallback method
9.
public LimitConfiguration fallbackRetrieveConfigurations()
10. {
11. //returning the default configuration
12. return new LimitConfiguration(999, 9);
13. }