基於nacos註冊中心的ribbon定製規則
阿新 • • 發佈:2020-12-15
前面說到基於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