目录
3、WeightedResponseTimeRule 加权响应时间策略
5、ClientConfigEnabledRoundRobinRule 客户端配置启用线性轮询策略
9、AvailabityFilteringRule 可用性过滤策略
如果要看使用,可直接跳过前面概念看案例
一 、概念介绍
1、Ribbon是什么
——ribbon是客户端负载均衡组件
ribbon是Netflix公司的开源项目,是一款基于HTTP和TCP的客户端负载均衡组件,它是不是可以独立部署的。Spring Cloud Ribbon基于Ribbon实现,基于轮询、随机等规则自动调用服务,也可以根据需要自定义负载均衡算法。
2、认识负载均衡
在我们生活中,负载均衡也随处可见。
例子:
1)超市收银窗口可以看成是负载均衡,当超市人流过多,增设窗口降低排队,是一种负载均衡提升买单效率减少排队的策略
2)理发店理发也可以看成是负载均衡,客户进店理发分配给理发师理发或者客户自己选择某个理发师理发也是一种负载均衡策略
3)餐馆后厨也看一看成是一个负载均衡,客户点菜,分配厨师炒菜,怎么分配厨师,其内部也有其策略。
在我们程序中,负载均衡通常指的是服务器端的负载均衡,比如增设多个服务器来响应用户请求,多个服务器通过一定的管理规则来处理请求的转发。也有客户端的负载均衡。下面来介绍下
2.1 服务器端的负载均衡
服务器端负载均衡,主要通过在客户端和服务端之间增加负载均衡器来实现。而负载均衡器又分为硬件负载均衡和软件负载均衡:
- 硬件负载均衡:主要采用F5、Radware、Array、A10等硬件设备。
- 软件负载均衡:在普通的服务器(硬件)上安装具有负载均衡功能的软件,以完成请求分发进而实现负载均衡。常见的负载均衡软件有Nginx、LVS、Haproxy
原理:负载均衡器维护着一个正常服务清单,通过心跳机制来删除“出现故障的服务节点”或者追加“恢复服务的节点”,以保证清单的有效性。
客户端的请求达到服务端的负载均衡器时,负载均衡将按照某种配置好的规则从可用服务清单中选出一台服务器去处理客户端的请求。这就是服务器端负载均衡。
例子:
餐馆案例:客人(客户端)去餐馆点菜,餐馆管理人员(负载均衡器)根据客人所点菜,分配给后台某个相对闲一点能做该菜系的厨师(服务器)烹饪。
2.2 客户端的负载均衡
客户端负载均衡的实现原理和服务器端负载均衡的实现原理差不多,它们的区别是:客户端本身拥有“服务提供者”清单,而服务器端负载均衡的“服务提供者清单”存储在负载均衡器中。
在客户端负载均衡中,所有客户端节点都管理着一份自己要访问的服务提供者清单,这些清单都是从“服务中心”(Eureka、Consul等)获取的。
例子:
理发店案例:客人(客户端)去理发店理发,里边指定要求某个理发师(服务端)理发。
3、Ribbon工作原理
4、Ribbon的主要组件
-
IClientConfig
用于读取配置,默认值是DefaultConfigImpl。查看源码可以看到一些默认配置,其中配置了ZoneAwareLoadBalancer和AvailibityFilteringRule,一下是部分源码配置
public class DefaultClientConfigImpl implements IClientConfig {
public static final Boolean DEFAULT_PRIORITIZE_VIP_ADDRESS_BASED_SERVERS = Boolean.TRUE;
public static final String DEFAULT_NFLOADBALANCER_PING_CLASSNAME = "com.netflix.loadbalancer.DummyPing"; // DummyPing.class.getName();
public static final String DEFAULT_NFLOADBALANCER_RULE_CLASSNAME = "com.netflix.loadbalancer.AvailabilityFilteringRule";
public static final String DEFAULT_NFLOADBALANCER_CLASSNAME = "com.netflix.loadbalancer.ZoneAwareLoadBalancer";
public static final boolean DEFAULT_USEIPADDRESS_FOR_SERVER = Boolean.FALSE;
public static final String DEFAULT_CLIENT_CLASSNAME = "com.netflix.niws.client.http.RestClient";
public static final String DEFAULT_VIPADDRESS_RESOLVER_CLASSNAME = "com.netflix.client.SimpleVipAddressResolver";
public static final String DEFAULT_PRIME_CONNECTIONS_URI = "/";
public static final int DEFAULT_MAX_TOTAL_TIME_TO_PRIME_CONNECTIONS = 30000;
public static final int DEFAULT_MAX_RETRIES_PER_SERVER_PRIME_CONNECTION = 9;
public static final Boolean DEFAULT_ENABLE_PRIME_CONNECTIONS = Boolean.FALSE;
public static final int DEFAULT_MAX_REQUESTS_ALLOWED_PER_WINDOW = Integer.MAX_VALUE;
public static final int DEFAULT_REQUEST_THROTTLING_WINDOW_IN_MILLIS = 60000;
-
ServerList
用户获取“服务提供者”地址列表。它即可以是一组固定的地址,也可以是从“注册中心”中定期查询出的“服务提供者”地址列表。
源码分析:
这里简单看下如何从配置文件中读取,追踪ConfigurationBasedServerList
追踪源码可以看到其配置规则ServiceName.ribbon.listOfServers: xxxxx1,xxxx2,xxxx3
-
ServerListFilter
用于在原始的“服务提供者”地址列表中使用一定策略过滤一部分不符合条件的地址(仅当使用动态ServerList时使用)
-
IRule
负责处理负载均衡的规则,默认通过ZoneAvoidanceRule选择实例。Ribbon的工作流程如下:
(1)通过ServerList获取所有可用的“服务提供者”地址列表
(2)通过ServerListFilter过滤一部分“服务提供者”地址
(3)在剩下的地址中通过IRule选出一台服务器
-
Iping
用来筛掉Ping不通的实例
-
ILoadBalancer
Ribbon的入口
-
ServerListUpdater
更新ServerList。当“服务中心”上“服务提供者”实例的个数发生变化时,Ribbon里的ServerList会根据默认值PollingServerListerUpdate定时更新“服务提供者”地址列表。
5、Ribbon支持的9大负载均衡策略
核心方法都是通过choose()方法来选择一个实例
1、 RoundRobinRule 线性轮询策略
按顺序挨个请求
2、RetryRule 重试策略
在方法失效时间内不停尝试,如果失效choose()方法会返回null
3、WeightedResponseTimeRule 加权响应时间策略
4、RandomRule 随机策略
随机选取一个
5、ClientConfigEnabledRoundRobinRule 客户端配置启用线性轮询策略
6、BestAvailableRule 最空闲策略
7、PredicateBasedRule 过滤线性轮询策略
8、ZoneAvoidanceRule 区域感知轮询策略
以区域、可用服务器为基础
9、AvailabityFilteringRule 可用性过滤策略
二、Ribbon使用案例
1、配置类方式进行配置
项目结构,ribbon配置规则类不能放到@CommponentScan能扫描到的地方
pom依赖
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<!-- Generated by https://start.springboot.io -->
<!-- 优质的 spring/boot/data/security/cloud 框架中文文档尽在 => https://springdoc.cn -->
<groupId>com.dolphin</groupId>
<artifactId>RibbonRule</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>RibbonRule</name>
<description>RibbonRule</description>
<properties>
<java.version>21</java.version>
<spring-cloud.version>Greenwich.SR2</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
创建IRule的配置类
启动类中添加注解和开启负载均衡支持
@RibbonClients(value = { @RibbonClient(name = "order-service",configuration = RibbonRandomRuleConfig.class), @RibbonClient(name = "stock-service",configuration = RibbonRoundRobinRuleConfig.class) })
yaml添加服务器配置
编写测试类
运行项目测试
2、配置文件方式进行配置(更简单清晰)
项目结构
pom文件和上边一致
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<!-- Generated by https://start.springboot.io -->
<!-- 优质的 spring/boot/data/security/cloud 框架中文文档尽在 => https://springdoc.cn -->
<groupId>com.dolphin</groupId>
<artifactId>RibbonRule</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>RibbonRule</name>
<description>RibbonRule</description>
<properties>
<java.version>21</java.version>
<spring-cloud.version>Greenwich.SR2</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
开启负载均衡支持
负载IRule规则均衡配置
测试类
启动项目访问测试结果与上边案例一致,这种相对简单些