ribbon 是一个负载均衡组件,当我们的服务有是集群部署的时候,我们可以使用ribbon来进行负载均衡。
项目结构:
1、user-service项目maven依赖引入:
org.springframework.boot
spring-boot-starter-web
需要依赖spring-cloud-starter-netflix-ribbon jar包
org.springframework.cloud
spring-cloud-starter-netflix-ribbon
com.wzy
order-api
${project.version}
2、user-service 微服务启动类:
@SpringBootApplication
public class UserServiceRibbonApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceRibbonApplication.class, args);
}
}
3、user-service中演示的Controller:
@RestController
public class UserLoabBalancerClientGetServerInstanceController {
@Autowired
private RestTemplate restTemplate;
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
spring-cloud-starter-netflix-ribbon 会自动装配一个LoadBalancerClient在上下文中,类型是RibbonLoadBalancerClient
@Autowired
private LoadBalancerClient loadBalancerClient;
@GetMapping("userGetOrderById")
public OrderDto userGetOrderById(@RequestParam("orderId") String orderId){
/*
使用负载均衡客户端进行服务选择,按照服务的id进行选择,服务的列表我们使用配置的方式:
order-service.ribbon.listOfServers=http://localhost:7071,http://localhost:7072
在后续集成服务注册与发现的时候就不需要这样配置了
*/
ServiceInstance serviceInstance = loadBalancerClient.choose("order-service");
System.out.println(serviceInstance.getHost());
System.out.println(serviceInstance.getPort());
String url = String.format("http://%s:%s/getOrderById?orderId=%s", serviceInstance.getHost(), serviceInstance.getPort(), orderId);
ResponseEntity forEntity = restTemplate.getForEntity(url, OrderDto.class);
return forEntity.getBody();
}
@PostMapping("userSaveOrder")
public OrderDto userSaveOrder(@RequestBody OrderDto orderDto){
ServiceInstance serviceInstance = loadBalancerClient.choose("order-service");
System.out.println(serviceInstance.getHost());
System.out.println(serviceInstance.getPort());
String url = String.format("http://%s:%s/saveOrder", serviceInstance.getHost(), serviceInstance.getPort());
OrderDto forObject = restTemplate.postForObject(url, orderDto, OrderDto.class);
return forObject;
}
}
4、user-service 服务中的 application.properties:
server.port= 8080
spring.application.name=user-service
#由于为集成服务注册于发现,因此在配置文件中维护order-service 服务的列表
order-service.ribbon.listOfServers=http://localhost:7071,http://localhost:7072
1、user-service中演示的Controller:其他的都不变化。
@RestController
public class UserController {
@Autowired
private RestTemplate restTemplate;
//使用@LoadBalanced注解来赋予此RestTemplate 具备负载均衡功能。
@LoadBalanced
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
@GetMapping("userGetOrderById")
public OrderDto userGetOrderById(@RequestParam("orderId") String orderId){
//使用具备负载均衡功能的RestTemplate进行http服务调用
ResponseEntity forEntity = restTemplate.getForEntity("http://order-service/getOrderById?orderId=" + orderId, OrderDto.class);
return forEntity.getBody();
}
@PostMapping("userSaveOrder")
public OrderDto userSaveOrder(@RequestBody OrderDto orderDto){
//使用具备负载均衡功能的RestTemplate进行http服务调用
OrderDto forObject = restTemplate.postForObject("http://order-service/saveOrder", orderDto, OrderDto.class);
return forObject;
}
}
maven依赖:
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
我们直接查看spring-cloud-starter-netflix-eureka-client项目的pom文件:
. . .
org.springframework.cloud
spring-cloud-starter-netflix-archaius
2.2.5.RELEASE
compile
pring-cloud-starter-netflix-eureka-client中默认将ribbon做了集成。
org.springframework.cloud
spring-cloud-starter-netflix-ribbon
2.2.5.RELEASE
compile
org.springframework.cloud
spring-cloud-starter-loadbalancer
2.2.5.RELEASE
compile
com.netflix.ribbon
ribbon-eureka
2.3.0
compile
annotations
com.google.code.findbugs
servlet-api
javax.servlet
. . .
我们使用eureka来作为服务注册于发现中心,项目结构:
1、eureka-server服务:
pom文件:
org.springframework.cloud
spring-cloud-starter-netflix-eureka-server
org.springframework.boot
spring-boot-starter-web
启动类:
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
配置文件application.properties
spring.application.name=eureka-server
server.port=9090
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
2、order-service 服务:
pom文件:
org.springframework.boot
spring-boot-starter-web
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
com.wzy
order-api
${project.version}
启动类:
@SpringBootApplication
@EnableEurekaClient
public class OrderServiceRibbonApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceRibbonApplication.class, args);
}
}
配置文件application.properties:
server.port= 7071
spring.application.name=order-service
eureka.client.service-url.defaultZone = http://localhost:9090/eureka
3、user-service服务:
pom文件:
org.springframework.boot
spring-boot-starter-web
org.springframework.cloud
spring-cloud-starter-netflix-ribbon
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
com.wzy
order-api
${project.version}
启动类:
@SpringBootApplication
@EnableDiscoveryClient
public class UserServiceRibbonApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceRibbonApplication.class, args);
}
}
配置文件application.properties:
server.port= 8080
spring.application.name=user-service
eureka.client.service-url.defaultZone = http://localhost:9090/eureka
不在配置文件中维护order-service服务提供者列表了
#order-service.ribbon.listOfServers=http://localhost:7071,http://localhost:7072
演示Controller:
@RestController
public class UserController {
@Autowired
private RestTemplate restTemplate;
@LoadBalanced
@Bean
public RestTemplate restTemplate(){
RestTemplate restTemplate = new RestTemplate();
return restTemplate;
}
@GetMapping("userGetOrderById")
public OrderDto userGetOrderById(@RequestParam("orderId") String orderId){
//使用具备负载均衡功能的RestTemplate进行http服务调用
ResponseEntity forEntity = restTemplate.getForEntity("http://order-service/getOrderById?orderId=" + orderId, OrderDto.class);
return forEntity.getBody();
}
@PostMapping("userSaveOrder")
public OrderDto userSaveOrder(@RequestBody OrderDto orderDto){
//使用具备负载均衡功能的RestTemplate进行http服务调用
OrderDto forObject = restTemplate.postForObject("http://order-service/saveOrder", orderDto, OrderDto.class);
return forObject;
}
}