Ribbon实现负载均衡

Myth丶恋晨 2022-05-21 08:12 349阅读 0赞

Spring Cloud Ribbon是基于Netflix Ribbon实现的一套【客户端】负载均衡工具。

Ribbon会自动帮助你基于某种规则(简单轮询、随机连接等),也可以实现自定义的负载均衡算法。

负载均衡介绍:

  1. 简单来说负载均衡就是将用户的请求ping平摊的分配到多个任务上,从而是系统达到HA(高可用)。

目前主要分两种负载均衡:

  1. 集中式LB:偏硬件,服务的消费方和提供方之间使用独立的LB设施(可以是硬件,如F5。也可以是软件,如Nginx),由该设施负责把访问请求以某种策略转发至服务的提供方。
  2. 进程内LB:偏软件, 将LB逻辑集成到消费方,消费方从服务注册中心指导哪些地址可用,再自己选择一个合适的服务器(如Ribbon)。

总结:Ribbon其实就是一个软负载均衡的客户端组件,可以和其他需要请求的客户端结合使用。

Ribbon初步配置:

分析图如下:

70

实现前提:构建服务提供者集群,新开两个provider模块,注册入Eureka,提供服务,集群中服务名称必须一致。

Ribbon是客户端负载均衡工具!所以应该配置在客户端。此处使用consume工程为例,配置仅需要在客户端配置即可。配置步骤如下:

1.加入依赖,因为Riboon需要依赖Eureka运行,所以要同时加入Eureka依赖。

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-eureka</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>org.springframework.cloud</groupId>
  7. <artifactId>spring-cloud-starter-ribbon</artifactId>
  8. </dependency>
  9. <dependency>
  10. <groupId>org.springframework.cloud</groupId>
  11. <artifactId>spring-cloud-starter-config</artifactId>
  12. </dependency>

2.对实现类加入@LoadBalanced注解,即以之前实现的RestTemplate为例。

在consume工程中的SpringBoot配置类ConfigBean中增加如下注解:

  1. import org.springframework.cloud.client.loadbalancer.LoadBalanced;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.web.client.RestTemplate;
  5. /* @Configuration 注解相当于代表该类是 applicationContext.xml */
  6. @Configuration
  7. public class ConfigBean
  8. {
  9. @Bean
  10. @LoadBalanced
  11. public RestTemplate getRestTemplate(){
  12. return new RestTemplate();
  13. }
  14. }

3. 在application.yml文件中配置向注册中心注册,如果是作为消费者模块不提供服务,不应该注册自己;

  1. server:
  2. port: 9001
  3. eureka:
  4. client:
  5. register-with-eureka: false #作为消费者不提供服务,不应该注册自己
  6. service-url:
  7. defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka

4. 主启动类中加入@EnableEurekaClient注解;

  1. import org.springframework.boot.SpringApplication;
  2. import org.springframework.boot.autoconfigure.SpringBootApplication;
  3. import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
  4. import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
  5. import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
  6. @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
  7. @EnableEurekaClient
  8. public class DeptConsumer_9001_App {
  9. public static void main(String[] args) {
  10. SpringApplication.run(DeptConsumer_9001_App.class, args);
  11. }
  12. }

5. 以上步骤1~4完成后即可在controller中直接通过服务名访问系统中的微服务,服务名作为URI

consumer应用中controller实现如下:

  1. /* 原服务url */
  2. //private static final String REST_URL_PREFIX = "http://localhost:8001";
  3. /* 以服务名作为URI */
  4. private static final String REST_URL_PREFIX = "http://SPRINGCLOUDDEMO-PROVIDER-DEPT";
  5. @Autowired
  6. private RestTemplate restTemplate;
  7. @RequestMapping(value = "/dept/list")
  8. public List<Dept> list() {
  9. return restTemplate.getForObject(REST_URL_PREFIX + "/provider/dept/list", List.class);
  10. }

完成以上5个步骤就已经实现客户端负载均衡功能(此处使用的是默认轮询的规则进行负载均衡),可以访问客户端进行测试(略过)。

Ribbon核心组件IRule:根据特定算法从服务列表中选取一个需要访问的服务;

其中IRule是一个接口,有七个自带的落地实现类,可以实现不同的负载均衡算法规则:
































RoundRobinRule                                                                                                       
轮询规则(默认方法)

RandomRule


随机

AvailabilityFilteringRule


先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,还有并发的连接数量超过阈值的服务,然后对剩余的服务进行轮询

WeightedResponseTimeRule


根据平均响应时间计算服务的权重。统计信息不足时会按照轮询,统计信息足够会按照响应的时间选择服务
RetryRule
正常时按照轮询选择服务,若过程中有服务出现故障,在轮询一定次数后依然故障,则会跳过故障的服务继续轮询。
BestAvailableRule
先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务

ZoneAvoidanceRule


默认规则,符合判断server所在的区域的性能和server的可用性选择服务

如何切换Ribbon中赋值均衡的规则,而不是使用默认的轮询方式?

只需在客户端(consume)工程中的SpringBoot配置类ConfigBean配置一个返回具体方法的bean即可,如下:

  1. @Bean
  2. public IRule MyRule(){
  3. /* RandomRule为Ribbon中自带规则实现之一,随机规则 */
  4. return new RandomRule();
  5. }

自定义Ribbon负载均衡算法

  1. **如果觉得Ribbon中自带的负载均衡规则无法满足你的需求,那也可以自定义****Ribbon负载均衡算法。**

需要注意的地方;

自定义的Ribbon算法类不能放在主启动类所在的包及子包下(确切来说是不能放在@ComponentScan注解的包及子包下),否则会被全局应用到Ribbon服务中。 应该把自定义算法类放在另外新建的包下,且这个类应该是为【配置类】即加上注解@Configuration。


实现自定义Ribbon负载均衡算法的步骤:

1。将原来consumer工程中的配置类ConfigBean中返回 IRule 的Bean删掉,然后新建一个包,定义配置类,返回自定义的负载均衡规则的实现类:

  1. package com.wangcw.ribbon;
  2. import com.netflix.loadbalancer.IRule;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.context.annotation.Configuration;
  5. @Configuration
  6. public class MySelfRule
  7. {
  8. @Bean
  9. public IRule myRule() {
  10. /* 此处返回自定义的负载算法规则 */
  11. return new RandomRule_Myself();
  12. }
  13. }

2.实现自定义规则实现类RandomRule_Myself(此处实现每台服务器调用5次后,再继续轮询下一台服务器)

  1. package com.wangcw.ribbon;
  2. import com.netflix.client.config.IClientConfig;
  3. import com.netflix.loadbalancer.AbstractLoadBalancerRule;
  4. import com.netflix.loadbalancer.ILoadBalancer;
  5. import com.netflix.loadbalancer.Server;
  6. import java.util.List;
  7. public class RandomRule_Myself extends AbstractLoadBalancerRule {
  8. /*
  9. total = 0 // 当total==5以后,我们指针才能往下走,
  10. index = 0 // 当前对外提供服务的服务器地址,
  11. total需要重新置为零,但是已经达到过一个5次,我们的index = 1 */
  12. /* 总共被调用的次数,目前要求每台被调用5次 */
  13. private int total = 0;
  14. /* 当前提供服务的机器号 */
  15. private int currentIndex = 0;
  16. public Server choose(ILoadBalancer lb, Object key) {
  17. if (lb == null) {
  18. return null;
  19. }
  20. Server server = null;
  21. while (server == null) {
  22. if (Thread.interrupted()) {
  23. return null;
  24. }
  25. List<Server> upList = lb.getReachableServers();
  26. List<Server> allList = lb.getAllServers();
  27. int serverCount = allList.size();
  28. if (serverCount == 0) {
  29. return null;
  30. }
  31. if (total < 5) {
  32. server = upList.get(currentIndex);
  33. total++;
  34. } else {
  35. total = 0;
  36. currentIndex++;
  37. if (currentIndex >= upList.size()) {
  38. currentIndex = 0;
  39. }
  40. }
  41. if (server == null) {
  42. Thread.yield();
  43. continue;
  44. }
  45. if (server.isAlive()) {
  46. return (server);
  47. }
  48. server = null;
  49. Thread.yield();
  50. }
  51. return server;
  52. }
  53. @Override
  54. public Server choose(Object key) {
  55. return choose(getLoadBalancer(), key);
  56. }
  57. @Override
  58. public void initWithNiwsConfig(IClientConfig clientConfig) {}
  59. }

3.在启动类上加上注解 @RibbonClient(name = “微服务名”,configuration = XXX.class) 注解指定需要用到负载均衡的微服务名及自定义算法的class对象。

  1. @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
  2. @EnableEurekaClient
  3. @RibbonClient(name="SPRINGCLOUDDEMO-PROVIDER-DEPT",configuration=MySelfRule.class)
  4. public class DeptConsumer_9001_App {
  5. public static void main(String[] args) {
  6. SpringApplication.run(DeptConsumer_9001_App.class, args);
  7. }
  8. }

4.启动测试就可以发现已经生效。

发表评论

表情:
评论列表 (有 0 条评论,349人围观)

还没有评论,来说两句吧...

相关阅读

    相关 负载均衡Ribbon

    1. Feign 默认集成了 Ribbon Feign 是一个声明式的伪 Http 客户端,它使得写 Http 客户端变得更简单。使用 Feign,只需要创建一个接口并注

    相关 负载均衡---ribbon

    Ribbon:提供云端负载均衡,有多种负载均衡策略可供选择,可配合服务发现和断路器使用。 上一篇简单讲解了eureka的使用,这一篇文章基于上一篇的基础上,讲一下spring

    相关 Ribbon负载均衡

    1. 集中式负载均衡 > 在客户端和服务端之间使用独立的负载均衡设施(可以是硬件,如F5, 也可以是软件,如nginx、LVS等), 由该设施负责把访问请求通过某种策略转发