基於nacos註冊中心的ribbon定製規則 Nacos數據模型

前面說到基於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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章