zoukankan      html  css  js  c++  java
  • 基于nacos注册中心的ribbon定制规则

    前面说到基于nacos的注册发现有可以扩展实现我们自己的负载均衡算法(Nacos数据模型),来实现同集群调用,是基于spring.cloud.nacos.discovery.cluster-name参数。另外基于spring.cloud.nacos.discovery.metadata参数也可以实现金丝雀发布调用。这里就使用ribbon来实现这两种负载均衡算法。

    直接使用feign调用,因为feign里面就是用的ribbon,引入feign依赖也就引入了ribbon

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
            </dependency>

    1.继承com.netflix.loadbalancer.AbstractLoadBalancerRule 实现自己的负载均衡算法,从NacosDiscoveryProperties中获取实例信息,然后筛选出来cluster-name和metadata中version相同的实例,进行调用。

    package com.nijunyang.order.ribbon.rule;
    
    import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
    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.BaseLoadBalancer;
    import com.netflix.loadbalancer.Server;
    import lombok.SneakyThrows;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    
    import java.security.SecureRandom;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * Description: 集群和版本规则
     * Created by nijunyang on 2020/12/14 21:36
     */
    @Slf4j
    public class ClusterWithVersionRule extends AbstractLoadBalancerRule {
    
    
        @Autowired
        private NacosDiscoveryProperties nacosDiscoveryProperties;
    
        /**
         * 重写choose方法
         * @param key
         * @return
         */
        @SneakyThrows
        @Override
        public Server choose(Object key) {
            //获取服务配置的集群名
            String clusterName = nacosDiscoveryProperties.getClusterName();
            //当前的版本号 配置文件配置的metadata信息
            String currentVersion = nacosDiscoveryProperties.getMetadata().get("version");
            //获取负载均衡器
            BaseLoadBalancer baseLoadBalancer = (BaseLoadBalancer) getLoadBalancer();
            //调用服务的名字
            String invokedServerName = baseLoadBalancer.getName();
            //获取namingServer(包含nacos注册发现相关api)
            NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();
            //获取被调用的服务的所有实例
            List<Instance> invokedAllInstanceList = namingService.getAllInstances(invokedServerName);
            //同集群同版本
            List<Instance> theSameClusterAndVersionList = new ArrayList<>();
            //跨集群同版本
            List<Instance> theSameVersionList = new ArrayList<>();
            for (Instance instance : invokedAllInstanceList) {
                if (clusterName.equalsIgnoreCase(instance.getClusterName())
                && currentVersion.equalsIgnoreCase(instance.getMetadata().get("version"))) {
                    theSameClusterAndVersionList.add(instance);
                } else if (currentVersion.equalsIgnoreCase(instance.getMetadata().get("version"))) {
                    theSameVersionList.add(instance);
                }
            }
            Instance invokedInstance;
            if (theSameClusterAndVersionList.isEmpty()) {
                //跨集群同版本调用, 随机选一个
                if (theSameVersionList.isEmpty()) {
                    throw new RuntimeException("无对应版本服务");
                }
                SecureRandom random = new SecureRandom();
                int i = random.nextInt(theSameVersionList.size());
                invokedInstance = theSameVersionList.get(i);
            } else {
                //同集群同版本调用 随机选一个
                SecureRandom random = new SecureRandom();
                int i = random.nextInt(theSameClusterAndVersionList.size());
                invokedInstance = theSameClusterAndVersionList.get(i);
            }
            return new NacosServer(invokedInstance);
        }
    
        @Override
        public void initWithNiwsConfig(IClientConfig iClientConfig) {
    
        }
    }

    2.配置自定义的负载均衡算法

    spring:
      application:
        name: order
      cloud:
        nacos:
          discovery:
            server-addr: 127.0.0.1:8848  #不用写协议
            #        namespace: 688bf906-8b48-4ee2-a433-828f042ec860   #test id
            #        group: pay
            cluster-name: CD
            metadata:
              version: v2
    
    ribbon:
      NFLoadBalancerRuleClassName: com.nijunyang.order.ribbon.rule.ClusterWithVersionRule #指定全局的负载均衡算法
      eager-load:
        enabled: true #饥饿加载(ribbon客户端不是在服务启动的时候加载的,所以可能第一次调用会很慢,甚至超时)
        clients: stock #指定哪些服务使用饥饿加载
    #按服务指定负载均衡算法
    stock:
      ribbon:
        NFLoadBalancerRuleClassName: com.nijunyang.order.ribbon.rule.ClusterWithVersionRule
        eager-load:
          enabled: true

    当需要指定某一服务使用某一负载均衡算法的时候,不要让spring容器扫描到该规则。在配置文件中如上配置即可。

    完整代码:https://github.com/bluedarkni/study/tree/master/cloud-alibaba

  • 相关阅读:
    Python split分割字符串
    test markdown
    Python 数字格式转换
    Python 字符串改变
    Python axis的含义
    python 第三方库
    Spark快速入门
    vim快捷键
    Hadoop HDFS负载均衡
    YARN DistributedShell源码分析与修改
  • 原文地址:https://www.cnblogs.com/nijunyang/p/14141028.html
Copyright © 2011-2022 走看看