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