文章目录
- Pre
- 需求
- 工程
- Code
- 继承AbstractLoadBalancerRule实现自定义Rule
- 随机权重策略
- 配置
- 验证
- 源码
Pre
Spring Cloud Alibaba - 05 Nacos 领域模型_NameSpac/Group/Cluster
中提到了同一个Namespace下 同一个Group下, 不同Cluster 内的服务,可以互相访问.
如果我们要想实现一个 同集群优先权重负载均衡算法, 怎么办呢?
比如实现如下调用
需求
举个例子: 有两个微服务artisan-order-center, artisan-product-center
。我们在北京机房部署一套artisan-order-center,artisan-product-center
。为了容灾处理,我们在广东同样部署一套artisan-order-center,artisan-product-center
。
但是 北京的artisan-order-center
访问广东的 artisan-product-center
毕竟不如调用本地的artisan-product-center
快。 如果本地的artisan-product-center
挂掉了,那么再访问广东的artisan-product-center
。
工程
接着 Spring Cloud Alibaba - 10 Ribbon 自定义负载均衡策略(权重算法) 中的工程,我们继续改造。
Code
继承AbstractLoadBalancerRule实现自定义Rule
代码语言:javascript复制package com.artisan.customrules;
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.ribbon.NacosServer;
import com.alibaba.nacos.api.exception.NacosException;
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.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
/**
* @author 小工匠
* @version 1.0
* @description: 同一个集群优先调用策略
* @date 2022/2/3 0:47
* @mark: show me the code , change the world
*/
@Slf4j
public class SameClusterPriorityRule extends AbstractLoadBalancerRule {
@Autowired
private NacosDiscoveryProperties discoveryProperties;
@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) {
}
@Override
public Server choose(Object key) {
try {
//第一步:获取当前服务所在的集群
String currentClusterName = discoveryProperties.getClusterName();
//第二步:获取一个负载均衡对象
BaseLoadBalancer baseLoadBalancer = (BaseLoadBalancer) getLoadBalancer();
//第三步:获取当前调用的微服务的名称
String invokedSerivceName = baseLoadBalancer.getName();
//第四步:获取nacos clinet的服务注册发现组件的api
NamingService namingService = discoveryProperties.namingServiceInstance();
//第五步:获取所有的服务实例
List<Instance> allInstance = namingService.getAllInstances(invokedSerivceName);
List<Instance> theSameClusterNameInstList = new ArrayList<>();
//第六步:过滤筛选同集群下的所有实例
for (Instance instance : allInstance) {
if (StringUtils.endsWithIgnoreCase(instance.getClusterName(), currentClusterName)) {
theSameClusterNameInstList.add(instance);
}
}
Instance toBeChooseInstance;
//第七步:选择合适的一个实例调用
if (theSameClusterNameInstList.isEmpty()) {
toBeChooseInstance = ArtisanWeightedBalancer.chooseInstanceByRandomWeight(allInstance);
log.info("发生跨集群调用--->当前微服务所在集群:{},被调用微服务所在集群:{},Host:{},Port:{}",
currentClusterName, toBeChooseInstance.getClusterName(), toBeChooseInstance.getIp(), toBeChooseInstance.getPort());
} else {
toBeChooseInstance = ArtisanWeightedBalancer.chooseInstanceByRandomWeight(theSameClusterNameInstList);
log.info("同集群调用--->当前微服务所在集群:{},被调用微服务所在集群:{},Host:{},Port:{}",
currentClusterName, toBeChooseInstance.getClusterName(), toBeChooseInstance.getIp(), toBeChooseInstance.getPort());
}
return new NacosServer(toBeChooseInstance);
} catch (NacosException e) {
log.error("同集群优先权重负载均衡算法选择异常:{}", e);
}
return null;
}
}
随机权重策略
代码语言:javascript复制package com.artisan.customrules;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.client.naming.core.Balancer;
import java.util.List;
/**
* @author 小工匠
* @version 1.0
* @description: 根据权重选择随机选择一个
* @date 2022/2/3 0:28
* @mark: show me the code , change the world
*/
public class ArtisanWeightedBalancer extends Balancer {
public static Instance chooseInstanceByRandomWeight(List<Instance> hosts) {
return getHostByRandomWeight(hosts);
}
}
配置
artisan-cloud-customcfg-ribbon-order 中的 nacos配置
代码语言:javascript复制spring:
cloud:
nacos:
discovery:
server-addr: 1.117.97.88:8848
cluster-name: BeiJingCluster
application:
name: artisan-order-center
artisan-cloud-customcfg-ribbon-product 中的 nacos配置
代码语言:javascript复制spring:
cloud:
nacos:
discovery:
server-addr: 1.117.97.88:8848
cluster-name: GuangDongCluster
application:
name: artisan-product-center
验证
代码语言:javascript复制artisan-cloud-customcfg-ribbon-order ---- cluster-name: BeiJingCluster
artisan-cloud-customcfg-ribbon-product ---- cluster-name: BeiJingCluster
artisan-cloud-customcfg-ribbon-product ---- cluster-name: GuangDongCluster
启动一个artisan-cloud-customcfg-ribbon-order和两个 artisan-cloud-customcfg-ribbon-product 工程后,
通过artisan-cloud-customcfg-ribbon-order 【BeiJingCluster 】
访问 artisan-cloud-customcfg-ribbon-product
查看artisan-cloud-customcfg-ribbon-order
日志
我们下线 artisan-cloud-customcfg-ribbon-order 【BeiJingCluster 】
再次调用 ,观察日志
这样就实现了刚才的需求
源码
https://github.com/yangshangwei/SpringCloudAlibabMaster