火の狐 的个人博客

记录精彩的程序人生

Open Source, Open Mind,
Open Sight, Open Future!
  menu
292 文章
2704 浏览
1 当前访客
ღゝ◡╹)ノ❤️

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