目录
一、 介绍
Ribbon是Netflix发布的云中间层服务开源项目,其主要功能是提供客户端实现负载均衡算法。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,Ribbon是一个客户端负载均衡器,我们可以在配置文件中Load Balancer后面的所有机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器,我们也很容易使用Ribbon实现自定义的负载均衡算法。
二、 Ribbon使用一 准备工作
首先启动一个Eureka Server, 并注册两个服务提供者,服务名称为“service-producer”
三、 使用方式一 -- 同Eureka一起使用
- pom中加入Eureka Client 依赖
<?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.2.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.springcloud.stu</groupId> <artifactId>eureka-client-consumer-ribbon</artifactId> <version>0.0.1-SNAPSHOT</version> <name>eureka-client-consumer-ribbon</name> <description>eureka-client-consumer-ribbon</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Hoxton.SR4</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <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> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </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>
- Spring boot的启动类上添加@EnableEurekaClient注解来启用Eureka客户端。RestTemplate Bean上 添加@LoadBalanced注解
@SpringBootApplication @EnableEurekaClient public class RibbonClientApplication { @Bean @LoadBalanced public RestTemplate getTestTemplate() { return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(RibbonClientApplication.class, args); } }
- 调用服务提供者提供的服务
@RestController @RequestMapping("/ribbon") public class RibbonControoler { @Autowired private RestTemplate restTemplate; @Autowired private LoadBalancerClient loadBalancerClient; @GetMapping("/get") public String get(String name) { //查看负载均衡器选择了哪个服务实例 ServiceInstance instance = loadBalancerClient.choose("srvice-producer"); log.info("uri={}, instanceId={}, matadata={}", instance.getUri(), instance.getInstanceId(), instance.getMetadata()); return "producer return:"+restTemplate.getForObject("http://srvice-producer/producer/get?name="+name, String.class); } }
这里调用的地址使用的是http://srvice-producer,即注册到Eureka Server上的服务名称。
四、 使用方式二 -- 不依赖Eureka单独使用
- pom中引入spring-cloud-starter-netflix-ribbon依赖
<?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.2.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.springcloud.stu</groupId> <artifactId>ribbon-client-without-eureka</artifactId> <version>0.0.1-SNAPSHOT</version> <name>ribbon-client-without-eureka</name> <description>ribbon-client-without-eureka</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Hoxton.SR3</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <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> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </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>
-
启动类
@SpringBootApplication public class RibbonClientApplication { @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(RibbonClientApplication.class, args); } }
-
配置application.yml
server: port: 8901 spring: application: name: ribbon-without-eureka service-producer: ribbon: listOfServers: localhost:8631,localhost:8632
重点是如下配置,来代替Eureka上注册的服务列表
service-producer:
ribbon:
listOfServers: localhost:8631,localhost:8632 -
调用类和使用Eureka时相同
@RestController @RequestMapping("/ribbon") public class RibbonControoler { @Autowired private RestTemplate restTemplate; @Autowired private LoadBalancerClient loadBalancerClient; @GetMapping("/get") public String get(String name) { //查看负载均衡器选择了哪个服务实例 ServiceInstance instance = loadBalancerClient.choose("srvice-producer"); log.info("uri={}, instanceId={}, matadata={}", instance.getUri(), instance.getInstanceId(), instance.getMetadata()); return "producer return:"+restTemplate.getForObject("http://srvice-producer/producer/get?name="+name, String.class); } }
五、 Ribbon文件配置
在application.yml中进行配置
ribbon:
eager-load:
enabled: true #是否开启预加载, 默认不预加载
clients: #开启预加载的服务列表
- eureka-client-producer2
- eureka-client-producer3
eureka-client-producer:
ribbon:
#负载均衡策略
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
#同一实例最大重试次数,不包括首次调用
MaxAutoRetries: 1
# 切换实例重试的次数,不包括首次所选的server.即第一个server不成功,则切换为另一个server,仍不成功(此处也会对切换后的server重试MaxAutoRetries次),再切换下一个,切换次数有此参数设置。
MaxAutoRetriesNextServer: 1
#无论是请求超时或者socket read timeout都进行重试
OkToRetryOnAllOperations: true
#服务列表刷新间隔时间
ServerListRefreshInterval: 2000
#Apache HttpClient连接超时时间
ConnectTimeout: 2000
#Apache HttpClient读取超时时间
ReadTimeout: 30
重要:Ribbon的超时时长=(ConnectTimeout+ReadTimeout)*(MaxAutoRetries+1)*(MaxAutoRetriesNextServer+1)
六、 负载均衡策略
所有负载均衡策略都实现IRule接口
public interface IRule{
/*
* choose one alive server from lb.allServers or
* lb.upServers according to key
*
* @return choosen Server object. NULL is returned if none
* server is available
*/
public Server choose(Object key);
public void setLoadBalancer(ILoadBalancer lb);
public ILoadBalancer getLoadBalancer();
}
继承关系
策略说明(源自 https://www.cnblogs.com/idoljames/p/11698923.html)
策略类 | 命名 | 描述 |
RandomRule | 随机策略 | 随机选择server |
RoundRobinRule | 轮询策略 | 按照顺序选择server(ribbon默认策略) |
RetryRule | 重试策略 | 在一个配置时间段内,当选择server不成功,则一直尝试选择一个可用的server |
BestAvailableRule | 最低并发策略 | 逐个考察server,如果server断路器打开,则忽略,再选择其中并发链接最低的server |
AvailabilityFilteringRule | 可用过滤策略 | 过滤掉一直失败并被标记为circuit tripped的server,过滤掉那些高并发链接的server(active connections超过配置的阈值) |
ResponseTimeWeightedRule | 响应时间加权重策略 | 根据server的响应时间分配权重,响应时间越长,权重越低,被选择到的概率也就越低。响应时间越短,权重越高,被选中的概率越高,这个策略很贴切,综合了各种因素,比如:网络,磁盘,io等,都直接影响响应时间 |
ZoneAvoidanceRule | 区域权重策略 | 综合判断server所在区域的性能,和server的可用性,轮询选择server并且判断一个AWS Zone的运行性能是否可用,剔除不可用的Zone中的所有server |