1. 程式人生 > 實用技巧 >基於nacos註冊中心的ribbon定製規則

基於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