注意:2020年前SpringCloud是采用Ribbon作为负载均衡实现,但是在2020后采用了LoadBalancer替代,所以要查看springboot,springcloud,sprincloudalibaba的版本链接对应,Ribbon负载均衡都是在springboot版本2.4之前使用
可以在maven查看使用的ribbon
修改默认负载均衡策略
1:查看spring-cloud的ribbon负载均衡策略有哪些,可以先进入到RandomRule负载均衡类中,然后按Ctrl+H,可以查看父类继承和子类继承之间的关联
1:自定义负载均衡类(可以复制spring-cloud的ribbon某个负载均衡类,然后稍作修改)
package com.test.configRibbon; import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.RoundRobinRule;
import com.netflix.loadbalancer.Server;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors; /*** @Description:* @Author: xu* @Data: 2024 -2024/4/8-11* @Version: V1.0*/
public class CustomRibbonRule extends AbstractLoadBalancerRule { private AtomicInteger nextServerCyclicCounter; private static final boolean AVAILABLE_ONLY_SERVERS = true ; private static final boolean ALL_SERVERS = false ; private static Logger log = LoggerFactory.getLogger( RoundRobinRule.class) ; private Integer post = 8084 ; public CustomRibbonRule ( ) { this.nextServerCyclicCounter = new AtomicInteger( 0 ) ; } public CustomRibbonRule( Integer post) { this( ) ; this.post = post; } public CustomRibbonRule( ILoadBalancer lb) { this( ) ; this.setLoadBalancer( lb) ; } public Server choose( ILoadBalancer lb, Object key) { if ( lb == null) { log.warn( "no load balancer" ) ; return null; } else { Server server = null; int count = 0 ; while ( true) { if ( server == null && count++ < 10 ) { List< Server> reachableServers = lb.getReachableServers( ) ; List< Server> allServers = lb.getAllServers( ) ; int upCount = reachableServers.size( ) ; int serverCount = allServers.size( ) ; if ( upCount != 0 && serverCount != 0 ) { server = allServers.stream( ) .filter( d -> d.getPort( ) == post) .collect( Collectors.toList( )) .get( 0 ) ; if ( server == null) { Thread.yield( ) ; } else { if ( server.isAlive( ) && server.isReadyToServe( )) { return server; } server = null; } continue ; } log.warn( "No up servers available from load balancer: " + lb) ; return null; } if ( count >= 10 ) { log.warn( "No available alive servers after 10 tries from load balancer: " + lb) ; } return server; } } } public Server choose( Object key) { return this.choose( this.getLoadBalancer( ) , key) ; } public void initWithNiwsConfig( IClientConfig clientConfig) { }
}
方法一:配置类的方式(注意RibbonConfig放的包的位置,如果放在ComponentScan默认扫描的包下,扫描到就变成全局的负载均衡策略 )
package com. test. configRibbon ; import com. netflix. loadbalancer. IRule ;
import org. springframework. context. annotation. Bean ;
import org. springframework. context. annotation. Configuration ; @Configuration
public class RibbonConfig { @Bean public IRule iRule ( ) { return new CustomRibbonRule ( 8083 ) ; }
}
利用@RibbonClient指定微服务及其负载均衡策略(RibbonConfig不能被@SpringbootApplication的@ComponentScan扫描到,否则就是全局的配置效果)
同时在启动类配置
@RibbonClients ( { @RibbonClient ( value = "stock-nacos" , configuration = { RibbonConfig . class } ) } )
public class OrderLoadbalancerApplication { public static void main ( String [ ] args) { SpringApplication . run ( OrderLoadbalancerApplication . class , args) ; } @Bean @LoadBalanced public RestTemplate restTemplate ( RestTemplateBuilder builder) { RestTemplate restTemplate = builder. build ( ) ; return restTemplate; } }
方法二:在yml配置文件设置调用指定微服务提供的服务时,使用对应的负载均衡策略算法,修改application.yml
stock-nacos : ribbon : NFLoadBalancerRuleClassName : com.test.configRibbon.CustomRibbonRule
开启饥饿加载,解决第一次调用慢的问题
ribbon : eager-load : enabled : true clients : stock- nacos
如果使用loadbalancer需要排除掉ribbon依赖,或者在配置文件设置ribbon的负载均衡为false
< dependency> < groupId> com.alibaba.cloud</ groupId> < artifactId> spring-cloud-starter-alibaba-nacos-discovery</ artifactId> < exclusions> < exclusion> < artifactId> spring-cloud-starter-netflix-ribbon</ artifactId> < groupId> org.springframework.cloud</ groupId> </ exclusion> </ exclusions>
</ dependency>