Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spring Cloud教程 - Ribbon自定义规则 #6

Open
TFdream opened this issue Jul 10, 2020 · 0 comments
Open

Spring Cloud教程 - Ribbon自定义规则 #6

TFdream opened this issue Jul 10, 2020 · 0 comments

Comments

@TFdream
Copy link
Owner

TFdream commented Jul 10, 2020

Spring Cloud Ribbon 定义了 com.netflix.loadbalancer.IRule接口,我们可以根据业务场景自定义规则。

定义完规则后有2种配置方式,第一种是通过代码配置,第二种是通过配置文件;

自定义IRule

自定义GrayReleaseRule类,继承自AbstractLoadBalancerRule,代码如下:

package io.dreamstudio.springcloud.netflix.ribbon.consumer.rule;

import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.ribbon.ExtendBalancer;
import com.alibaba.cloud.nacos.ribbon.NacosServer;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.DynamicServerListLoadBalancer;
import com.netflix.loadbalancer.Server;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 自定义灰度发布规则
 * 参考 com.alibaba.cloud.nacos.ribbon.NacosRule
 * @author Ricky Fung
 */
public class GrayReleaseRule extends AbstractLoadBalancerRule {
    private final Logger LOG = LoggerFactory.getLogger(this.getClass());

    public static final String GRAY_LABEL = "gray-label";

    @Autowired
    private NacosDiscoveryProperties nacosDiscoveryProperties;

    @Override
    public Server choose(Object key) {
        try {
            Map<String, String> metadata = this.nacosDiscoveryProperties.getMetadata();
            String grayLabel = metadata.get(GRAY_LABEL);

            DynamicServerListLoadBalancer loadBalancer = (DynamicServerListLoadBalancer) getLoadBalancer();
            String name = loadBalancer.getName();

            NamingService namingService = nacosDiscoveryProperties
                    .namingServiceInstance();
            List<Instance> instances = namingService.selectInstances(name, true);
            if (CollectionUtils.isEmpty(instances)) {
                LOG.warn("no instance in service {}", name);
                return null;
            }

            List<Instance> preferList = instances;
            if (StringUtils.isNotEmpty(grayLabel)) {
                //过滤相同的
                List<Instance> sameGrayInstances = instances.stream()
                        .filter(instance -> Objects.equals(grayLabel,
                                instance.getMetadata().get(GRAY_LABEL)))
                        .collect(Collectors.toList());

                if (CollectionUtils.isEmpty(sameGrayInstances)) {
                    LOG.error("满足条件的灰度服务提供者列表为空, name = {}, gray-label = {}, instances = {}",
                            name, grayLabel, instances);
                    return null;
                } else {
                    preferList = sameGrayInstances;
                }
            }

            Instance instance = ExtendBalancer.getHostByRandomWeight2(preferList);

            return new NacosServer(instance);
        } catch (Exception e) {
            LOG.error("Nacos Gray Rule error", e);
        }
        return null;
    }

    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {

    }

}

具体实现可以参考 spring-cloud-starter-alibaba-nacos-discovery 模块中实现的 com.alibaba.cloud.nacos.ribbon.NacosRule,其目标是 同集群调用优先。

使用自定义IRule

有两种配置方式可选。

1、注解配置

/**
 * Ribbon 自定义规则
 */
@Configuration
public class MyRuleConfig {

    @Bean
    public IRule getRule(){
        return new GrayReleaseRule();
    }

}

然后在代码中调用的地方增加以下配置:

@Configuration
@RibbonClient(name="netflix-ribbon-consumer", configuration=MyRuleConfig.class)  //name:建议写服务名称     configuration:配置类
public class CloudProviderConfig {

}

2、在配置文件中配置

分两步,首先注册我们的IRule对象,如下:

/**
 * Ribbon 自定义规则
 */
@Configuration
public class MyRuleConfig {

    @Bean
    public IRule getRule(){
        return new GrayReleaseRule();
    }

}

然后,我们在application.yml文件 增加配置,格式:``` .ribbon.```` ,

<clientName>: 
    ribbon: 
        NFLoadBalancerClassName: 配置ILoadBalancer的实现类
        NFLoadBalancerRuleClassName: 配置IRule的实现类
        NFLoadBalancerPingClassName: 配置IPing的实现类
        NFWSServerListClassName: 配置ServerList的实现类
        NIWSServerListFilterClassName: 配置ServerListFilter的实现类

本文中配置如下:

spring:
  application:
    name: netflix-ribbon-02-consumer
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848 # Nacos 服务器地址

# 配置负载均衡
netflix-ribbon-02-consumer:
  ribbon:
    NFLoadBalancerRuleClassName: io.dreamstudio.springcloud.netflix.ribbon.consumer.rule.GrayReleaseRule

验证规则

首先 我们在 spring-cloud-netflix-ribbon-provider 的 application.yml文件中 增加元数据:

spring:
  application:
    name: netflix-ribbon-provider
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848 # Nacos 服务器地址
        metadata:
          gray-label: gray

然后,我们将 spring-cloud-netflix-ribbon-02-consumer application.yml文件增加一个 元数据配置:

spring:
  application:
    name: netflix-ribbon-02-consumer
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848 # Nacos 服务器地址
        metadata:
          gray-label: gray01

# 配置负载均衡
netflix-ribbon-02-consumer:
  ribbon:
    NFLoadBalancerRuleClassName: io.dreamstudio.springcloud.netflix.ribbon.consumer.rule.GrayReleaseRule

源码下载:https://github.com/TFdream/spring-cloud-tutorials/tree/master/spring-cloud-netflix-ribbon

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant