springCloudGateway+nacos自定义负载均衡-通过IP隔离开发环境

先说一下想法,小公司开发项目,参考若依框架使用的spring-cloud-starter-gatewayspring-cloud-starter-alibaba-nacos, 用到了nacos的配置中心和注册中心,有多个模块(每个模块都是一个服务)。
想本地开发,且和其他同事不互相影响的情况下,有同事建议 本地部署 完整的环境(nacos、需要的模块、前端等),除了 数据库和redis共用。这种方案也能用,就是占用自己电脑资源太多了(ps 自己电脑摸鱼的硬件资源就少了)。
我通过看nacos相关的教程,发现可以通过 配置中心 和 注册中心 的namespace命名不同进行隔离,这样可以不用部署nacos服务。
继续分析发现,网关模块 默认的 负载均衡 ReactorServiceInstanceLoadBalancer 的实现 RoundRobinLoadBalancer 是通过轮询 访问服务的,可以 改造 负载均衡 来实现 本地开发环境最小化(只允许开发的服务模块),其他服务用 测试环境提供。
当前改造只适用请求通过网关,如果模块服务之间 直连调用,就需要在每个模块增加类似处理。暂不考虑

(ps 本人小白一枚springCloudGateway使用的少)本文章限定在这个项目里面,如果自己项目环境不一样,不保证能拿来直接用。

实现截图-不想看原理的先食用结果

在这里插入图片描述
在这里插入图片描述

参考

本来想通过搜索和AI找到解决方案,结果代码抄下来每一个能实现的。要么没有引用的类,要么无法实现自己的想法。所以就不贴了。
每个项目的依赖和版本情况都不一样,最好的方法是 找到框架的核心实现类,在跟踪调试和找到引用与初始化的地方。想办法自定义实现注入-这种方式最好,毕竟都是框架给留的口子。实在不行,就只能通过魔改或劫持的方式实现了。

原理图-设想

改造前请求流程

在这里插入图片描述
这种情况,适用于 非开发环境,简单高效

改造后请求流程

在这里插入图片描述
改造后的,适用于 本地开发,通过网关只请求自己的服务,或者自己没有只请求测试环境(简单的测试环境所有服务一台机器上)。尽最大可能不影响 其他同事开发。
图中没有画 锁定请求服务IP的情况(这块代码没测试)。

项目框架主要依赖

参考时候请注意 依赖包版本是否差距过大

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
    <version>3.1.4</version>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    <version>2021.0.4.0</version>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    <version>2021.0.4.0</version>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    <version>2021.0.4.0</version>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
    <version>2021.0.4.0</version>
</dependency>
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
    <version>1.8.5</version>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-loadbalancer</artifactId>
    <version>3.1.5</version>
</dependency>

自定义实现

自定义负载均衡类

根据 org.springframework.cloud.loadbalancer.core.RoundRobinLoadBalancer 轮询策略 改造,这块代码倒还好实现。TestLocalLockIpLoadBalancer直接注入spring中,ObjectProvider<ServiceInstanceListSupplier> 获取不到服务列表,看了spring实现,要完全替换需要注入好几个类,有点麻烦。最后改成运行时替换。

自定义路由负载均衡,负载均衡策略:

  • 先根据请求IP查询IP相同的服务
  • 再找和网关IP相同的服务
  • 最后轮询其他IP服务
package *.*.*.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.*;
import org.springframework.cloud.loadbalancer.core.NoopServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer;
import org.springframework.cloud.loadbalancer.core.SelectedInstanceCallback;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.http.HttpHeaders;
import reactor.core.publisher.Mono;

import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 自定义路由负载均衡->初始化,负载均衡策略: 先找请求IP查询IP相同的服务、再找和网关IP相同的服务、最后轮询其他IP服务
 *
 * @see  org.springframework.cloud.loadbalancer.core.RoundRobinLoadBalancer
 * @author z
 * @date 2025/1/10
 */
public class TestLocalLockIpLoadBalancer implements ReactorServiceInstanceLoadBalancer {
   
   
    private static final Logger log = LoggerFactory.getLogger(TestLocalLockIpLoadBalancer.class);
    final AtomicInteger position;
    final String serviceId;
    ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;
    private String localIp;
    public TestLocalLockIpLoadBalancer setLocalIp(String localIp) {
   
    this.localIp = localIp; return this; }

    public TestLocalLockIpLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> provide, String serviceId) {
   
   
        this(provide, serviceId, new Random().nextInt(1000));
    }
    public TestLocalLockIpLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> provide, String serviceId
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值