在Nacos上,支持集群配置。集群是对指定微服务的一种虚拟分类。集群还是比较有用的,例如:
- 为了容灾,把指定微服务同时部署在两个机房(例如同城多活【其中1个机房崩溃另一个机房还能顶】、异地多活【防止自然灾害,例如地震什么的】),比如南京机房和北京机房。
- 调用时,可优先调用同机房的实例,如果同机房没有实例,再跨机房调用。
当然cluster还有很多其他作用,请各位看客自行脑补,本文将围绕上面描述的场景展开。
虽然Spring Cloud Alibaba支持集群配置,例如:
1 2 3 4 5 6
| spring: cloud: nacos: discovery: # 北京机房集群 cluster-name: BJ
|
但在调用时,服务消费者并不会优先调用同集群的实例。
本节来探讨如何扩展Ribbon,从而实现 同集群优先调用的效果,并且还能 支持Nacos权重配置。关于权重配置,在 扩展Ribbon支持Nacos权重的三种方式 一文中已经写得比较详细了。本文在前面的基础上实现同集群优先策略。
写代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| /** * 支持优先调用同集群实例的ribbon负载均衡规则. * * @author itmuch.com */ @Slf4j public class NacosRule extends AbstractLoadBalancerRule { @Autowired private NacosDiscoveryProperties nacosDiscoveryProperties; @Override public Server choose(Object key) { try { String clusterName = this.nacosDiscoveryProperties.getClusterName(); DynamicServerListLoadBalancer loadBalancer = (DynamicServerListLoadBalancer) getLoadBalancer(); String name = loadBalancer.getName(); NamingService namingService = this.nacosDiscoveryProperties.namingServiceInstance(); List<Instance> instances = namingService.selectInstances(name, true); if (CollectionUtils.isEmpty(instances)) { return null; } List<Instance> instancesToChoose = instances; if (StringUtils.isNotBlank(clusterName)) { List<Instance> sameClusterInstances = instances.stream() .filter(instance -> Objects.equals(clusterName, instance.getClusterName())) .collect(Collectors.toList()); if (!CollectionUtils.isEmpty(sameClusterInstances)) { instancesToChoose = sameClusterInstances; } else { log.warn("发生跨集群的调用,name = {}, clusterName = {}, instance = {}", name, clusterName, instances); } } Instance instance = ExtendBalancer.getHostByRandomWeight2(instancesToChoose); return new NacosServer(instance); } catch (Exception e) { log.warn("NacosRule发生异常", e); return null; } } @Override public void initWithNiwsConfig(IClientConfig iClientConfig) { } }
|
负载均衡算法:
1 2 3 4 5 6 7 8 9 10 11 12
| // Balancer来自于com.alibaba.nacos.client.naming.core.Balancer,也就是Nacos Client自带的基于权重的负载均衡算法。 public class ExtendBalancer extends Balancer { /** * 根据权重,随机选择实例 * * @param instances 实例列表 * @return 选择的实例 */ public static Instance getHostByRandomWeight2(List<Instance> instances) { return getHostByRandomWeight(instances); } }
|
写配置
1 2 3
| microservice-provider-user: ribbon: NFLoadBalancerRuleClassName: com.itmuch.cloud.study.ribbon.NacosClusterAwareWeightedRule
|
这样,服务在调用microservice-provider-user 这个服务时,就会优先选择相同集群下的实例。
配套代码