【SpringCloud】什么是 Ribbon 以及入门案例

  • Post author:
  • Post category:其他


在这里插入图片描述



1、什么是 Ribbon?

Ribbon 是一个基于 HTTP 和 TCP 的客户端负载均衡工具,它是基于 Netflix Ribbon 实现的。

它不想 Spring Cloud 服务注册中心、配置中心、API网关那样独立部署,但是它几乎存在于每个Spring Cloud 微服务中。包括 Feign 提供的声明式服务调用也是基于该 Ribbon 实现的。

Ribbon 默认提供很多种负载均衡算法,例如轮询、随机等等,甚至包含自定义的负载均衡算法。



2、Ribbon 解决了什么问题?

Ribbon 提供了一套微服务的负载均衡解决方案。



3、负载均衡不同方案的区别

目前业界主流的负载均衡方案可分成两类:

  • 集中式负载均衡(服务器负载均衡),即在 consumer 和 provider 之间使用独立的负载均衡设施(可以是硬件,如 F5,也可以是软件,如Nginx),由该设施负责把访问请求通过某种策略转发至 provider;
  • 进程内负载均衡(客户端负载均衡),将负载均衡逻辑继承到 consumer,consumer 从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的 provider。

Ribbon 属于后者,它只是一个类库,集成于 consumer 进程,consumer 通过它来获取 provider 的地址。



3.1、集中式负载均衡

image-20220510221519331



3.2、进程内负载均衡

image-20220510221627567



4、Ribbon 负载均衡策略



4.1、轮询策略(默认)

策略对应类名:RoundRobinRule

实现原理:轮询策略表示每次都顺序取下一个 provider,比如一共有 5 个 provider,第1次取第1个,第2次取第2个,第3次取第3个,以此类推。



4.2、权重轮询策略

策略对应类名:WeightedResponseTimeRule

实现原理:

  • 根据每个 provider 的响应时间分配一个权重,响应时间越长,权重越小,被选中的可能性越小。
  • 原理:一开始为轮询策略,并开启一个计时器,每 30 秒收集一次每个 provider 的平均响应时间,当信息足够时,给每个 provider 附上一个权重,并按权重随机选择 provider,越高权重的 provider 会被高概率选中。



4.3、随机策略

策略对应类名:RandomRule

实现原理:从 provider 列表中随机选择一个。



4.4、最少并发数策略

策略对应类名:BestAvailableRule

实现原理:选择正在请求中的并发数最小的 provider,除非这个 provider 在熔断中。



4.5、重试策略

策略对应类名:RetryRule

实现原理:其实就是轮询策略的增强版,轮询策略当服务不可用时不做处理,而重试策略在服务不可用时会重新尝试集群中的其他节点。



4.6、可用性敏感策略

策略对应类名:AvailabilityFilteringRule

实现原理:过滤性能差的 provider

  • 第一种:过滤掉在 Eureka 中处于一直连接失败的 provider
  • 第二种:过滤掉高并发(繁忙)的 provider



4.7、区域敏感性策略

策略对应类名:ZoneAvoidanceRule

实现原理:

  • 以一个区域为单位考察可用性,对于不可用的区域整个丢弃,从剩下区域中选可用的 provider
  • 如果这个 ip 区域内有一个或多个实例不可达或响应变慢,都会降低该 ip 区域内其他 ip 被选中的权重



5、Ribbon 入门案例

在笔者的前几篇文章中,我们建立了 eureka-demo,那么我们就基于这个案例项目对 Ribbon 进行学习。

我们在 eureka-demo 项目中创建子项目 server-provider02,与之前的项目一样:

添加依赖

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <artifactId>service-consumer</artifactId>
  <version>1.0-SNAPSHOT</version>

  <parent>
    <groupId>org.fengluo</groupId>
    <artifactId>eureka-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>

  <name>service-consumer</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>

  <dependencies>
    <!-- netflix eureka server 依赖 -->
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>

    <!-- spring boot web 依赖 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
    </dependency>

    <!-- spring boot test 依赖 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
      <exclusions>
        <exclusion>
          <groupId>org.junit.vintage</groupId>
          <artifactId>junit-vintage-engine</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
  </dependencies>

  <build>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-jar-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
        <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
        <plugin>
          <artifactId>maven-site-plugin</artifactId>
          <version>3.7.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-project-info-reports-plugin</artifactId>
          <version>3.0.0</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

添加配置文件(注意修改一下端口,我这边修改成了7071)

server:
  port: 7071 # 端口

spring:
  application:
    name: service-provider # 注册名称

# 配置 Eureka Server 注册中心
eureka:
  instance:
    prefer-ip-address: true # 是否使用 ip 地址注册
    instance-id: ${spring.cloud.client.ip-address}:${server.port} # ip:port
  client:
    service-url: # 设置服务注册中心地址
      defaultZone: http://root:123456@localhost:8761/eureka/,http://root:123456@localhost:8762/eureka/

# 度量指标监控与健康检查
management:
  endpoints:
    web:
      exposure:
        include: shutdown # 开启 shutdown 访问
  endpoint:
    shutdown:
      enabled: true # 开启 shutdown 实现停服

将 server-provider 中的服务以及启动类复制过来即可!

image-20220511194153336

这里注意我们为了观察负载均衡机制的效果,采用了第二种方法,即通过客户端负载均衡获取服务,并打印访问的 provider 的 ip 地址和端口号,并关闭了启动类的 负载均衡注解!

@Override
public Order selectOrderById(Integer id) {
    return new Order(id, "order-001", "中国", 31994D,
                     selectProductListByLoadBalancerClient());
}

………
    
sb = new StringBuffer();
sb.append("http://" + si.getHost() + ":" + si.getPort() + "/product/list");
System.out.println(sb);

启动注册中心

image-20220511193715333

最后我们启动消费者,并多次访问 http://localhost:9090/order/1,可以看到访问的 ip,即 Ribbon 的默认负载均衡策略,轮询。

image-20220511194524079



版权声明:本文为qq_45523411原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。