前言:
一般来说,在生成环境中,各个微服务都会部署多个实例,那么服务消费者要如何将请求分摊到多个服务提供者实例上呢?
1.Ribbon 简介
Ribbon 是Netflix 发布的负载均衡器,它有助于HTTP和TCP客户端的行为。为Ribbon配置服务提供者地址列表后,Ribbon就可以基于某种负载均衡算法,自动地帮助服务消费者去请求。Ribbon默认提供了很多的负载均衡算法,例如: 轮询丶随机等。当然也可以为Ribbon实现自定义的负载均衡算法。
在Spring Cloud中,当Ribbon与Eureka配合使用时,Ribbon可以自动从Eureka Server获取服务提供者地址列表,并基于负载均衡算法,请求其中一个服务提供者实例,大致架构如图:
2.为服务消费者整合Ribbon
步骤:
1.项目引入Ribbon依赖,如果已经引入了Eureka-client依赖,依赖已经包含了此依赖,则不需要引入这个,
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
2.为RestTemplate添加@LoadBalanced注解
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
3.对前面文章项目中的Controller进行修改,修改后如下:
@Autowired
private RestTemplate restTemplate;
@Autowired
private LoadBalancerClient loadBalancerClient;
@GetMapping("/user/{id}")
public User findById(@PathVariable Long id){
return this.restTemplate.getForObject("http://mic/"+id, User.class);
}
@GetMapping("/log-user-instance")
public void logUserInstance(){
ServiceInstance serviceInstance = this.loadBalancerClient.choose("mic");
log.info(serviceInstance.getServiceId()+" "+serviceInstance.getHost() +" "+serviceInstance.getPort() );
}
3.测试
1.启动Eureka项目
2.启动2个或者更多的mic实例
3.启动movie-ribbon项目
4.访问:http://localhost:8761,如下图
5.多次访问http://localhost:8011/log-user-instance,控制台打印如下日志:
2020-05-31 15:59:28.645 INFO 2724 --- [nio-8010-exec-7] c.s.movie.controller.MovieController : mic 192.168.1.110 8000
2020-05-31 15:59:28.798 INFO 2724 --- [nio-8010-exec-9] c.s.movie.controller.MovieController : mic 192.168.1.110 8001
2020-05-31 15:59:28.957 INFO 2724 --- [nio-8010-exec-1] c.s.movie.controller.MovieController : mic 192.168.1.110 8000
2020-05-31 15:59:29.114 INFO 2724 --- [nio-8010-exec-3] c.s.movie.controller.MovieController : mic 192.168.1.110 8001
2020-05-31 15:59:29.290 INFO 2724 --- [nio-8010-exec-5] c.s.movie.controller.MovieController : mic 192.168.1.110 8000
2020-05-31 15:59:29.425 INFO 2724 --- [nio-8010-exec-7] c.s.movie.controller.MovieController : mic 192.168.1.110 8001
2020-05-31 15:59:29.575 INFO 2724 --- [nio-8010-exec-9] c.s.movie.controller.MovieController : mic 192.168.1.110 8000
可以看出,此时请求会均匀分布到两个用户微服务,说明一件实现了负载均衡。
movie-ribbon项目下载地址为:
ps: 虚拟主机名,不能包含"_"之类的字符,否则Ribbon在调用时候会报异常。
4.Ribbon配置自定义
很多场景下,可能根据需要自定义Ribbon的配置。例如修改Ribbon的负载均衡规则等。
Spring Cloud Edgware允许使用Java代码或者属性自定义Ribbon的配置,两种方式都是等价的。
1.配置指定名称的Ribbon Client
在Spring Cloud中,Ribbon默认的配置类是RibbonClientConfiguration。也可以使用一个POJO自定义Ribbon的配置(自定义配置会覆盖默认配置)。这种配置是细粒度的,不同名称的Ribbon客户端可使用不同配置。
实践;
1.复制项目movie-ribbon将ArtifactId修改为movie-ribbon-custom
2.创建Ribbon的配置类,为了演示方便,就直接扫描了此类,没有排除出去,其实需要注意,以下的注意事项
@Configuration
public class RibbonConfiguration {
@Bean
public IRule ribbonRule(){
// 负载均衡规则,改为随机
return new RandomRule();
}
}
3.测试:
1.启动rueka项目
2.启动2个或者更多mic实例
3.启动movie-ribbon-costom项目
4.多次访问http://localhost:8010/log-user-instance,可获取如下日志:
2020-05-31 16:39:19.370 INFO 29996 --- [nio-8010-exec-1] c.s.movie.controller.MovieController : mic 192.168.1.110 8000
2020-05-31 16:39:19.484 INFO 29996 --- [nio-8010-exec-3] c.s.movie.controller.MovieController : mic 192.168.1.110 8000
2020-05-31 16:39:19.661 INFO 29996 --- [nio-8010-exec-5] c.s.movie.controller.MovieController : mic 192.168.1.110 8001
2020-05-31 16:39:19.795 INFO 29996 --- [nio-8010-exec-7] c.s.movie.controller.MovieController : mic 192.168.1.110 8000
2020-05-31 16:39:19.931 INFO 29996 --- [nio-8010-exec-9] c.s.movie.controller.MovieController : mic 192.168.1.110 8001
2020-05-31 16:39:20.065 INFO 29996 --- [nio-8010-exec-1] c.s.movie.controller.MovieController : mic 192.168.1.110 8000
2020-05-31 16:39:20.184 INFO 29996 --- [nio-8010-exec-2] c.s.movie.controller.MovieController : mic 192.168.1.110 8000
此时请求会随机分布到两个用户微服务节点上,说明已经实现了Ribbon的自定义配置。
ps: 必须注意的是,例子中的RibbonConfigurtaion类不能存放在主应用程序上下文的@ComponetScan所扫描的包中,否则改类中的配置信息将被所有的@RibbonClient共享。因此,如果只想自定义某一个Ribbon客户端的配置,必须防止@Configuration注解的类所在的包与@ComponetScan扫描的包重叠,或者显示指定@ComponetScan不扫描@Configurtaion所在的包。
2.使用属性自定义Ribbon配置
从Spring Cloud Netflix 1.2.0开始,Ribbon支持使用属性自定义,这种方式比使用Java代码配置的方式更加方便
支持的属性如下:
配置的前缀是<ClientName>.ribbon.。其中<ClientName>是RibbonClient的名称,如果省略,则表示全局配置
1.NFLoadBalancerClassName: 配置LoadBalancer的实现类
2.NFLoadBalancerRuleClassName: 配置IRule的实现类
3.NFLoadBalancerPingClassName: 配置IPing的实现类
4.NIWSServerListClassName: 配置ServerList的实现类
5.NIWSServerListFilterClassName: 配置ServerListFilter的实现类
ps: 属性配置的方式比Java代码配置的方式优先级更高