Ribbon负载均衡策略
文章目录
- Ribbon负载均衡策略
- 1.默认-轮询策略
- 1.1 修改User服务,使用Ribbon默认轮询策略
- 1.2 RestTemplate配置
- 1.3 RestTemplate访问Order订单服务
- 1.4 重启user服务
- 1.5 测试Ribbon轮询访问
- 2.随机策略
- 2.1 定义RandomLoadBalancer 随机负载均衡策略
- 2.2 LoadBalancerClients指定使用策略
- 2.3 重启user服务,验证随机策略
Ribbon默认的是轮询策略,那么还有其他策略么?该如何使用其他策略
Ribbon 一共7 种策略
- 轮询策略 RoundRobinRule
- 随机策略 RandomRule
- 轮询重试策略 RetryRule
- 响应速度决定权重 WeightedResponseTimeRule
- 最优可用 BestAvailableRule, 采用并发连接数判断最优,连接数最小的节点
- 可用性过滤规则 AvailabilityFilteringRule
- 区域内可用性能最优 ZoneAvoidanceRule
如果需要一些前置配置的比如服务创建及Eureka使用,可以看下上一篇文章
Ribbon负载均衡(一)Ribbon实战 我使用的版本如下
本文使用的版本是 Springboot-2.6.7 ,Spring Cloud -2021.0.2 , Eureka 版本3.1.2
这坑爹玩意,这里面在Eureka 下面的jar包中是没有ribbon的, 没IRule接口,如何定义负载均衡策略 ?推荐使用 Springcloud LoadBalancer 替换RibbonSpringcloud LoadBalancer只有两种负载均衡策略+自定义负载均衡策略
springcloud 2020.0.1 版本之后 删除了eureka中的ribbon,替代ribbon的是spring cloud自带的LoadBalancer
Spring-cloud-starter-loadbalancer 的jar 这个应该是和Ribbon的功能一样,但是他就提供了RandomLoadBalancer 随机 和RoundRobinLoadBalancer 轮询的方式,默认使用的是轮询的方式
1.默认-轮询策略
我们改造一下
1.1 修改User服务,使用Ribbon默认轮询策略
增加config/RestTemplateConfig 配置文件, 引入RestTemplate便于访问http接口
1.2 RestTemplate配置
RestTemplateConfig.java
package com.ribbon.user.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
//如果不加上面的注释 @LoadBalanced 就不会从eureka上获取 order服务地址, 也就不会使用负载均衡,
// 你访问的 http://order/order order服务的host就会找不到
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
}
1.3 RestTemplate访问Order订单服务
package com.ribbon.user.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
@RestController
@Slf4j
public class UserController {
@Resource
private RestTemplate restTemplate;
@GetMapping("/user")
public String test() {
log.info("client 发起UserController");
return "user";
}
@GetMapping("/testribbon")
public String testRibbon() {
//restTemplate 请求访问 order订单服务的 order URL ,
// 参数URL http://order/order 第一个order 就是服务名字 就是注册在Eureka上的 服务名字 第二个order就是 controller 入口
// 第二个参数String.class 就是 访问返回值
String result = restTemplate.getForObject("http://order/order", String.class);
log.info("user 发起UserController 测试ribbon 调用 :{} ", result);
return result;
}
}
1.4 重启user服务
访问 localhost:8088/testribbon
如果报错, 看下你的RestTemplate种的@LoadBalanced 注解是否加上,不加上默认是使用正常的restTemplate 访问IP+PORT ,你的URL是 http://order/order 不会去Eureka上获取order服务的地址及端口的
没有@LoadBalanced 注解 会报如下错误
nested exception is java.net.UnknownHostException: order] with root cause
java.net.UnknownHostException: order
2022-05-15 21:51:03.169 ERROR 6216 --- [nio-8088-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://order/order": order; nested exception is java.net.UnknownHostException: order] with root cause
java.net.UnknownHostException: order
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:184) ~[na:1.8.0_181]
服务正常启动
1.5 测试Ribbon轮询访问
访问testribbon接口,看看RestTemplate访问的是否是轮询访问三个节点中的一个
可以看到顺序那都是 two,one,three,的确是轮询访问三个服务
2.随机策略
如何实现Ribbon对order服务随机策略?我们只要定制规则即可? 但是我们已经没了Ribbon 所以你是引入不了 IRule 接口去重新定义Rule负载均衡策略的,咋办?????
SpringCloud重新定义了一套 ReactorLoadBalancer 策略
2.1 定义RandomLoadBalancer 随机负载均衡策略
定义随机策略
package com.ribbon.user.config;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.loadbalancer.core.RandomLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;
/**
* 这里不需要 @configuration注解 不需要 不需要!!!!
* 它可以在RestTemplateConfig中指定 Configuration CustomLoadBalancerConfiguration
*/
public class CustomLoadBalancerConfiguration {
@Bean
ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,
LoadBalancerClientFactory loadBalancerClientFactory) {
String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
return new RandomLoadBalancer(loadBalancerClientFactory
.getLazyProvider(name, ServiceInstanceListSupplier.class),
name);
}
}
为什么这个类上不加 @Configuration 让Spring 扫描到它? 因为官方文档中给除了明确说法 不要加注释@Configuration 或者你可以在Spring 包扫描外 新建这个配置
2.2 LoadBalancerClients指定使用策略
修改RestTemplateConfig 配置文件 ,很重要!!!!!
配置LoadBalancerClients 指定你的 service服务 及使用的负载均衡策略
package com.ribbon.user.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
//在这里配置我们自定义的LoadBalancer策略
// 如果扩展算法 需要自己去实现ReactorServiceInstanceLoadBalancer接口
// 标准@LoadBalancerClients(defaultConfiguration = {name = "CLOUD-PAYMENT-SERVICE", configuration = CustomLoadBalancerConfiguration.class})
//注意这里的name属性 需要和eureka页面中的服务提供者名字保持一致
@LoadBalancerClient(name = "order", configuration = CustomLoadBalancerConfiguration.class)
public class RestTemplateConfig {
//如果不加上面的注释 @LoadBalanced 就不会从eureka上获取 order服务地址, 也就不会使用负载均衡,
// 你访问的 http://order/order order服务的host就会找不到
@Bean
@LoadBalanced
//使用这个 @LoadBalanced 注解给restTemplate赋予了负载均衡的能力
RestTemplate restTemplate() {
return new RestTemplate();
}
}
2.3 重启user服务,验证随机策略
访问 http://localhost:8088/testribbon 接口 可以看到 随机取调用某台节点
实现了随机访问的负载均衡模式
至此我们已经简单的可以使用 SpringCloud LoadBalancer了 , 这两种都是基本的负载均衡策略,下一篇 我们介绍下 如何用 SpringCloud LoadBalancer 取自定义负载均衡策略