206 Netflix Ribbon 负载均衡
通过 Spring Cloud 的封装,可以让我们轻松地将面向服务的 REST 模版请求自动转换成客户端负载均衡的服务调用。Ribbon作为后端负载均衡器,比Nginx更注重的是承担并发而不是请求分发,可以直接感知后台动态变化来指定分发策略。Ribbon是一个客户端负载均衡软件,通过注册到Eureka上的服务名,获取服务列表,缓存到本地,选择负载均衡算法,发送http请求。在spring clou
Netflix Ribbon
- Netflix Ribbon
- 【1】工作图解
- 【2】POM依赖
- 【3】配置方式
- 【4】核心知识点
- 【4.1】负载均衡策略
- 【4.2】请求流程源码
- 【4.3】负载均衡源码
Netflix Ribbon
【1】工作图解
作用:主要提供客服端负载均衡
简介:Spring Cloud Ribbon 是一个基于 HTTP 和 TCP 的客户端负载均衡工具,它基于 Netflix Ribbon 实现。通过 Spring Cloud 的封装,可以让我们轻松地将面向服务的 REST 模版请求自动转换成客户端负载均衡的服务调用。
【2】POM依赖
<!--ribbon依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
【3】配置方式
全局配置:
ribbon:
# NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #配置规则 随机
# NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule #配置规则 轮询
# NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RetryRule #配置规则 重试
# NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule #配置规则 响应时间权重
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule
#以下的配置需要配合fegin使用
#ConnectTimeout: 1000 #请求连接超时时间
#ReadTimeout: 1000 #请求处理的超时时间
#OkToRetryOnAllOperations: true #对所有请求都进行重试
#MaxAutoRetriesNextServer: 0 #切换实例的重试次数
#MaxAutoRetries: 1 #对当前实例的重试次数
指定服务配置:
# 指定设置module-user-service 表示作用到哪个微服务
module-user-service:
ribbon:
# NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #配置规则 随机
# NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule #配置规则 轮询
# NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RetryRule #配置规则 重试
# NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule #配置规则 响应时间权重
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule
#以下的配置需要配合fegin使用
# ConnectTimeout: 500 #请求连接超时时间
# ReadTimeout: 500 #请求处理的超时时间
# OkToRetryOnAllOperations: true #对所有请求都进行重试
# MaxAutoRetriesNextServer: 1 #切换实例的重试次数
# MaxAutoRetries: 2 #对当前实例的重试次数
有的地方说需要开启loadbalancer,这里验证默认是开启的
spring:
application:
name: module-user-ribbon
cloud:
loadbalancer:
retry:
enabled: true #开启重试
hystrix与ribbon组合使用的时候,需要注意execution.isolation.thread.timeoutInMilliseconds的时间要大于ribbon的处理时间
hystrix:
command:
default:
execution.isolation.thread.timeoutInMilliseconds: 5000 # 请求5S超时后,执行熔断方法
启动配置
package com.it.springcloud;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RoundRobinRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
/***
* @description UserRibbonStart
* @return
*/
@SpringBootApplication
@EnableEurekaClient
public class UserRibbonStart {
public static void main(String[] args) {
SpringApplication.run(UserRibbonStart.class);
}
@Bean
//提供负载均衡的功能
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
@Bean
public IRule ribbonRule() {
return new RoundRobinRule();//这里配置策略,和配置文件对应
}
}
使用方式:
package com.it.springcloud.service;
import com.it.springcloud.basic.ResponseWrap;
import com.it.springcloud.exception.ProjectException;
import com.it.springcloud.req.UserVo;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.client.RestTemplate;
import java.util.Date;
/**
* @ClassName UserController.java
* @Description 用户controller
*/
@Service
public class UserRibbonService {
@Autowired
RestTemplate restTemplate;
private static String BASIC_URL ="http://module-user-service";
/***
* @description 注册用户
* @param userVo 注册信息
* @return: java.lang.Boolean
*/
public ResponseWrap<Boolean> registerUser(UserVo userVo) throws ProjectException {
return restTemplate.postForObject(BASIC_URL+"/user/register",
userVo,
ResponseWrap.class);
}
.....
}
【4】核心知识点
【4.1】负载均衡策略
Ribbon作为后端负载均衡器,比Nginx更注重的是承担并发而不是请求分发,可以直接感知后台动态变化来指定分发策略。它一共提供了7种负载均衡策略:
策略名 | 策略声明 | 策略描述 | 实现说明 |
---|---|---|---|
BestAvailableRule | public class BestAvailableRule extends ClientConfigEnabledRoundRobinRule | 选择一个最小的并发请求的server | 逐个考察Server,如果Server被tripped了,则忽略,在选择其中ActiveRequestsCount最小的server |
AvailabilityFilteringRule | public class AvailabilityFilteringRule extends PredicateBasedRule | 过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值) | 使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个server的运行状态 |
WeightedResponseTimeRule | public class WeightedResponseTimeRule extends RoundRobinRule | 根据响应时间分配一个weight,响应时间越长,weight越小,被选中的可能性越低。 | 一个后台线程定期的从status里面读取评价响应时间,为每个server计算一个weight。Weight的计算也比较简单responsetime 减去每个server自己平均的responsetime是server的权重。当刚开始运行,没有形成status时,使用roubine策略选择server。 |
RetryRule | public class RetryRule extends AbstractLoadBalancerRule | 对选定的负载均衡策略机上重试机制。 | 在一个配置时间段内当选择server不成功,则一直尝试使用subRule的方式选择一个可用的server |
RoundRobinRule | public class RoundRobinRule extends AbstractLoadBalancerRule | roundRobin方式轮询选择server | 轮询index,选择index对应位置的server |
RandomRule | public class RandomRule extends AbstractLoadBalancerRule | 随机选择一个server | 在index上随机,选择index对应位置的server |
ZoneAvoidanceRule | public class ZoneAvoidanceRule extends PredicateBasedRule | 复合判断server所在区域的性能和server的可用性选择server | 使用ZoneAvoidancePredicate和AvailabilityPredicate来判断是否选择某个server,前一个判断判定一个zone的运行性能是否可用,剔除不可用的zone(的所有server),AvailabilityPredicate用于过滤掉连接数过多的Server。 |
yml文件配置:
# 指定设置名称为module-user-service 服务
module-user-service:
ribbon:
# NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #配置规则 随机
# NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule #配置规则 轮询
# NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RetryRule #配置规则 重试
# NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule #配置规则 响应时间权重
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
启动类:
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
@Bean
public IRule ribbonRule() {
return new RandomRule();//这里配置策略,和配置文件对应
}
一定记得为IRule指定yml文件中选择的配置,很多文章没有。里面配具体的策略。
【4.2】请求流程源码
Ribbon是一个客户端负载均衡软件,通过注册到Eureka上的服务名,获取服务列表,缓存到本地,选择负载均衡算法,发送http请求。
在spring cloud可以通过简单配置,即可完成客户端负载均衡,用法如下:配置,注入,请求
LoadBalancerInterceptor
作用:对负载服务的拦截处理,用户发起请求时候他会处理3件事情:
- 获得请求的路径:request.getURI()
- 获得目标服务:originalUri.getHost()
- 执行调用:this.loadBalancer.execute、
- LoadBalancerClient
作用:执行目标请求
点击this.loadBalancer.execute进入LoadBalancerClient
public interface LoadBalancerClient extends ServiceInstanceChooser {
<T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException;
/**
* 使用来自LoadBalancer的ServiceInstance,对起执行请求
* @param serviceId
* @param 服务实例
* @param Request。允许在执行前后添加metric
* @return 回调结果
*/
<T> T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest<T> request) throws IOException;
/**
* 创建一个真正的URL包含主机和端口:
* http://myservice/path/to/service --> http://host:port/path/to/service
* @param 服务实例
* @param 源url,是一个包含serviceId或者dns的URL
* @return 重新构造的URL
*/
URI reconstructURI(ServiceInstance instance, URI original);
}
RibbonLoadBalancerClient
作用:是LoadBalancerClient的实现,进行追踪源码:
继续追踪,ILoadBalancer是一个方法重要的接口
ILoadBalancer
public interface ILoadBalancer {
void addServers(List<Server> var1); // 初始化服务列表
Server chooseServer(Object var1); // 从列表中选择一个服务
void markServerDown(Server var1); // 标记服务为down
List<Server> getReachableServers(); // 获取up和reachable的服务
List<Server> getAllServers();//获取所有服务(reachable and unreachable)
}
【4.3】负载均衡源码
在刚才的代码中,可以看到获取服务使通过一个getServer
方法:
进入到loadBalancer.chooseServer方法
我们继续跟入:
继续跟踪源码chooseServer方法,发现这么一段代码:
我们看看这个rule是谁:
这里的rule默认值是一个RoundRobinRule
,
我们注意到,这个类其实是实现了接口IRule的,查看一下:
定义负载均衡的规则接口。
它有规则实现
更多推荐
所有评论(0)