扩展Ribbon-基于元数据的版本控制

本文介绍了如何配置Nacos以实现微服务content-center跨集群调用user-center时,优先选择同一集群内版本匹配的服务。通过扩展Ribbon规则,实现在调用时根据元数据和集群名进行策略选择。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

假设有两个微服务一个叫user-center ,一个叫content-center。为了容灾,两个微服务在BJ集群和CD集群都有部署。
user-center ,content-center两个微服务都有不同的版本,v1版本的content-center 只能调用v1版本的user-center
要求同一集群下的应用优先调用,也就是说:content-center如果在BJ集群里那么在调用user-center微服务时优先调用BJ集群下的content-center。

下面来实现。

一、配置yml

  application:
    name: content-center
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
        cluster-name: BJ-Center
        metadata:
          target-version: v2
          version: v1
server:
  port: 8081
  application:
    name: user-center
  cloud:
    nacos:
      discovery:
        #指定Nacos的地址
        server-addr: localhost:8848
        #指定集群名称
        cluster-name: BJ-Center
        metadata:
          version: v2
          
server:
  port: 8082
  application:
    name: user-center
  cloud:
    nacos:
      discovery:
        #指定Nacos的地址
        server-addr: localhost:8848
        #指定集群名称
        cluster-name: CD-Center
        metadata:
          version: v2
server:
  port: 8083

二、content-center端扩展Ribbon


import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.client.naming.core.Balancer;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.Server;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties;
import org.springframework.cloud.alibaba.nacos.ribbon.NacosServer;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
public class NacosFinalRule extends AbstractLoadBalancerRule {
    @Autowired
    NacosDiscoveryProperties nacosDiscoveryProperties;
    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {

    }

    @Override
    public Server choose(Object o) {

        try {
            //1.拿到loadBalancer
            BaseLoadBalancer loadBalancer = (BaseLoadBalancer)this.getLoadBalancer();
            //2.拿到请求的微服务的名称
            String name = loadBalancer.getName();
            //3.用 nacosDiscoveryProperties 拿到服务发现的相关API 以及配置文件中配置的集群名字 以及配置中的目标版本
            NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();
            String clusterName = nacosDiscoveryProperties.getClusterName();
            String target_version = nacosDiscoveryProperties.getMetadata().get("target-version");
            //4.用 NocasApi 获取这个微服务的所有实例 A
            List<Instance> instances = namingService.selectInstances(name, true);
            //如果配置了目标版本,则筛选出目标版本的实例集合
            List<Instance> metadataMatchInstances = new ArrayList<>();
            if(!StringUtils.isEmpty(target_version)){
                metadataMatchInstances  = instances.stream().filter(instance ->
                        Objects.equals(instance.getMetadata().get("version"), target_version)).collect(Collectors.toList());

                if(CollectionUtils.isEmpty(metadataMatchInstances)){
                    log.warn("未找到元数据匹配的目标实例!请检查配置. target-version:{}",target_version);
                    return null;
                }
            }
            //5.如果配置了集群名称则 筛选同集群下的微服务实例集合B
            List<Instance> clusterMetadataMatchInstances = new ArrayList<>();
            if(!StringUtils.isEmpty(clusterName)){
                clusterMetadataMatchInstances  = metadataMatchInstances.stream().filter(instance -> Objects.equals(instance.getClusterName(), clusterName)).collect(Collectors.toList());
                //6.B空用A,否则用B
                if(CollectionUtils.isEmpty(clusterMetadataMatchInstances)){
                    log.warn("发生跨集群的调用,instance name:{} clusterName:{}",name,clusterName);
                    clusterMetadataMatchInstances = metadataMatchInstances;
                }
            }
            //7.用NocasApi 权重负载均衡
            Instance instance = Balancer_local.getHostByRandomWeight_local(clusterMetadataMatchInstances);
            log.info("NacosSameClusterWeightedRule.instance:url:{},port:{}",instance.getIp(),instance.getPort());
            return new NacosServer(instance);
        } catch (NacosException e) {
            log.error("NacosSameClusterWeightedRule.NacosException:",e);
            e.printStackTrace();
        }
        return null;
    }
}
class Balancer_local extends Balancer {
    public static  Instance  getHostByRandomWeight_local(List<Instance> hosts){
        return getHostByRandomWeight(hosts);
    }
}

再调用user-center时,先根据元数据得到8082,8083两个实例,再根据cluster-name 筛选出8082

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值