实现Ribbon规则

@Configuration
@ConditionalOnNacosDiscoveryEnabled
public class NacosAutoConfiguration {

    @Bean
    public RouteProperties routeProperties() {
        return new RouteProperties();
    }

    @Bean
    public NacosNamingService nacosNamingService() {
        return new NacosNamingService();
    }

    @Bean
    @Scope("prototype")
    public IRule getRibbonRule() {
        return new NacosWeightLoadBalancerRule();
    }

}

@Slf4j
@Configuration
@ConditionalOnRouteEnabled
public class RouteAutoConfiguration {

    @Autowired(required = false)
    private RouteProperties routeProperties;

    @Value("${spring.cloud.nacos.discovery.namespace:}")
    private String namespace;

    @PostConstruct
    public void init() {
        NacosExecutorService.setBaseUrl(routeProperties.getAddress());
        NacosPullInstanceWorker worker = new NacosPullInstanceWorker();
        //保存路由信息交由线程池执行
        worker.run();
        int period = routeProperties.getPeriod();
        NacosExecutorService nacosExecutorService = new NacosExecutorService("nacos-pull-instance");
        nacosExecutorService.execute(period, worker);
    }

}
//创建一个调度线程执行拉取服务列表
public class NacosExecutorService {
    final ScheduledExecutorService executorService;

    private static String baseUrl;

    public static String getBaseUrl() {
        return baseUrl;
    }

    public static void setBaseUrl(String baseUrl) {
        NacosExecutorService.baseUrl = baseUrl;
    }

    public void execute(int period, Runnable task) {
        executorService.scheduleWithFixedDelay(task, 3, period, TimeUnit.SECONDS);
    }

    public NacosExecutorService(String name) {
        executorService = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors(), new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread(r);
                t.setName(name);
                t.setDaemon(true);
                return t;
            }
        });
    }
}
//拉取服务线程实例
@Slf4j
public class NacosPullInstanceWorker implements Runnable {
      @Override
    public void run() {
        HashMap paramMap = new HashMap<>();
        paramMap.put("md5", md5);


        RestTemplate restTemplate = new RestTemplate();
        TypeReference> forObject = restTemplate.getForObject(NacosExecutorService.getBaseUrl(), new TypeReference>() {
        }.getClass(), paramMap);
        List instances = (List) forObject.getType();
        if (instances == null) {
            log.warn("Nacos列表为空!");
            return;
        }
        log.debug("Nacos列表数量:{}", instances.size());
        NacosNamingService.setINSTANCE(instances);

    }
}
//实际实现策略方法
@Slf4j
public class NacosNamingService {
    @Autowired
    private NacosDiscoveryProperties discoveryProperties;

    @Autowired
    private RouteProperties routeProperties;
    public Instance getInstance(String serviceName, String groupName) throws NacosException {
        Boolean routeEnable = routeProperties.isEnable();
        if (!routeEnable) {
            return discoveryProperties.namingServiceInstance().selectOneHealthyInstance(serviceName, groupName);
        }

        GlobalContext globalContext = ContextUtil.getCurrentContext();
        if (globalContext == null) {
            globalContext = new GlobalContext();
        }
        String env = globalContext.getEnv();
        if (env == null) {
            ApplicationContext context = SpringContextUtil.getContext();
            if (context != null) {
                Environment environment = context.getEnvironment();
                env = environment.getProperty("spring.cloud.nacos.discovery.namespace", "");
            } else {
                env = "";
            }
        }
        String group = globalContext.getGroup();
        if (group == null) {
            ApplicationContext context = SpringContextUtil.getContext();
            if (context != null) {
                Environment environment = context.getEnvironment();
                group = environment.getProperty("spring.cloud.nacos.discovery.group", "");
            } else {
                group = CommonConstant.DEFAULT_GROUP;
            }
        }
        return getInstance(serviceName, env, group, globalContext.getClientIp());
    }

    public Instance getInstance(String serviceName, String envName, String groupName, String clientIp) throws NacosException {
        log.debug("getInstance serviceName:{}, envName:{}, groupName:{}, clientIp:{}", serviceName, envName, groupName, clientIp);
        List envAndGroupInstanceList = new ArrayList<>();
        List envDefaultGroupInstanceList = new ArrayList<>();
        List defaultInstanceList = new ArrayList<>();

        List instanceList = INSTANCE_MAP.get(serviceName);
        //非空校验
        if (instanceList == null || instanceList.size() == 0) {
            log.warn("Nacos服务列表为空!");
            return null;
        }
        //遍历搜索
        for (SmartInstance instance : instanceList) {
            //服务信息获取

            //优先本机匹配
            if (clientIp == null) {
                clientIp = LocalIpUtil.getLocalIp();
            }
            if (clientIp.equals(instance.getIp())) {
                return instance;
            }
            //按照下列规则路由: (环境,组) -> (环境,默认组) -> (默认环境,默认组)
            if (eq(instance.getNamespace(), envName) && eq(instance.getGroupName(),groupName)) {
                envAndGroupInstanceList.add(instance);
                continue;
            }
            if (eq(instance.getNamespace(),envName) && eq(instance.getGroupName(),CommonConstant.DEFAULT_GROUP)) {
                envDefaultGroupInstanceList.add(instance);
                continue;
            }
            if (eq(instance.getNamespace(),CommonConstant.Env.MASTER) && eq(instance.getGroupName(),CommonConstant.DEFAULT_GROUP)) {
                defaultInstanceList.add(instance);
            }
        }
        //输出路由结果
        log.debug("getInstance envAndGroupInstanceList:{} envDefaultGroupInstanceList:{} defaultInstanceList:{}",
                envAndGroupInstanceList, envDefaultGroupInstanceList, defaultInstanceList);

        //获取最合适实例
        SmartInstance instance = getSuitableInstance(envAndGroupInstanceList);
        if (instance != null) {
            return instance;
        }
        instance = getSuitableInstance(envDefaultGroupInstanceList);
        if (instance != null) {
            return instance;
        }
        return getSuitableInstance(defaultInstanceList);
    }

    /**
     * 获取包含测试网段的实例
     * @param instanceList 实例列表
     * @return
     */
    private SmartInstance getSuitableInstance(List instanceList) {
        if (instanceList.size() > 0) {
            SmartInstance instance = instanceList.get(0);
            for (SmartInstance instanceItem : instanceList) {
                if(instanceItem.getWeight() > instance.getWeight()){
                    instance = instanceItem;
                }
            }
            return instance;
        }
        return null;
    }

    static boolean eq(String s1, String s2){
        return StringUtils.equals(s1, s2);
    }

    public static void setINSTANCE(List instances) {
        if(instances != null){
            Map> map = instances.stream()
                    .collect(Collectors.groupingBy(SmartInstance::getName));
            if(map != null){
                INSTANCE_MAP = map;
            }
        }
    }
    private static Map> INSTANCE_MAP = new HashMap<>();
}
//重写获取服务的方法
@Slf4j
public class NacosWeightLoadBalancerRule extends AbstractLoadBalancerRule {
    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {
    }

    @Autowired
    private NacosNamingService nacosNamingService;

    @Autowired
    private ConfigurableApplicationContext applicationContext;
    @Override
    public Server choose(Object o) {
        String groupName = applicationContext.getEnvironment().getProperty("spring.cloud.nacos.config.group");
        if (groupName == null) {
            groupName = "DEFAULT_GROUP";
        }
        DynamicServerListLoadBalancer loadBalancer = (DynamicServerListLoadBalancer) getLoadBalancer();
        String name = loadBalancer.getName();
        try {
            Instance instance = nacosNamingService.getInstance(name, groupName);
            log.info("请求服务:{}", instance != null ? instance.getInstanceId() : null);
            return new NacosServer(instance);
        } catch (NacosException ee) {
            log.error("请求服务异常!异常信息:{}", ee);
        } catch (Exception e) {
            log.error("请求服务异常!异常信息:{}", e);
        }
        return null;
    }
}
public class SmartInstance extends Instance {

    String groupName;

    String name;

    String namespace;
    }
}

你可能感兴趣的:(实现Ribbon规则)