From 031fa11e388838e4482a643a48a1b16c78764a88 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 15 Jul 2025 13:04:09 +0800 Subject: [PATCH] =?UTF-8?q?reactor=EF=BC=9A=E3=80=90Cloud=20=E5=BE=AE?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E3=80=91tag=20=E8=B7=AF=E7=94=B1=E6=97=B6?= =?UTF-8?q?=EF=BC=8C=E8=AF=B7=E6=B1=82=E6=97=A0=20tag=20=E6=97=B6=E4=BC=98?= =?UTF-8?q?=E5=85=88=E5=8C=B9=E9=85=8D=E6=97=A0=20tag=20=E5=AE=9E=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../env/core/fegin/EnvLoadBalancerClient.java | 42 +++++++++++++++---- .../gateway/filter/grey/GrayLoadBalancer.java | 10 ++++- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-env/src/main/java/cn/iocoder/yudao/framework/env/core/fegin/EnvLoadBalancerClient.java b/yudao-framework/yudao-spring-boot-starter-env/src/main/java/cn/iocoder/yudao/framework/env/core/fegin/EnvLoadBalancerClient.java index ac136e6ba..79339b25c 100644 --- a/yudao-framework/yudao-spring-boot-starter-env/src/main/java/cn/iocoder/yudao/framework/env/core/fegin/EnvLoadBalancerClient.java +++ b/yudao-framework/yudao-spring-boot-starter-env/src/main/java/cn/iocoder/yudao/framework/env/core/fegin/EnvLoadBalancerClient.java @@ -49,15 +49,17 @@ public class EnvLoadBalancerClient implements ReactorServiceInstanceLoadBalancer @Override public Mono> choose(Request request) { - // 情况一,没有 tag 时,使用默认的 reactiveLoadBalancer 实现负载均衡 - String tag = EnvContextHolder.getTag(); - if (StrUtil.isEmpty(tag)) { - return Mono.from(reactiveLoadBalancer.choose(request)); - } - - // 情况二,有 tag 时,使用 tag 匹配服务实例 ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider.getIfAvailable(NoopServiceInstanceListSupplier::new); - return supplier.get(request).next().map(list -> getInstanceResponse(list, tag)); + return supplier.get(request).next().map(list -> { + // 情况一,没有 tag 时,过滤掉有 tag 的节点。目的:避免 test 环境,打到本地有 tag 的实例 + String tag = EnvContextHolder.getTag(); + if (StrUtil.isEmpty(tag)) { + return getInstanceResponseWithoutTag(list); + } + + // 情况二,有 tag 时,使用 tag 匹配服务实例 + return getInstanceResponse(list, tag); + }); } private Response getInstanceResponse(List instances, String tag) { @@ -74,10 +76,32 @@ public class EnvLoadBalancerClient implements ReactorServiceInstanceLoadBalancer chooseInstances = instances; } - // TODO 芋艿:https://juejin.cn/post/7056770721858469896 想通网段 + // TODO 芋艿:https://juejin.cn/post/7056770721858469896 相同网段 // 随机 + 权重获取实例列表 TODO 芋艿:目前直接使用 Nacos 提供的方法,如果替换注册中心,需要重新失败该方法 return new DefaultResponse(NacosBalancer.getHostByRandomWeight3(chooseInstances)); } + /** + * 当没有 tag 时,过滤掉有 tag 的实例列表 + */ + private Response getInstanceResponseWithoutTag(List instances) { + // 如果服务实例为空,则直接返回 + if (CollUtil.isEmpty(instances)) { + log.warn("[getInstanceResponseWithoutTag][serviceId({}) 服务实例列表为空]", serviceId); + return new EmptyResponse(); + } + + // 筛选没有 tag 的实例列表 + List chooseInstances = CollectionUtils.filterList(instances, instance -> StrUtil.isEmpty(EnvUtils.getTag(instance))); + // 【重要】补充说明:如果希望在 chooseInstances 为空时,不允许打到有 tag 的实例,可以取消注释下面的代码 + if (CollUtil.isEmpty(chooseInstances)) { + log.warn("[getInstanceResponseWithoutTag][serviceId({}) 没有不带 tag 的服务实例列表,直接使用所有服务实例列表]", serviceId); + chooseInstances = instances; + } + + // 随机 + 权重获取实例列表 + return new DefaultResponse(NacosBalancer.getHostByRandomWeight3(chooseInstances)); + } + } diff --git a/yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/filter/grey/GrayLoadBalancer.java b/yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/filter/grey/GrayLoadBalancer.java index 452e5fdb0..2637a8f7d 100644 --- a/yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/filter/grey/GrayLoadBalancer.java +++ b/yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/filter/grey/GrayLoadBalancer.java @@ -93,10 +93,16 @@ public class GrayLoadBalancer implements ReactorServiceInstanceLoadBalancer { * @return 服务实例列表 */ private List filterTagServiceInstances(List instances, HttpHeaders headers) { - // 情况一,没有 tag 时,直接返回 + // 情况一,没有 tag 时,过滤掉有 tag 的节点。目的:避免 test 环境,打到本地有 tag 的实例 String tag = EnvUtils.getTag(headers); if (StrUtil.isEmpty(tag)) { - return instances; + List chooseInstances = CollectionUtils.filterList(instances, instance -> StrUtil.isEmpty(EnvUtils.getTag(instance))); + // 【重要】补充说明:如果希望在 chooseInstances 为空时,不允许打到有 tag 的实例,可以取消注释下面的代码 + if (CollUtil.isEmpty(chooseInstances)) { + log.warn("[filterTagServiceInstances][serviceId({}) 没有不带 tag 的服务实例列表,直接使用所有服务实例列表]", serviceId); + chooseInstances = instances; + } + return chooseInstances; } // 情况二,有 tag 时,使用 tag 匹配服务实例