文章目录
- Spring Cloud 学习 | - 04 - 自定义Ribbon负载均衡策略
- 1. 启动Eureka
- 1.1 Eureka依赖:
- 1.2 配置文件
- 1.3 开启EurekaServer功能
- 2. 启动服务提供者
- 2.1 主要依赖
- 2.2 配置文件
- 2.3 启用服务发现注解
- 2.4 Service
- 2.5 Controller
- 2.6 启动服务
- 3. 自定义负载均衡策略
- 3.1 新建一个测试类和方法
- 3.2 修改负载均衡规则
- 3.3 自定义负载均衡策略
- 3.3.1 方式一配置文件.yml实现
- 3.3.2 方式二配置类Configuration实现
- 4. 附:Ribbon内嵌的7种负载均衡的策略说明:
Spring Cloud 学习 | - 04 - 自定义Ribbon负载均衡策略
学习
Spring Cloud
之路,文中Spring Boot
版本为2.1.3.RELEASE
,Spring Cloud
版本为Greenwich.SR1
。
接上篇 Spring Cloud 学习 | - 03 - 服务消费(Rest + Ribbon实现负载均衡),我们使用Rest+Ribbon实现了负载均衡,默认策略是轮询策略。接下来,我们看看怎么修改负载均衡的规则。
1. 启动Eureka
具体Eureka相关的,这里就不再赘述,详情请参阅之前的文章内容。这里贴一下基本的配置及代码。
1.1 Eureka依赖:
主要Maven依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
1.2 配置文件
application.yml
:
## app port conf
server:
port: 8761
spring:
application:
name: spring-cloud-eureka
eureka:
client:
service-url:
# EurekaServer的地址,现在是自己的地址,如果是集群,需要加上其它Server的地址
defaultZone: http://localhost:${server.port}/eureka
register-with-eureka: false #由于该应用为注册中心,所以设置为false,代表不向注册中心注册自己
fetch-registry: false #由于注册中心的职责就是维护服务实例,它并不需要去检索服务,所以也设置为false
server:
enable-self-preservation: false # 关闭自我保护机制
1.3 开启EurekaServer功能
@SpringBootApplication
@EnableEurekaServer
public class SpringCloudEurekaApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCloudEurekaApplication.class, args);
}
}
启动Eureka服务。
2. 启动服务提供者
具体这里就不详细说明了,请查阅前一篇博文,这里主要贴一下主要配置和代码。
2.1 主要依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2.2 配置文件
server:
port: 8090
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
instance:
prefer-ip-address: true # 返回ip而不是host名称
# ip-address: 127.0.0.1 # 指定自己的ip信息
lease-expiration-duration-in-seconds: 15 # 服务失效时间,默认值90秒
lease-renewal-interval-in-seconds: 5 # 服务续约(renew)的间隔,默认为30秒
spring:
application:
name: user-provider
2.3 启用服务发现注解
@SpringBootApplication
@EnableDiscoveryClient
public class UserProviderApplication {
public static void main(String[] args) {
SpringApplication.run(UserProviderApplication.class, args);
}
}
2.4 Service
@Service
public class UserServiceImpl implements UserService {
/**
* 查询所有用户
* @return
*/
@Override
public List findAll() {
List list = Arrays.asList("Cindy","Pony","Marry");
return list;
}
}
2.5 Controller
@RestController
@RequestMapping("/user")
public class UserController {
@Value("${server.port}")
private String port;
@Autowired
private UserService userService;
@GetMapping("/list")
public Map list(){
Map<String,Object> data = new HashMap<>(16);
data.put("port", port);
data.put("rows", userService.findAll());
return data;
}
}
2.6 启动服务
分别启动2个user-provider服务,端口分别为8090
、8091
,详细步骤请参阅上一篇博文。
启动完成后,查看eureka注册中心:
3. 自定义负载均衡策略
3.1 新建一个测试类和方法
我们用LoadBalancerClient获取应用实例,在控制台输入主机和端口,重复10次。
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserConsumerApplicationTests {
@Autowired(required = false)
private LoadBalancerClient client;
@Test
public void testRule(){
for (int i = 0; i < 10; i++) {
ServiceInstance instance = client.choose("user-provider");
String host = instance.getHost();
int port = instance.getPort();
System.err.println("Host=" + host + ",port=" + port);
}
}
}
先来看一下,默认的轮询测试结果:
结果是顺序轮流的调用。
3.2 修改负载均衡规则
我们只要注入一个实现IRule
的Bean即可,这里注入Ribbon里自带的一个规则为例(其他的,请实现IRule
接口即可),默认实现的规则有:
这里以RandomRule
为例:
新建一个Configuration
配置类,或者直接在启动类XxxApplication里注入IRule
的Bean:
@Bean
public IRule customRule(){
return new RandomRule();
}
这样便可以了。我们测试一下:
输出结果是随机的,证明随机的策略生效了。
下边我们说下,对指定的服务配置负载均衡策略的方法。
3.3 自定义负载均衡策略
3.3.1 方式一配置文件.yml实现
官方的说明文档如下:
.yml
配置的格式:<clientName>.ribbon.NFLoadBalancerRuleClassName:自定义的Rule规则类(需要实现IRule接口)
,我们修改自己的.yml
配置,新增如下内容:
user-provider: # 我们为user-provider这个服务配置自定义的策略
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 自定义的策略类
注释掉刚才全局的策略配置:
// @Bean
// public IRule customRule(){
// return new RandomRule();
// }
这样就OK了,我们测试游戏,是不是随机的调用规则:
我们看到是随机的,配置正确。
3.3.2 方式二配置类Configuration实现
- 先注释掉刚才的
.yml
配置方式代码:
#user-provider: # 我们为user-provider这个服务配置自定义的策略
# ribbon:
# NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 自定义的策略类
- 我们新建一个Rrule配置类,这个类要注意下package的位置,不能再XxxApplication启动类同级及其子包下,Sprig Cloud官方文档说明如下:
- 新建配置类
CustomRuleConfig
,路径如下
@Configuration
public class CustomRuleConfig {
@Bean
public IRule customRule(){
return new RandomRule();
}
}
- 修改启动类XxxApplication,添加注解
@RibbonClient
:
@SpringBootApplication
@EnableDiscoveryClient
@RibbonClient(name = "user-provider",configuration = CustomRuleConfig.class)
public class UserConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(UserConsumerApplication.class, args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
name:表示是指定哪个服务启用这个策略,
configuration :表示指定哪个自定义的策略规则
- 好了,我们测试一下:
结果是随机的,采用了指定负载均衡的规则。
4. 附:Ribbon内嵌的7种负载均衡的策略说明:
No. | Rule | Desc |
1 | RoundRobinRule | 轮询 |
2 | RandomRule | 随机 |
3 | AvailabilityFilteringRule | 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,还有并发的连接数量超过阈值的服 务,然后对剩余的服务列表按照轮询策略进行访问 |
4 | WeightedResponseTimeRule | 根据平均响应事件计算所有服务的权重,响应时间越快服务权重越大被选中的概率越高,刚启动时如果统计信息不足,则使用RoundRobinRule 策略,等统计信息足够,会切换到WeightedResponseTimeRule |
5 | RetryRule | 先按照RoundRobinRule 的策略获取服务,如果获取服务失败则在指定时间内会进行重试,获取可用的服务 |
6 | BestAvailableRule | 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务 |
7 | ZoneAvoidanceRule | 复合判断server所在区域的性能和server的可用性选择服务器 |