What is Load Balancing? Need for Netflix Ribbon
In computing, load balancing improves the distribution of workloads across multiple computing resources, such as computers, a computer cluster, network links, central processing units, or disk drives. Load balancing aims to optimize resource use, maximize throughput, minimize response time, and avoid overload of any single resource. Using multiple components with load balancing instead of a single component may increase reliability and availability through redundancy. Load balancing usually involves dedicated software or hardware, such as a multilayer switch or a Domain Name System server process.
In previous posts we developed two services employee-producer and employee-consumer. Suppose other modules are also calling and consuming employee-producer module services. So the load at employee-producer is high. To deal with this we this we deploy multiple instances of employee-producer. Suppose two in this case. Now we will have to use a Load Balancer to route any incoming requests to either one of these two services
Eureka: Expose Service API, it have own Server
Ribbon : load balancer at client side
Histrix : circut breaking, exception hander at application server side
Eureka Server :
Pom.xml
(?xml version="1.0" encoding="UTF-8"?)
(project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd")
(modelVersion)4.0.0(/modelVersion)
(groupId)com.example(/groupId)
(artifactId)EurekaServer(/artifactId)
(version)0.0.1-SNAPSHOT(/version)
(packaging)jar(/packaging)
(name)EurekaServer(/name)
(description)Demo project for Spring Boot(/description)
(parent)
(groupId)org.springframework.boot(/groupId)
(artifactId)spring-boot-starter-parent(/artifactId)
(version)1.5.6.RELEASE(/version)
(relativePath/) (!-- lookup parent from repository --)
(/parent)
(properties)
(project.build.sourceEncoding)UTF-8(/project.build.sourceEncoding)
(project.reporting.outputEncoding)UTF-8(/project.reporting.outputEncoding)
(java.version)1.8(/java.version)
(/properties)
(dependencies)
(dependency)
(groupId)org.springframework.boot(/groupId)
(artifactId)spring-boot-starter(/artifactId)
(/dependency)
(dependency)
(groupId)org.springframework.cloud(/groupId)
(artifactId)spring-cloud-starter-eureka-server(/artifactId)
(/dependency)
(/dependencies)
(dependencyManagement)
(dependencies)
(dependency)
(groupId)org.springframework.cloud(/groupId)
(artifactId)spring-cloud-dependencies(/artifactId)
(version)Camden.SR6(/version)
(type)pom(/type)
(scope)import(/scope)
(/dependency)
(/dependencies)
(/dependencyManagement)
(build)
(plugins)
(plugin)
(groupId)org.springframework.boot(/groupId)
(artifactId)spring-boot-maven-plugin(/artifactId)
(/plugin)
(/plugins)
(/build)
(/project)
Application.properties:
server.port=8090
EurekaServerApplication.java
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
========================================================================
Application Producer:
(?xml version="1.0" encoding="UTF-8"?)
(project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd")
(modelVersion)4.0.0(/modelVersion)
(groupId)com.example(/groupId)
(artifactId)EurekaProducer(/artifactId)
(version)0.0.1-SNAPSHOT(/version)
(packaging)jar(/packaging)
(name)EurekaProducer(/name)
(description)Demo project for Spring Boot(/description)
(parent)
(groupId)org.springframework.boot(/groupId)
(artifactId)spring-boot-starter-parent(/artifactId)
(version)1.5.6.RELEASE(/version)
(relativePath/) (!-- lookup parent from repository --)
(/parent)
(properties)
(project.build.sourceEncoding)UTF-8(/project.build.sourceEncoding)
(project.reporting.outputEncoding)UTF-8(/project.reporting.outputEncoding)
(java.version)1.8(/java.version)
(/properties)
(dependencies)
(dependency)
(groupId)org.springframework.boot(/groupId)
(artifactId)spring-boot-starter(/artifactId)
(/dependency)
(dependency)
(groupId)org.springframework.boot(/groupId)
(artifactId)spring-boot-starter-web(/artifactId)
(/dependency)
(dependency)
(groupId)org.springframework.cloud(/groupId)
(artifactId)spring-cloud-starter-eureka(/artifactId)
(/dependency)
(dependency)
(groupId)org.springframework.cloud(/groupId)
(artifactId)spring-cloud-starter-hystrix(/artifactId)
(/dependency)
(/dependencies)
(dependencyManagement)
(dependencies)
(dependency)
(groupId)org.springframework.cloud(/groupId)
(artifactId)spring-cloud-dependencies(/artifactId)
(version)Camden.SR6(/version)
(type)pom(/type)
(scope)import(/scope)
(/dependency)
(/dependencies)
(/dependencyManagement)
(build)
(plugins)
(plugin)
(groupId)org.springframework.boot(/groupId)
(artifactId)spring-boot-maven-plugin(/artifactId)
(/plugin)
(/plugins)
(/build)
(/project)
application.properties:
eureka.client.serviceUrl.defaultZone=http://localhost:8090/eureka
eureka.instance.instanceId=${spring.application.name}:${random.value}
bootstrap.properties:
spring.application.name=employee-producer
Employee.java
package com.javainuse.model;
public class Employee {
private String empId;
private String name;
private String designation;
private double salary;
public Employee() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDesignation() {
return designation;
}
public void setDesignation(String designation) {
this.designation = designation;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public String getEmpId() {
return empId;
}
public void setEmpId(String empId) {
this.empId = empId;
}
}
eureka.instance.instanceId=${spring.application.name}:${random.value}
bootstrap.properties:
spring.application.name=employee-producer
Employee.java
package com.javainuse.model;
public class Employee {
private String empId;
private String name;
private String designation;
private double salary;
public Employee() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDesignation() {
return designation;
}
public void setDesignation(String designation) {
this.designation = designation;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public String getEmpId() {
return empId;
}
public void setEmpId(String empId) {
this.empId = empId;
}
}
Controller Class
package com.javainuse.controllers;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.javainuse.model.Employee;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
@RestController
public class TestController {
@RequestMapping(value = "/employee", method = RequestMethod.GET)
@HystrixCommand(fallbackMethod = "getDataFallBack")
public Employee firstPage() {
Employee emp = new Employee();
emp.setName("emp1");
emp.setDesignation("manager");
emp.setEmpId("1");
emp.setSalary(3000);
if(emp.getName().equalsIgnoreCase("emp1"))
throw new RuntimeException();
return emp;
}
public Employee getDataFallBack() {
Employee emp = new Employee();
emp.setName("fallback-emp1");
emp.setDesignation("fallback-manager");
emp.setEmpId("fallback-1");
emp.setSalary(3000);
return emp;
}
}
package com.javainuse;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.javainuse.model.Employee;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
@RestController
public class TestController {
@RequestMapping(value = "/employee", method = RequestMethod.GET)
@HystrixCommand(fallbackMethod = "getDataFallBack")
public Employee firstPage() {
Employee emp = new Employee();
emp.setName("emp1");
emp.setDesignation("manager");
emp.setEmpId("1");
emp.setSalary(3000);
if(emp.getName().equalsIgnoreCase("emp1"))
throw new RuntimeException();
return emp;
}
public Employee getDataFallBack() {
Employee emp = new Employee();
emp.setName("fallback-emp1");
emp.setDesignation("fallback-manager");
emp.setEmpId("fallback-1");
emp.setSalary(3000);
return emp;
}
}
package com.javainuse;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public class SpringBootHelloWorldApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootHelloWorldApplication.class, args);
}
}
========================================================================
Application Consumer
(?xml version="1.0" encoding="UTF-8"?)
(project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd")
(modelVersion)4.0.0(/modelVersion)
(groupId)com.example(/groupId)
(artifactId)EurekaConsumer(/artifactId)
(version)0.0.1-SNAPSHOT(/version)
(packaging)jar(/packaging)
(name)EurekaConsumer(/name)
(description)Demo project for Spring Boot(/description)
(parent)
(groupId)org.springframework.boot(/groupId)
(artifactId)spring-boot-starter-parent(/artifactId)
(version)1.5.6.RELEASE(/version)
(relativePath/) (!-- lookup parent from repository --)
(/parent)
(properties)
(project.build.sourceEncoding)UTF-8(/project.build.sourceEncoding)
(project.reporting.outputEncoding)UTF-8(/project.reporting.outputEncoding)
(java.version)1.8(/java.version)
(/properties)
(dependencies)
(dependency)
(groupId)org.springframework.boot(/groupId)
(artifactId)spring-boot-starter-web(/artifactId)
(/dependency)
(dependency)
(groupId)org.springframework.cloud(/groupId)
(artifactId)spring-cloud-starter-eureka(/artifactId)
(/dependency)
(dependency)
(groupId)org.springframework.cloud(/groupId)
(artifactId)spring-cloud-starter-ribbon(/artifactId)
(/dependency)
(/dependencies)
(dependencyManagement)
(dependencies)
(dependency)
(groupId)org.springframework.cloud(/groupId)
(artifactId)spring-cloud-dependencies(/artifactId)
(version)Camden.SR6(/version)
(type)pom(/type)
(scope)import(/scope)
(/dependency)
(/dependencies)
(/dependencyManagement)
(build)
(plugins)
(plugin)
(groupId)org.springframework.boot(/groupId)
(artifactId)spring-boot-maven-plugin(/artifactId)
(/plugin)
(/plugins)
(/build)
(/project)
package com.javainuse;
import java.io.IOException;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestClientException;
import com.javainuse.controllers.ConsumerControllerClient;
@SpringBootApplication
public class SpringBootHelloWorldApplication {
public static void main(String[] args) throws RestClientException, IOException {
ApplicationContext ctx = SpringApplication.run(
SpringBootHelloWorldApplication.class, args);
ConsumerControllerClient consumerControllerClient=ctx.getBean(ConsumerControllerClient.class);
System.out.println(consumerControllerClient);
consumerControllerClient.getEmployee();
}
@Bean
public ConsumerControllerClient consumerControllerClient()
{
return new ConsumerControllerClient();
}
}
package com.javainuse.controllers;
import java.io.IOException;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
@Controller
public class ConsumerControllerClient {
@Autowired
private LoadBalancerClient loadBalancer;
public void getEmployee() throws RestClientException, IOException {
ServiceInstance serviceInstance=loadBalancer.choose("employee-producer");
System.out.println(serviceInstance.getUri());
String baseUrl=serviceInstance.getUri().toString();
baseUrl=baseUrl+"/employee";
RestTemplate restTemplate = new RestTemplate();
ResponseEntity response=null;
try{
response=restTemplate.exchange(baseUrl,
HttpMethod.GET, getHeaders(),String.class);
}catch (Exception ex)
{
System.out.println(ex);
}
System.out.println(response.getBody());
}
private static HttpEntity getHeaders() throws IOException {
HttpHeaders headers = new HttpHeaders();
headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
return new HttpEntity<>(headers);
}
}
application.properties:
server.port=8091
eureka.client.serviceUrl.defaultZone=http://localhost:8090/eureka
bootstrap.properties:
spring.application.name=employee-consumer
========================================================================
========================================================================
Example2 :
server.port=8091
eureka.client.serviceUrl.defaultZone=http://localhost:8090/eureka
bootstrap.properties:
spring.application.name=employee-consumer
========================================================================
========================================================================
Example2 :
No comments:
Post a Comment