spring-cloud微服务负载均衡器ribbon

注意: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某个负载均衡类,然后稍作修改)

bash 复制代码
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默认扫描的包下,扫描到就变成全局的负载均衡策略 )

java 复制代码
package com.test.configRibbon;

import com.netflix.loadbalancer.IRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Description:
 * @Author: xu
 * @Data: 2024-2024/4/8-11
 * @Version: V1.0
 */

@Configuration
public class RibbonConfig {

    @Bean
    public IRule iRule() {
        return new CustomRibbonRule(8083);
    }
}

利用@RibbonClient指定微服务及其负载均衡策略(RibbonConfig不能被@SpringbootApplication的@ComponentScan扫描到,否则就是全局的配置效果)

同时在启动类配置

java 复制代码
//@RibbonClient(value = "stock-nacos",configuration = {RibbonConfig.class})
@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) {
        //new NacosRule();
        RestTemplate restTemplate = builder.build();
        return restTemplate;
    }

}

方法二:在yml配置文件设置调用指定微服务提供的服务时,使用对应的负载均衡策略算法,修改application.yml

yml 复制代码
stock-nacos: # 给某个微服务配置负载均衡规则,这里是stock-nacos服务
  ribbon:
    #NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡规则
    NFLoadBalancerRuleClassName: com.test.configRibbon.CustomRibbonRule # 负载均衡规则 

开启饥饿加载,解决第一次调用慢的问题

yml 复制代码
#开启饥饿加载,解决第一次调用慢的问题
ribbon:
  eager-load:
    #开启饥饿加载
    enabled: true
    #配合stock-nacos使用ribbon饥饿加载,多个使用逗号分割
    clients: stock-nacos

如果使用loadbalancer需要排除掉ribbon依赖,或者在配置文件设置ribbon的负载均衡为false

xml 复制代码
<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>
相关推荐
编程一生2 小时前
微服务相比传统服务的优势
微服务·云原生·架构
亿坊电商2 小时前
PHP框架在微服务迁移中能发挥什么作用?
开发语言·微服务·php
prinrf('千寻)5 小时前
nacos设置权重进行负载均衡不生效
运维·负载均衡
Angindem9 小时前
SpringClound 微服务分布式Nacos学习笔记
分布式·学习·微服务
细心的莽夫17 小时前
SpringCloud 微服务复习笔记
java·spring boot·笔记·后端·spring·spring cloud·微服务
hoho不爱喝酒21 小时前
微服务Nacos组件的介绍、安装、使用
微服务·云原生·架构
RECRUITGUY1 天前
用交换机连接两台电脑,电脑A读取/写电脑B的数据
服务器·网络·负载均衡
nbsaas-boot1 天前
分布式微服务架构,数据库连接池设计策略
分布式·微服务·架构