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
相关推荐
Devin~Y1 小时前
从内容社区到AIGC客服:Spring Boot、Redis、Kafka、K8s、RAG的三轮大厂Java面试对话(附标准答案)
java·spring boot·redis·spring cloud·kafka·kubernetes·micrometer
西凉的悲伤2 小时前
Spring Boot 、Spring Cloud 微服务架构认证授权方案
spring boot·spring cloud·微服务·架构·认证授权
phltxy1 天前
HAProxy安装与RabbitMQ负载均衡配置
分布式·rabbitmq·负载均衡
西凉的悲伤1 天前
Spring Cloud Gateway介绍
java·spring cloud·gateway
JAVA社区2 天前
Java高级全套教程(十)—— SpringCloudAlibaba超详细实战详解
java·开发语言·spring cloud·面试·职场和发展
JAVA社区2 天前
Java高级全套教程(九)—— SpringCloud超详细实战详解
java·开发语言·后端·spring cloud·面试·职场和发展
Devin~Y2 天前
大厂Java面试实录:Spring Boot/Cloud、Kafka、Redis、K8s 可观测性 + RAG/Agent(小Y翻车版)
java·spring boot·redis·spring cloud·kafka·kubernetes·mybatis
菜萝卜子2 天前
【Docker】Harbor 代理缓存(Pull-Through Cache)配置与使用指南
spring cloud·云原生·eureka
苏渡苇2 天前
Spring Cloud Gateway 网关限流
spring cloud·gateway·springboot·网关限流