Ribbon负载均衡

目录

一、负载均衡实现逻辑

二、负载均衡策略

三、修改负载均衡规则

四、饥饿加载


注:Ribbon拦截Eureka请求,找eureka-server拿对应服务信息,根据对应策略返回调用的ip和端口。

一、负载均衡实现逻辑

1、逻辑图

2、ClientHttpRequestInterceptor接口:客户端http请求拦截

3、LoadBalancerInterceptor类实现上面接口

java 复制代码
//该方法拦截http请求
@Override
public ClientHttpResponse intercept(final HttpRequest request,final byte[] body,final ClientHttpRequestExecution execution){
	//得到请求地址:http://user-service/user/1
	final URI originalUri = request.getURI();

	//得到服务名user-service
	String serciceName=originalUri.getHost();
	
	//RibbonLoadBalancerClient loadBalancer 进入负载均衡客户端
	return this.loadBalancer.execute(serviceName,this.requestFactory.createRequest(request,body,execution));
}

4、RibbonLoadBalancerClient类

java 复制代码
public <T> T execute(String serviceId,LoadBalancerRequest<T> request,Object hint) throws IOException{
	//根据服务名拿到服务信息 DynamicServerListLoadBalancer 动态服务列表负载均衡器
	ILoadBalancer loadBalancer=getLoadBalancer(serviceId);
	
	//根据指定策略获取具体服务IP端口
	Server server=getServer(loadBalancer,hint);
	if(server==null){
	  throw new IllegalStateException("No instances available for"+serviceId);
	}
    RibbonServer ribbonServer=new RibbonServer(serviceId,server,isSecure(server,serviceId),serverIntrospector(serviceId).getMetadata(server));
    return execute(serviceId,ribbonServer,request);
}


protected Server getServer(ILoadBalancer loadBalancer,Object hint){
	if(loadBalancer==null){
		return null;
	}
	return loadBalancer.chooseServer(hint!=null?hint:"default");
}

5、ZoneAwareLoadBalancer类

java 复制代码
@Override
public Server chooseServer(Object key){
	if(!ENABLED.get()||getLoadBalancerStats().getAvailableZones().size()<=1){
		logger.debug("Zone aware logic disabled or there is only one zone");
		return super.chooseServer(key);
	}

	Server server=null;
	try{
		LoadBalancerStats lbStats=getLoadBalancerStats();
		
	}
}

6、BaseLoadBalancer类

java 复制代码
public Server chooseServer(Object key){
	if(counter==null){
		counter=createCounter();
	}
	counter.increment();
	if(rule==null){
		return null;
	}else{
		try{
			//调用IRule规则的实现类得到ip端口
			return rule.choose(key);
		}catch(Exception e){
			logger.warn("LoadBalancer [{}]: Error choosing server for key {}",name,key,e);
			return null;
		}
	}
}
二、负载均衡策略
java 复制代码
Ribbon的负载均衡规则是一个叫做IRule的接口来定义的,每一个接口都是一种规则。

1、IRule层级(Eureka的实现类)

java 复制代码
- AbstractLoadBalancerRule:策略抽象类
	1. RetryRule:重试,重试机制的选择逻辑。
	2. ClientConfigEnabledRoundRobinRule:
		-  BestAvailableRule:最低并发,忽略哪些短路的服务器,并选择并发数较低的服务器。		
		- PredicateBasedRule:
			- AvailabilityFilteringRule:可用过滤,[[#AvailabilityFilteringRule作用]]
			- ZoneAvoidanceRule:区域权重,[[#ZoneAvoidanceRule作用]]
	3. RoundRobinRule:轮询,简单轮询服务列表来选择服务器。它是Ribbon默认的负载均衡规则。
		- WeightedResponseTimeRule:[[#WeightedResponseTimeRule作用]]
	4. RandomRule:随机,随机选择一个可用的服务器。

2、AvailabilityFilteringRule作用

对以下两种服务器进行忽略:

  • 在默认情况下,这台服务器如果3次连接失败,这台服务器就会被设置为"短路"状态。短路状态将持续30秒,如果再次连接失败,短路的持续时间就会几何级地增加。

  • 并发数过高的服务器。如果一个服务器的并发连接数过高,配置了AvailabilityFilteringRule规则的客户端也会将其忽略。并发连接数的上限,可以由客户端的<clientName>.<clientConfigNameSpace>.ActiveConnectionsLimit属性进行配置。

3、ZoneAvoidanceRule作用

  • 以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房,一个机架等。而后再对Zone内的多个服务做轮询。

4、WeightedResponseTimeRule作用

  • 为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。
三、修改负载均衡规则

1、引入依赖包

Groovy 复制代码
//eureka-ribbon 负载均衡  
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-ribbon:2.2.10.RELEASE'

2、代码方式:在order-service中的OrderApplication类中,定义一个新的IRule

java 复制代码
@Bean  
public IRule randomRule() {  
	return new RandomRule();  
}

3、 配置文件方式:在order-service的application.yml文件中,添加新的配置也可以修改规则

Groovy 复制代码
user-service:  
	ribbon:  
		# eureka负载均衡规则  
		NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
		
		# nacos负载均衡规则  
		# NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule

4、nacos的ribbon策略实现类

四、饥饿加载
  • Ribbon默认是采用懒加载,即第一次访问时才会去创建LoadBalanceClient,请求时间会很长。而饥饿加载则会在项目启动时创建,降低第一次访问的耗时。

  • 开启饥饿加载

Groovy 复制代码
ribbon:  
	eager-load:  
		# 开启饥饿加载  
		enabled: true  
		clients:  
			# 指定饥饿加载的服务名称  
			- user-service
相关推荐
Rain的Java大神之路5 天前
如何快速上传10G文件
java·spring boot·redis·后端·mysql·spring cloud·面试
需要8265 天前
MySQL 索引 B+ 树与“查询为什么变慢了
java·spring boot·spring·spring cloud·tomcat
需要8265 天前
Arthas 一个命令排查线上问题
java·jvm·spring·spring cloud
苏渡苇6 天前
Spring Insight 里如何把 Span 画成瀑布时间线
后端·spring·spring cloud·springboot·监控·apm
叶总没有会6 天前
Nacos—注册中心
spring cloud·微服务
苏渡苇7 天前
Spring Insight 里如何把 Span 收成一条链路
spring boot·spring·spring cloud·系统监控·apm
叶总没有会7 天前
微服务--分布式基础
java·spring·spring cloud·微服务
孙启超8 天前
【AI开发之Rust】第 7 课:错误处理 —— panic、Result 与 `?`
人工智能·分布式·后端·爬虫·spring cloud·架构·rust
行百里er9 天前
Spring Insight 里如何把 Span 收成一条链路
spring boot·spring cloud·监控
砍材农夫9 天前
spring|spring web|拦截器、过滤器、aop
java·spring boot·spring·spring cloud