1. 概述
Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡工具,提供客户端的软件负载均衡算法和服务调用。
LB负载均衡(LoadBalance):将用户的请求平摊的分配到多个服务上,从而达到系统的HA(高可用)
Ribbon客户端负载均衡与Nginx服务端负载均衡区别
Nginx是服务端负载均衡,客户端所有请求都会交给nginx,然后由nginx实现转发请求,即负载均衡是由服务端实现的
Ribbon是客户端负载均衡,在调用服务接口时,会在注册中心上获取注册信息服务列表之后缓存到JVM本地,从而在本地实现RPC远程服务调用
集中式负载均衡:在服务的消费方和提供方之间使用独立的LB组件(可以是硬件,如F5;也可以是软件,如nginx),由该组件负责把访问请求通过某种测了转发到服务的提供方
进程内负载均衡:将负载均衡逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的服务器
Ribbon实现负载均衡步骤
- 选择Eureka Server,优先选择在同一个区域内负载较少的server
- 根据用户指定的策略,从server获取到的服务注册列表中选择一个地址
Ribbon实现远程调用就是使用RestTemplate调用+负载均衡
2. RestTemplate远程调用
RestTemplate远程调用主要使用了get/postForObject和get/postForEntity两个方法
get/postForObject
返回对象为响应体中数据转化成的对象,类似于Json
get/postForEntity
返回对象为ResponseEntity对象,包含响应头、响应状态码和响应体
3. 引入核心依赖
<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.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
4. 编写yml配置文件
server:
port: 8780
spring:
application:
name: cloud-ribbon
eureka:
client:
register-with-eureka: false
service-url:
defaultZone: http://localhost:8761/eureka
5. 编写配置类
@Configuration
public class RestTemplateConfig {
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
}
6. 编写启动类
@SpringBootApplication
@EnableEurekaClient
public class RibbonApplication {
public static void main(String[] args) {
SpringApplication.run(RibbonApplication.class, args);
}
}
7. 编写业务接口
@RestController
@RequestMapping("/ribbon")
public class RibbonController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/getRibbonInfo/{message}")
public String getRibbonInfo(@PathVariable("message") String message) {
String respose = restTemplate.getForObject("http://CLOUD-PROVIDER/provider/getProviderInfo/" + message, String.class);
return "This is Ribbon consumer, from provider get info is " + respose;
}
}
依次启动erueka server、provider和ribbon-consumer微服务,浏览器输入地址http://localhost:8780/ribbon/getRibbonInfo/world
8. Ribbon负载均衡策略
每次RPC请求时,由Ribbon得IRule负载均衡策略接口的某个实现类来进行负载均衡
8.1. 负载均衡原理
Rest接口第几次请求数 % 服务器集群总数量 = 实际调用服务器位置下标,每次服务重新启动后Rest接口计数从1开始
8.2. 常用策略
随机策略(RandomRule)
RandomRule实现类从Provider服务列表清单中随机选择一个Provider服务实例,作为RPC请求的目标Provider
线性轮询策略(RoundRobinRule)
RoundRobinRule每次都只取下一个Provider服务器,假设一共有5台Provider服务节点,使用线性轮询策略,第1次取第1台,第2次取第2台,第3次取第3台,以此类推
响应时间权重策略(WeightedResponseTimeRule)
WeightedResponseTimeRule为每一个Provider服务维护一个权重值,它的规则简单概括为Provider服务响应时间越长,其权重就越小。在进行服务器选择时,权重值越小,被选择的机会就越少。WeightedResponseTimeRule继承了RoundRobinRule,开始时每一个Provider都没有权重值,每当RPC请求过来时,由其父类的轮询算法完成负载均衡方式。该策略类有一个默认的每30秒执行一次的权重更新定时任务,该定时任务会根据Provider实例的响应时间更新Provider权重列表。后续有RPC过来时,将根据权重值进行负载均衡
最少连接策略(BestAvailableRule)
在进行服务器选择时,该策略类遍历Provider清单,选出可用的且连接数最少的一个Provider。该策略类里面有一个LoadBalancerStats类型的成员变量,会存储所有Provider的运行状况和连接数。在进行负载均衡计算时,如果选取到的Provider为null,就会调用线性轮询策略重新选取。
如果第一次RPC请求时LoadBalancerStats成员为null,就会使用线性轮询策略来获取符合要求的实例,后续的RPC在选择的时候,才能选择连接数最少的服务。每次RPC请求时,BestAvailableRule都会统计LoadBalancerStats,作为后续请求负载均衡计算的输入
重试策略(RetryRule)
该类会在一定的时限内进行Provider循环重试。RetryRule会在每次选取之后对选举的Provider进行判断,如果为null或者not alive,就会在一定的时限内(如500毫秒)不停地选取和判断
可用过滤策略(AvailabilityFilteringRule)
该类扩展了线性轮询策略,会先通过默认的线性轮询策略选取一个Provider,再去判断该Provider是否超时可用,当前连接数是否超过限制,如果都符合要求,就成功返回。
简单来说,AvailabilityFilteringRule将对候选的Provider进行可用性过滤,会先过滤掉因多次访问故障而处于熔断器跳闸状态的Provider服务,还会过滤掉并发的连接数超过阈值的Provider服务,然后对剩余的服务列表进行线性轮询
区域过滤策略(ZoneAvoidanceRule)
该类扩展了线性轮询策略,除了过滤超时和连接数过多的Provider之外,还会过滤掉不符合要求的Zone区域中的所有节点
8.3. 自定义负载均衡策略
新建一个Rule配置类,要求其不能放在@ComponentScan所扫描的当前包下以及子包下
@Configuration
public class RibbonConfig {
/**
* 自定义负载均衡策略
* @return
*/
@Bean
IRule ribbonRule() {
return new RandomRule();
}
}
在配置类中引入该配置类
@Configuration
@RibbonClient(name = "CLOUD-PROVIDER", configuration = RibbonConfig.class)
public class ProviderConfig {
}
8.4. Ribbon常用yml配置
自定义负载均衡策略也可以配置在yml文件中
cloud-provider:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule
如果没有结合Eureka服务,配置如下:
ribbon:
eureka:
enabled: false #禁用Eureka
cloud-provider:
ribbon:
listOfServers: localhost:8771,localhost:8772 #手动配置provider清单
RPC请求超时配置,可以根据不同的业务提供者配置不同的超时时间
cloud-provider:
ribbon:
ConnectTimeout: 30000 #连接超时时间,单位毫秒
ReadTimeout: 30000 #读取超时时间,单位毫秒
重试机制配置
cloud-provider:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RetryRule #负载均衡配置为重试策略
MaxAutoRetries: 1 #同一台实例的最大重试次数,不包括首次调用,默认1次
MaxAutoRetriesNextServer: 1 #重试其他实例的最大重试次数,不包括首次调用,默认0次
OkToRetryOnAllOperations: true #是否对所有操作都进行重试,默认false
ServerListRefreshInterval: 2000 #从注册中心刷新provider的时间间隔,默认2秒
retryableStatusCodes: 400,401,403,404,500,502,504