Ribbon负载均衡
一、什么是Ribbon。
Ribbon是Netfix发布的负载均衡器,它有助于控制HTTP和TCP客户端的行为。为Ribbon配置服务提供者地址列表后,Ribbon就可基于某种负载均衡算法,自动的去帮助服务消费者去请求。Ribbon默认为我们提供了很多的负载均衡算法,例如轮询、随机等。当然,我们也可为Ribbon实现自定义的负载均衡算法。
在实际环境中,当获取的服务列表中就会有多个时,需要编写负载均衡算法,在多个实例列表中进行选择。Eureka中已经帮我们集成了负载均衡组件:Ribbon,简单修改代码即可使用。
二、使用Ribbon实现负载均衡。
1、启动两个服务实例。
2、访问 localhost:8080 查看 Eureka 监控面板。
3、开启负载均衡。
因为 Eureka 中已经集成了 Ribbon,所以无需引入新的依赖,直接修改代码即可。
3.1、在RestTemplate的配置方法上添加 @LoadBalanced 注解:
@SpringBootApplication @EnableDiscoveryClient // 开启Eureka客户端 public class ConsumerDemoApplication { @Bean @LoadBalanced public RestTemplate restTemplate(){ return new RestTemplate(new OkHttp3ClientHttpRequestFactory()); } public static void main(String[] args) { SpringApplication.run(ConsumerDemoApplication.class, args); } }
3.2、修改调用方式。不在手动获取ip和端口 ,而是直接通过服务名称调用:
@Service public class UserService { @Autowired private RestTemplate restTemplate; // Eureka客户端,可以获取到服务实例信息。 @Autowired private DiscoveryClient discoveryClient;// Eureka客户端,可以获取到服务实例信息 public List<User> queryListByIds(List<Long> ids) { List<User> users = new ArrayList<>(); // 地址直接写服务名称 String baseUrl = "http://user-service/user/"; for (Long id : ids) { // 多次查询 users.add(this.restTemplate.getForObject(baseUrl + id, User.class)); // 每次间隔500毫秒 try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } return users; } }
3.3、启动并访问 http://localhost:8082/consumer?ids=1,2
4、负载均衡策略。
Ribbon 默认的负载均衡的策略是简单的轮询。
拦截器中是使用 RibbonLoadBalanceClient 来进行负载均衡的,其中有一个方法 choose 就是负载均衡的实例方法。
编写测试类,注入 choose 方法的类对象,然后测试:
@RunWith(SpringRunner.class) @SpringBootTest(classes = ConsumerDemoApplication.class) public class LoadBalanceTest { @Autowired RibbonLoadBalancerClient client; @Test public void test(){ for (int i = 0; i < 100; i++) { ServiceInstance instance = this.client.choose("user-service"); System.out.println(instance.getHost() + ":" + instance.getPort()); } } }
结果:
定义负载均衡的规则接口为 IRule ,它有以下实现,分别对应不同的规则。
SpringBoot 也帮我们提供了修改负载均衡规则的配置入口,格式是:{服务名称}.ribbon.NFLoadBalancerRuleClassName
user-service:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
5、重试机制,通过 yml 配置文件配置。
Eureka 的服务治理强调了 CAP(一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)) 原则中的 AP,即可用性和可靠性。它与Zookeeper 这一类强调 CP(一致性,可靠性)的服务治理框架最大的区别在于:Eureka为了实现更高的服务可用性,牺牲了一定的一致性,极端情况下它宁愿接收故障实例也不愿丢掉健康实例,正如我们上面所说的自我保护机制。
spring:
cloud:
loadbalancer:
retry:
enabled: true # 开启Spring Cloud的重试功能
user-service:
ribbon:
ConnectTimeout: 250 # Ribbon的连接超时时间
ReadTimeout: 1000 # Ribbon的数据读取超时时间
OkToRetryOnAllOperations: true # 是否对所有操作都进行重试
MaxAutoRetriesNextServer: 1 # 切换实例的重试次数
MaxAutoRetries: 1 # 对当前实例的重试次数
<dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency>
重启user-consumer,测试,发现即使user-service宕机,也能通过另一台服务实例获取结果。