1. Introduction
In Microservice architecture, a monolithic application is split into multiple Smaller and independent applications. Each application manages a certain functionality independently and can be deployed/scaled independently.
However in order to accomplish a business functionality, it's often required for multiple services to communicate with one another.
Spring Cloud Netflix provides Netflix integration with spring boot applications which ensure seamless Java web Development Company of Microservice.It provides common design patterns for developing the applications.
- Eureka - For service discovery
- Hystrix - For implementing circuit breaker pattern
- Ribbon - For client side load balancing
- Zuul - Intelligent routing.
In this article, we’ll be exploring more about Ribbon.
2. Netflix Ribbon
One of the advantages of microservices is that they can be scaled vertically (increasing allocated heap memory, threads) or horizontally (deploying multiple instances of same service) very easily.
We can bring up multiple instances of your service with any instance capable of handling any request. To leverage this horizontal scaling, Load balancers are employed. In traditional load balancers client only knows 1 target. The target in-turn distributes the request among multiple instances.
Netflix Ribbon is an alternate approach to Traditional Load Balancers, where client is aware of multiple instances of a service and chooses a particular instance of it. One advantage of this is client controls the load balancing algorithm.
Netflix Ribbon is a Client Side Load Balancer.
Following are salient features of Ribbon :
- Source Code : https://github.com/Netflix/ribbon
- Client Side Load Balancer
- Can be used with Eureka or without it. In case Eureka isn’t configured, the list of service instances needs to be explicitly provided to client.
3. Project
In our project, we’ll be creating 3 microservices
- Eureka Server - service registry
- User Service - A Eureka registered microservice, which provides User specific endpoints. For employing ribbon, we’ll be deploying 3 instances of this service on different ports.
- Simple Ribbon Client - This will be a client service, which will consume endpoints of User Service. Here we will employ default configuration of ribbon.
- In the final section, we’ll explore customizing Ribbon configuration.
The general flow of client side load balancer with Eureka (for service discovery) is:
- Eureka Server acts as Service Discovery which maintains the list of all the microservices as KEY-VALUE pair. Key is serviceId and value is the instance information (host, port).
- User microservice has multiple instances deployed.
- The client microservice employs Ribbon as Load balancer and consumes the user service endpoints.
- Ribbon talks to Eureka Server and gets information about instances of the User Service to choose from.
- Even if instance of User Service is added or goes down, Eureka updates the same and Ribbon uses the updated information to choose an instance of it. Thus no manual intervention is needed.
3.1 Flow Diagram:
4. Eureka Server:
To implement the Eureka server, all we need to do is:
- Add spring-cloud-starter-eureka-server dependency
- Enable Eureka Server by adding annotation @EnableEurekaServeron our main Spring boot application class.
The project structure is as follows:
4.1 Maven dependencies
4.2 Spring Boot Main Class
4.3 Application Properties
Thus Eureka Server will run on port 8761.
4.4 Starting Eureka Server
1. To start the Eureka Server application, go to the project’s root directory and execute
2. If the build is success, we can launch the application by:
3. The following logs indicate that application is up and running
You can access, the Eureka Server console at http://localhost:8761/
5. User Service
User Service is Eureka Registered micro service.
It will also expose some endpoints which will then be consumed by the client application. Also we’ll be deploying multiple instances of this.
The project structure is as follows:
5.1 Maven Dependencies
5.2 Spring Boot Main Class
The convenience annotation @EnableEurekaClient makes this application as a Eureka Client which can be registered with our Eureka Server.
5.3 User Model Class:
This is the model class which will be rendered via controller endpoints.
5.4 Controller
This exposes User service endpoints
5.5 Application Properties:
5.6 Multiple instances of User Services
We’ll be creating 3 instances of User Service. The code base of them is same, only their application properties are different.
All the multiple instances will have the same service ID. The only difference is in port. To create multiple instances of the same, simple copy-paste the folder.
We have created 3 instances/folders of User service.
Following are the application properties of them.
5.6.1 User Service 1
5.6.2 User Service 2
5.6.3 User Service 3
5.7 Deploying the User Services:
The process to deploy each user Microservice is similar.
1. Go to the project’s root directory and execute
2. If the build is success, we can launch the application by:
3. The following logs indicate that application is up and running and also registered with Eureka server.
4. At the same point, in Eureka Server logs, you can see that User service has registered itself.
5. Repeat the same process by visiting individual directories of User Service instances.
6. Upon refreshing the Eureka server console (http://localhost:8761/), you can see all the UserService instances are now available.
6. Simple Ribbon Client MicroService
This micro service consumes the endpoints of User service. It uses Ribbon with default configuration to select apt instance of User service.
The project structure is
6.1 Maven Dependencies
By including dependency spring-cloud-starter-eureka, the Ribbon dependencies are also included.
6.2 Spring Boot Main Class:
6.3 User Client Controller:
This controller act as client and consumes the endpoints from User Service.
* @Autowired
* private DiscoveryClientdiscoveryClient;
*
* @RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
* public MapgetUserById(@PathVariable String id) {
* ListserviceInstances = discoveryClient.getInstances(userServiceName);
* if (serviceInstances.isEmpty()) {
* throw new IllegalArgumentException("No instance found with serviceId :" + userServiceName);
* }
* ServiceInstanceuserServiceInstance = serviceInstances.get(0);
* String url = userServiceInstance.getUri().toString() + "/" + id;
* ...
*
*
* The drawback of this approach is at line:
* ServiceInstanceuserServiceInstance = serviceInstances.get(0);
*
* even if multiple service instances are available, we are choosing the same every time.
*
* With Ribbon, we use
* 1. #{LoadBalancerClient} instead of #{DiscoveryClient}
* 2. The instance is chosen via following line :
* ServiceInstanceuserServiceInstance = loadBalancerClient.choose(userServiceName);
*
* Thus load-balancer determines which instance to choose.
*
* @author hemant
*
*/
@RestController
publicclassUserClientController {
@Autowired
privateLoadBalancerClientloadBalancerClient;
privateRestTemplaterestTemplate = newRestTemplate();
privatefinal String userServiceName = "user-service";
@RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
public MapThis uses Ribbon loadBalancerClient to choose an instance of User Service.
By default, the most well known and basic load balancing strategy, i.e. Round Robin Rule is used.
6.4 Application Properties
Ribbon can be used without Eureka (In that case explicit list of service instances needs to be provided). However since we are using Eureka, no explicit configuration of User service instances is needed.
6.5 Deploying the Application
1. Go to the project’s root directory and execute
2. If the build is success, we can launch the application by:
6.6 Testing the Client:
Once the service is deployed, we can test the load balancer as follows:
1. Hit the client service endpoint
2. Hit it second time
3. Hit it third time
4. Hit it forth time
On further re-tries, we can infer that the load balancer is consuming the user-service instances using Round-Robin strategy. Even if instance is removed/new instance is added, Ribbon will get updated instance information via Eureka and continue its operation without any hassle.
7. Customizing Ribbon Configuration
We didn’t do much Load Balancer configuration in previous application. However Ribbon allows us to configure the following components:
- Rule – component which specifies load balancing rule (implementation of com.netflix.loadbalancer.IRule). The implementations are AbstractLoadBalancerRule, AvailabilityFilteringRule, ClientConfigEnabledRoundRobinRule, RandomRule, ResponseTimeWeightedRule, RetryRule, RoundRobinRule, WeightedResponseTimeRule, ZoneAvoidanceRule
- Ping – Component which specifies mechanism to determine the server’s availability in real-time (Implementation of com.netflix.loadbalancer.IPing). The implementations are bstractLoadBalancerPing, DummyPing, NoOpPing, PingConstant
- ServerList – can be dynamic or static. In case Eureka is used, then this need not be configured.
7.1 Customizing Application Properties:
With spring, some part of configuration can be done in application properties.
The properties are prefixed as <client>.ribbon.*
Following is the sample configuration used for our User Service:
7.2 Advanced Customization:
We can also take full control of the client by declaring additional configuration.
The Spring Boot application class is as follows:
The ribbon configuration class is as follows:
This configuration is used in client logic as follows:
8. Conclusion:
Thus we have used Ribbon for client side load balancing and accessing a specific instance of the service. The default load balancing strategy used is Round-Robin.
In advanced configuration section, we have also explored how to take full control of ribbon configuration.