注意: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 {@Beanpublic 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@LoadBalancedpublic 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: trueclients: 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>