Spring Cloud Alibaba - 11 Ribbon 自定义负载均衡策略(同集群优先权重负载均衡算法)

简介: Spring Cloud Alibaba - 11 Ribbon 自定义负载均衡策略(同集群优先权重负载均衡算法)

6735aa4777de402592fbe82e8b40ee3d.png

Pre

Spring Cloud Alibaba - 05 Nacos 领域模型_NameSpac/Group/Cluster

中提到了同一个Namespace下 + 同一个Group下, 不同Cluster 内的服务,可以互相访问.


c83749688c704b76b5f4111e86751ee5.png


如果我们要想实现一个 同集群优先权重负载均衡算法, 怎么办呢?

比如实现如下调用

2e506ec1dbab4d238332248076d9a2eb.png


需求


举个例子: 有两个微服务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

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;
    }
}

随机权重策略

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配置

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配置

spring: 
  cloud:
    nacos:
      discovery:
        server-addr: 1.117.97.88:8848
        cluster-name: GuangDongCluster
  application:
    name: artisan-product-center


验证

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

ecf2b12b8697473f90674f5dc7f6a13a.png


查看artisan-cloud-customcfg-ribbon-order 日志

6e2e47397ed04b368d7dbfaefbe2223d.png

我们下线 artisan-cloud-customcfg-ribbon-order 【BeiJingCluster 】


e66a6080007646cfb62d75b8b31c8c0f.png

再次调用 ,观察日志

a888a48a4cec434fa7de22cffa0ae6b4.png


这样就实现了刚才的需求


源码


https://github.com/yangshangwei/SpringCloudAlibabMaster

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
相关文章
|
人工智能 Java Serverless
【MCP教程系列】搭建基于 Spring AI 的 SSE 模式 MCP 服务并自定义部署至阿里云百炼
本文详细介绍了如何基于Spring AI搭建支持SSE模式的MCP服务,并成功集成至阿里云百炼大模型平台。通过四个步骤实现从零到Agent的构建,包括项目创建、工具开发、服务测试与部署。文章还提供了具体代码示例和操作截图,帮助读者快速上手。最终,将自定义SSE MCP服务集成到百炼平台,完成智能体应用的创建与测试。适合希望了解SSE实时交互及大模型集成的开发者参考。
13431 60
|
4月前
|
监控 安全 Java
使用 @HealthEndpoint 在 Spring Boot 中实现自定义健康检查
Spring Boot 通过 Actuator 模块提供了强大的健康检查功能,帮助开发者快速了解应用程序的运行状态。默认健康检查可检测数据库连接、依赖服务、资源可用性等,但在实际应用中,业务需求和依赖关系各不相同,因此需要实现自定义健康检查来更精确地监控关键组件。本文介绍了如何使用 @HealthEndpoint 注解及实现 HealthIndicator 接口来扩展 Spring Boot 的健康检查功能,从而提升系统的可观测性与稳定性。
369 0
使用 @HealthEndpoint 在 Spring Boot 中实现自定义健康检查
|
10月前
|
JSON Java 数据格式
微服务——SpringBoot使用归纳——Spring Boot中的全局异常处理——拦截自定义异常
本文介绍了在实际项目中如何拦截自定义异常。首先,通过定义异常信息枚举类 `BusinessMsgEnum`,统一管理业务异常的代码和消息。接着,创建自定义业务异常类 `BusinessErrorException`,并在其构造方法中传入枚举类以实现异常信息的封装。最后,利用 `GlobalExceptionHandler` 拦截并处理自定义异常,返回标准的 JSON 响应格式。文章还提供了示例代码和测试方法,展示了全局异常处理在 Spring Boot 项目中的应用价值。
515 0
|
存储 SpringCloudAlibaba Java
【SpringCloud Alibaba系列】一文全面解析Zookeeper安装、常用命令、JavaAPI操作、Watch事件监听、分布式锁、集群搭建、核心理论
一文全面解析Zookeeper安装、常用命令、JavaAPI操作、Watch事件监听、分布式锁、集群搭建、核心理论。
【SpringCloud Alibaba系列】一文全面解析Zookeeper安装、常用命令、JavaAPI操作、Watch事件监听、分布式锁、集群搭建、核心理论
|
XML Java 数据格式
使用idea中的Live Templates自定义自动生成Spring所需的XML配置文件格式
本文介绍了在使用Spring框架时,如何通过创建`applicationContext.xml`配置文件来管理对象。首先,在resources目录下新建XML配置文件,并通过IDEA自动生成部分配置。为完善配置,特别是添加AOP支持,可以通过IDEA的Live Templates功能自定义XML模板。具体步骤包括:连续按两次Shift搜索Live Templates,配置模板内容,输入特定前缀(如spring)并按Tab键即可快速生成完整的Spring配置文件。这样可以大大提高开发效率,减少重复工作。
使用idea中的Live Templates自定义自动生成Spring所需的XML配置文件格式
|
8月前
|
负载均衡 前端开发 应用服务中间件
Tomcat的负载均衡和动静分离(与nginx联动)
总的来说,负载均衡和动静分离是提高Web应用性能的两个重要手段。通过合理的配置和使用,我们可以让Web应用更好地服务于用户。
269 21
|
缓存 负载均衡 算法
解读 Nginx:构建高效反向代理和负载均衡的秘密
解读 Nginx:构建高效反向代理和负载均衡的秘密
319 2
|
负载均衡 前端开发 应用服务中间件
负载均衡指南:Nginx与HAProxy的配置与优化
负载均衡指南:Nginx与HAProxy的配置与优化
783 3
|
负载均衡 算法 应用服务中间件
nginx自定义负载均衡及根据cpu运行自定义负载均衡
nginx自定义负载均衡及根据cpu运行自定义负载均衡
395 1
|
运维 负载均衡 算法
SLB与NGINX的异同是什么
SLB与NGINX的异同是什么
2021 2

热门文章

最新文章