1、Ribbon
1.1 Ribbon使用场景
在Eureka篇的案例中,我们启动了一个user-service,然后通过DiscoveryClient来获取服务实例信息,然后获取ip和端口来访问。
但是实际环境中,我们往往会开启很多个user-service的集群。此时我们获取的服务列表中就会有多个,到底该访问哪一个呢?
一般这种情况下我们就需要编写负载均衡算法,在多个实例列表中进行选择。
不过Eureka中已经帮我们集成了负载均衡组件:Ribbon,简单修改代码即可使用。
1.2 什么是Ribbon
Ribbon是Netlix 发布的负载均衡器,它有助于控制HTTP和TCP客户端的行为。
为Ribbon配置服务提供者地址列表后,Ribbon 就可基于某种负载均衡算法,自动地帮助服务消费者去请求。Ribbon 默认为我们提供了很多的负载均衡算法,例如轮询、随机等。当然,我们也可为Ribbon实现自定义的负载均衡算法。
2、入门案例
首先启动两个user-service实例,一个9091,一个9092。
在user-service中配置如下端口:
server:
port: ${port:9091}
在启动配置中配置如下
Eureka监控面板:
开启负载均衡
因为Eureka中已经集成了Ribbon,所以我们无需引入新的依赖。直接修改代码:
1)在RestTemplate的配置方法上添加 @LoadBalanced 注解:
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
2)修改调用方式,不再手动获取ip和端口,而是直接通过服务名称调用:
@GetMapping("/{id}")
public User queryById(@PathVariable("id") Long id) {
String url = "http://user-service/user/" + id;
return restTemplate.getForObject(url, User.class);
}
3、Ribbon原理
为什么只输入了service名称就可以访问了呢?之前还要获取ip和端口。
显然是有组件根据service名称,获取到了服务实例的ip和端口。因为 consumer-demo 使用的是RestTemplate,spring使用LoadBalancerInterceptor拦截器 ,这个类会在对RestTemplate的请求进行拦截,然后从Eureka根据服务id获取服务列表,随后利用负载均衡算法得到真实的服务地址信息,替换服务id。
3.1 负载均衡策略
Ribbon默认使用的是轮询的负载均衡策略,也就是各个实例依次交替执行。
SpringBoot也帮我们提供了修改负载均衡规则的配置入口:
user-service:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
格式是: {服务名称}.ribbon.NFLoadBalancerRuleClassName ,值就是IRule的实现类。