From e9bfa1396ff47d171b3052a606e0931e6f93cc9c Mon Sep 17 00:00:00 2001
From: houzhongjian <houzhongyi@126.com>
Date: 星期四, 10 四月 2025 12:05:23 +0800
Subject: [PATCH] 还原framework代码

---
 iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/core/fegin/EnvLoadBalancerClient.java |   83 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 83 insertions(+), 0 deletions(-)

diff --git a/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/core/fegin/EnvLoadBalancerClient.java b/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/core/fegin/EnvLoadBalancerClient.java
new file mode 100644
index 0000000..fb43806
--- /dev/null
+++ b/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/core/fegin/EnvLoadBalancerClient.java
@@ -0,0 +1,83 @@
+package com.iailab.framework.env.core.fegin;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
+import com.iailab.framework.common.util.collection.CollectionUtils;
+import com.iailab.framework.env.core.context.EnvContextHolder;
+import com.iailab.framework.env.core.util.EnvUtils;
+import com.alibaba.cloud.nacos.balancer.NacosBalancer;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.cloud.client.ServiceInstance;
+import org.springframework.cloud.client.loadbalancer.DefaultResponse;
+import org.springframework.cloud.client.loadbalancer.EmptyResponse;
+import org.springframework.cloud.client.loadbalancer.Request;
+import org.springframework.cloud.client.loadbalancer.Response;
+import org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancer;
+import org.springframework.cloud.loadbalancer.core.NoopServiceInstanceListSupplier;
+import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer;
+import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
+import reactor.core.publisher.Mono;
+
+import java.util.List;
+
+/**
+ * 多环境的 {@link org.springframework.cloud.client.loadbalancer.LoadBalancerClient} 实现类
+ * 在从服务实例列表选择时,优先选择 tag 匹配的服务实例
+ *
+ * @author iailab
+ */
+@RequiredArgsConstructor
+@Slf4j
+public class EnvLoadBalancerClient implements ReactorServiceInstanceLoadBalancer {
+
+    /**
+     * 用于获取 serviceId 对应的服务实例的列表
+     */
+    private final ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;
+    /**
+     * 需要获取的服务实例名
+     *
+     * 暂时用于打印 logger 日志
+     */
+    private final String serviceId;
+    /**
+     * 被代理的 ReactiveLoadBalancer 对象
+     */
+    private final ReactiveLoadBalancer<ServiceInstance> reactiveLoadBalancer;
+
+    @Override
+    public Mono<Response<ServiceInstance>> 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));
+    }
+
+    private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> instances, String tag) {
+        // 如果服务实例为空,则直接返回
+        if (CollUtil.isEmpty(instances)) {
+            log.warn("[getInstanceResponse][serviceId({}) 服务实例列表为空]", serviceId);
+            return new EmptyResponse();
+        }
+
+        // 筛选满足条件的实例列表
+        List<ServiceInstance> chooseInstances = CollectionUtils.filterList(instances, instance -> tag.equals(EnvUtils.getTag(instance)));
+        if (CollUtil.isEmpty(chooseInstances)) {
+            log.warn("[getInstanceResponse][serviceId({}) 没有满足 tag({}) 的服务实例列表,直接使用所有服务实例列表]", serviceId, tag);
+            chooseInstances = instances;
+        }
+
+        // TODO iailab:https://juejin.cn/post/7056770721858469896 想通网段
+
+        // 随机 + 权重获取实例列表 TODO iailab:目前直接使用 Nacos 提供的方法,如果替换注册中心,需要重新失败该方法
+        return new DefaultResponse(NacosBalancer.getHostByRandomWeight3(chooseInstances));
+    }
+
+}

--
Gitblit v1.9.3