NACOS领域模型及负载均衡调用策略

NACOS领域模型及负载均衡调用策略

每天多学一点点~
话不多说,这就开始吧…

文章目录

1.前言

阿里,阿里爸爸,阿里爸爸开源的框架真的很精髓~

2.NACOS领域模型划分

在这里插入图片描述

 

  • NameSpace:命名空间,默认的NameSpace是public。比如,我们开发,测试环境共用一个nacos,必定我们的接口地址也是不同,而且你在开发过程中,也是不建议随意配置测试环境的,这时我们就应该用namespace来隔离我们的空间。在这里插入图片描述

     

  • group:分组。也是用来隔离的,打个比方啊,加入我们的用户服务,订单服务,仓储服务和物流服务四个服务,订单服务中有一个接口叫getData,仓储服务中也有一个接口叫getData,我们的用户服务只想调用到我们的订单服务的getData,不想调用到仓储服务的getData,这时我们可以用group分组来隔离。在这里插入图片描述

     

  • cluster:集群。打个比方,我们现在有两组集群,一组是北京的订单服务集群,北京的商品服务集群,还有一组是南京的订单服务集群,南京的商品服务集群。 我们希望北京的订单集群,优先去调用北京的商品系统,南京的优先调用南京的集群服务。并不希望我们跨地区远程调用(如果组内实在没有服务了,也可以调用,但是优先考虑同一集群的)在这里插入图片描述

     

  • metadata: 只要用于版本控制。比如,我们在开发中可能是多个版本共存的,订单的v1版本只能调商品的v1版本,订单的v2版本只能调商品的v2版本。

在这里插入图片描述

 

nacos官方文档

yml配置

spring:
  application:
    name: test-demo
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
        namespace: 0610f97e-c25d-4f49-bfb8-b340e3584b82
        group: test
        cluster-name: BJ-cluster
        metadata:
          current-version: V1
server:
  port: 8888

3.同集群优先调用策略

@Slf4j
public class TheSameClusterPriorityRule extends AbstractLoadBalancerRule {

    @Autowired
    private NacosDiscoveryProperties discoveryProperties;

    @Override
    public void initWithNiwsConfig(IClientConfig clientConfig) {

    }

    @Override
    public Server choose(Object key) {
        try {
            //第一步:获取当前服务所在的集群
            String currentClusterName = discoveryProperties.getClusterName();

            //第二步:获取一个负载均衡对象
            BaseLoadBalancer baseLoadBalancer = (BaseLoadBalancer) getLoadBalancer();

            //第三步:获取当前调用的微服务的名称
            String invokedSerivceName = baseLoadBalancer.getName();

            //第四步:获取nacos clinet的服务注册发现组件的api
            NamingService namingService = discoveryProperties.namingServiceInstance();

            //第五步:获取所有的服务实例 包括不同集群的
            List<Instance> allInstance =  namingService.getAllInstances(invokedSerivceName);

            List<Instance> theSameClusterNameInstList = new ArrayList<>();

            //第六步:过滤筛选同集群下的所有实例
            for(Instance instance : allInstance) {
                if(StringUtils.endsWithIgnoreCase(instance.getClusterName(),currentClusterName)) {
                    theSameClusterNameInstList.add(instance);
                }
            }

            Instance toBeChooseInstance ;

            //第七步:选择合适的一个实例调用
            if(theSameClusterNameInstList.isEmpty()) {

                toBeChooseInstance = TulingWeightedBalancer.chooseInstanceByRandomWeight(allInstance);  //allInstance 所有实例(包括不同集群的)

                log.info("发生跨集群调用--->当前微服务所在集群:{},被调用微服务所在集群:{},Host:{},Port:{}",
                        currentClusterName,toBeChooseInstance.getClusterName(),toBeChooseInstance.getIp(),toBeChooseInstance.getPort());
            }else {
                toBeChooseInstance = TulingWeightedBalancer.chooseInstanceByRandomWeight(theSameClusterNameInstList);// theSameClusterNameInstList 通过集群实例

                log.info("同集群调用--->当前微服务所在集群:{},被调用微服务所在集群:{},Host:{},Port:{}",
                        currentClusterName,toBeChooseInstance.getClusterName(),toBeChooseInstance.getIp(),toBeChooseInstance.getPort());
            }

            return new NacosServer(toBeChooseInstance);

        } catch (NacosException e) {
            log.error("同集群优先权重负载均衡算法选择异常:{}",e);
        }
        return null;
    }
}

yml ribbon的 细粒度配置

product-center: # 需要配置的微服务名称
  ribbon:
    NFLoadBalancerRuleClassName: com.demo.myrule.TheSameClusterPriorityWithVersionRule  

4.金丝雀版本权重负载均衡策略

金丝雀版本发布,即灰度发布,同版本同集群优先调用

@Slf4j
public class TheSameClusterPriorityWithVersionRule extends AbstractLoadBalancerRule {

    @Autowired
    private NacosDiscoveryProperties discoveryProperties;

    @Override
    public void initWithNiwsConfig(IClientConfig clientConfig) {

    }

    @Override
    public Server choose(Object key) {

        try {

            String currentClusterName = discoveryProperties.getClusterName();

            List<Instance> theSameClusterNameAndTheSameVersionInstList = getTheSameClusterAndTheSameVersionInstances(discoveryProperties);

            //声明被调用的实例
            Instance toBeChooseInstance;

            //判断同集群同版本号的微服务实例是否为空
            if(theSameClusterNameAndTheSameVersionInstList.isEmpty()) {
                //跨集群调用相同的版本
                toBeChooseInstance = crossClusterAndTheSameVersionInovke(discoveryProperties);
            }else {
                // theSameClusterNameAndTheSameVersionInstList 同集群同版本的实例
                toBeChooseInstance = TulingWeightedBalancer.chooseInstanceByRandomWeight(theSameClusterNameAndTheSameVersionInstList);
                log.info("同集群同版本调用--->当前微服务所在集群:{},被调用微服务所在集群:{},当前微服务的版本:{},被调用微服务版本:{},Host:{},Port:{}",
                        currentClusterName,toBeChooseInstance.getClusterName(),discoveryProperties.getMetadata().get("current-version"),
                        toBeChooseInstance.getMetadata().get("current-version"),toBeChooseInstance.getIp(),toBeChooseInstance.getPort());
            }

            return new NacosServer(toBeChooseInstance);

        } catch (NacosException e) {
            log.error("同集群优先权重负载均衡算法选择异常:{}",e);
            return null;
        }
    }



    /**
     * 方法实现说明:获取相同集群下,相同版本的 所有实例
     * @author:smlz
     * @param discoveryProperties nacos的配置
     * @return: List<Instance>
     */
    private List<Instance> getTheSameClusterAndTheSameVersionInstances(NacosDiscoveryProperties discoveryProperties) throws NacosException {

        //当前的集群的名称
        String currentClusterName = discoveryProperties.getClusterName();

        String currentVersion = discoveryProperties.getMetadata().get("current-version");// current-version 是配置在yml中的metadata下的

        //获取所有实例的信息(包括不同集群的)
        List<Instance> allInstance =  getAllInstances(discoveryProperties);

        List<Instance> theSameClusterNameAndTheSameVersionInstList = new ArrayList<>();

        //过滤相同集群的
        for(Instance instance : allInstance) {
            if(StringUtils.endsWithIgnoreCase(instance.getClusterName(),currentClusterName)&&
               StringUtils.endsWithIgnoreCase(instance.getMetadata().get("current-version"),currentVersion)) {

                theSameClusterNameAndTheSameVersionInstList.add(instance);
            }
        }

        return theSameClusterNameAndTheSameVersionInstList;
    }

    /**
     * 方法实现说明:获取被调用服务的所有实例
     * @author:smlz
     * @param discoveryProperties nacos的配置
     * @return: List<Instance>
     */
    private List<Instance> getAllInstances(NacosDiscoveryProperties discoveryProperties) throws NacosException {

        //第1步:获取一个负载均衡对象
        BaseLoadBalancer baseLoadBalancer = (BaseLoadBalancer) getLoadBalancer();

        //第2步:获取当前调用的微服务的名称
        String invokedSerivceName = baseLoadBalancer.getName();

        //第3步:获取nacos clinet的服务注册发现组件的api
        NamingService namingService = discoveryProperties.namingServiceInstance();

        //第4步:获取所有的服务实例
        List<Instance> allInstance =  namingService.getAllInstances(invokedSerivceName);

        return allInstance;
    }

    private Instance crossClusterAndTheSameVersionInovke(NacosDiscoveryProperties discoveryProperties) throws NacosException {

        //获取所有集群下相同版本的实例信息
        List<Instance>  crossClusterAndTheSameVersionInstList = getCrossClusterAndTheSameVersionInstList(discoveryProperties);
        //当前微服务的版本号
        String currentVersion = discoveryProperties.getMetadata().get("current-version");
        //当前微服务的集群名称
        String currentClusterName = discoveryProperties.getClusterName();

        //声明被调用的实例
        Instance toBeChooseInstance = null ;

        //没有对应相同版本的实例
        if(crossClusterAndTheSameVersionInstList.isEmpty()) {
            log.info("跨集群调用找不到对应合适的版本当前版本为:currentVersion:{}",currentVersion);
            throw new RuntimeException("找不到相同版本的微服务实例");
        }else {
            //crossClusterAndTheSameVersionInstList 所有的,同版本不同集群
            toBeChooseInstance = TulingWeightedBalancer.chooseInstanceByRandomWeight(crossClusterAndTheSameVersionInstList);

            log.info("跨集群同版本调用--->当前微服务所在集群:{},被调用微服务所在集群:{},当前微服务的版本:{},被调用微服务版本:{},Host:{},Port:{}",
                    currentClusterName,toBeChooseInstance.getClusterName(),discoveryProperties.getMetadata().get("current-version"),
                    toBeChooseInstance.getMetadata().get("current-version"),toBeChooseInstance.getIp(),toBeChooseInstance.getPort());
        }

        return toBeChooseInstance;
    }

    /**
     * 方法实现说明:跨集群环境下 相同版本的
     * @author:smlz
     * @param discoveryProperties
     * @return: List<Instance>
     */
    private List<Instance> getCrossClusterAndTheSameVersionInstList(NacosDiscoveryProperties discoveryProperties) throws NacosException {

        //版本号
        String currentVersion = discoveryProperties.getMetadata().get("current-version");

        //被调用的所有实例
        List<Instance> allInstance = getAllInstances(discoveryProperties);

        List<Instance>  crossClusterAndTheSameVersionInstList = new ArrayList<>();

        //过滤相同版本
        for(Instance instance : allInstance) {
            if(StringUtils.endsWithIgnoreCase(instance.getMetadata().get("current-version"),currentVersion)) {

                crossClusterAndTheSameVersionInstList.add(instance);
            }
        }

        return crossClusterAndTheSameVersionInstList;
    }
}

yml ribbon的 细粒度配置

order-center: # 需要配置的微服务名称
  ribbon:
    NFLoadBalancerRuleClassName: com.demo.myrule.TheSameClusterPriorityWithVersionRule

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值