文章目录
前言下面来实现。
一、配置yml二、content-center端扩展Ribbon
前言
假设有两个微服务一个叫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
//如果配置了目标版本,则筛选出目标版本的实例集合
List
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
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
return getHostByRandomWeight(hosts);
}
}
再调用user-center时,先根据元数据得到8082,8083两个实例,再根据cluster-name 筛选出8082
文章来源
发表评论