springboot-nacos-ribbon负载均衡实现

负载均衡Ribbon

Ribbon是Netflx发布的开源项目,主要功能是提供客户端的软件负载均衡算法和服务调用。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器。我们很容易使用Ribbon实现自定义的负载均衡算法。

springboot加载配置

@Configuration
public class RibbonConfig {

@Primary
@Bean
public IRule getRule() {
    // 实现带有权重的负载均衡策略
    return new DefaultGrayLoadBalancerRule();
}

}

Ribbon核心组件IRule

RoundRobinRule:轮询,出厂默认使用轮询;
RandomRule:随机;
RetryRule:先按照RoundRobinRule的策略获取服务,如果获取服务失败则在指定时间内会进行重试,获取可用服务;
WeightedResponseTimeRule:对RandomRule的扩展,响应速度越快的实例选择权重越大,越容易被选择;
BestAvaliableRule:会先过滤由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量小的服务;
AvailabilityFilteringRule:先过滤掉故障实例,再选择并发较小的实例;
ZoneAvoidanceRule:默认规则,复合判断server所在区域的性能和server的可用性选择服务器。

实现choose方法

可以获取nacos,实现负载均衡

```java
   @Override
    public Server choose(Object key) {
        try {
            NamingService namingService = this.nacosDiscoveryProperties.namingServiceInstance();
            // 获取到所有的目标实例
            DynamicServerListLoadBalancer loadBalancer = (DynamicServerListLoadBalancer) getLoadBalancer();
            String serverName = "";
            if (key != null && !StrUtil.isEmpty((String) key)) {
                serverName = (String) key;
            } else {
                serverName = loadBalancer.getName();
            }
            List<Instance> instances = namingService.selectInstances(serverName, true);
            if (CollectionUtils.isEmpty(instances)) {
                log.warn("no instance in service {}", serverName);
                return null;
            }

            List<Instance> instancesToChoose = instances(instances);

            if (CollectionUtils.isEmpty(instancesToChoose)) {
                log.warn("no instance in service {}", serverName);
                return null;
            }
            String clusterName = this.nacosDiscoveryProperties.getClusterName();

            if (StringUtils.isNotBlank(clusterName)) {
                List<Instance> sameClusterInstances = instancesToChoose.stream()
                        .filter(instance -> Objects.equals(clusterName,
                                instance.getClusterName()))
                        .collect(Collectors.toList());
                if (!org.springframework.util.CollectionUtils.isEmpty(sameClusterInstances)) {
                    instancesToChoose = sameClusterInstances;
                } else {
                    log.warn(
                            "A test-cluster,name = {}, clusterName = {}, instance = {}",
                            serverName, clusterName, instancesToChoose);
                }
            }

            // 保留nacos默认负载均衡
            Instance instance = ExtendBalancer.getHostByRandomWeight2(instancesToChoose);
            return new NacosServer(instance);

        } catch (Exception e) {
            log.warn("Nacos error", e);
            return null;
        }
    }

Autowired自动装载

@Autowired
protected NacosDiscoveryProperties nacosDiscoveryProperties;

instances实现

    
  protected List<Instance> instances(List<Instance> instances) {
        List<Instance> target = new ArrayList<>();
        List<Instance> defaults = new ArrayList<>();
        List<Instance> result;
        String fromRegion = GrayContextHolder.getCurrentGrayContext().get("default");
        // 匹配满足region的实例
        for (Instance instance : instances) {
            Map<String, String> tarMetadata = instance.getMetadata();
            // 目标实例
                instancesResult .add(instance);
        }
        instancesResult = instancesTarget;
     return instancesResult;
    }

运行后,在nacos操作后台可以查看到主机内容。