提交 | 用户 | 时间
|
e7c126
|
1 |
package com.iailab.framework.env.core.fegin; |
H |
2 |
|
|
3 |
import cn.hutool.core.collection.CollUtil; |
|
4 |
import cn.hutool.core.util.StrUtil; |
|
5 |
import com.iailab.framework.common.util.collection.CollectionUtils; |
|
6 |
import com.iailab.framework.env.core.context.EnvContextHolder; |
|
7 |
import com.iailab.framework.env.core.util.EnvUtils; |
|
8 |
import com.alibaba.cloud.nacos.balancer.NacosBalancer; |
|
9 |
import lombok.RequiredArgsConstructor; |
|
10 |
import lombok.extern.slf4j.Slf4j; |
|
11 |
import org.springframework.beans.factory.ObjectProvider; |
|
12 |
import org.springframework.cloud.client.ServiceInstance; |
|
13 |
import org.springframework.cloud.client.loadbalancer.DefaultResponse; |
|
14 |
import org.springframework.cloud.client.loadbalancer.EmptyResponse; |
|
15 |
import org.springframework.cloud.client.loadbalancer.Request; |
|
16 |
import org.springframework.cloud.client.loadbalancer.Response; |
|
17 |
import org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancer; |
|
18 |
import org.springframework.cloud.loadbalancer.core.NoopServiceInstanceListSupplier; |
|
19 |
import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer; |
|
20 |
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier; |
|
21 |
import reactor.core.publisher.Mono; |
|
22 |
|
|
23 |
import java.util.List; |
|
24 |
|
|
25 |
/** |
|
26 |
* 多环境的 {@link org.springframework.cloud.client.loadbalancer.LoadBalancerClient} 实现类 |
|
27 |
* 在从服务实例列表选择时,优先选择 tag 匹配的服务实例 |
|
28 |
* |
|
29 |
* @author iailab |
|
30 |
*/ |
|
31 |
@RequiredArgsConstructor |
|
32 |
@Slf4j |
|
33 |
public class EnvLoadBalancerClient implements ReactorServiceInstanceLoadBalancer { |
|
34 |
|
|
35 |
/** |
|
36 |
* 用于获取 serviceId 对应的服务实例的列表 |
|
37 |
*/ |
|
38 |
private final ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider; |
|
39 |
/** |
|
40 |
* 需要获取的服务实例名 |
|
41 |
* |
|
42 |
* 暂时用于打印 logger 日志 |
|
43 |
*/ |
|
44 |
private final String serviceId; |
|
45 |
/** |
|
46 |
* 被代理的 ReactiveLoadBalancer 对象 |
|
47 |
*/ |
|
48 |
private final ReactiveLoadBalancer<ServiceInstance> reactiveLoadBalancer; |
|
49 |
|
|
50 |
@Override |
|
51 |
public Mono<Response<ServiceInstance>> choose(Request request) { |
|
52 |
// 情况一,没有 tag 时,使用默认的 reactiveLoadBalancer 实现负载均衡 |
|
53 |
String tag = EnvContextHolder.getTag(); |
|
54 |
if (StrUtil.isEmpty(tag)) { |
|
55 |
return Mono.from(reactiveLoadBalancer.choose(request)); |
|
56 |
} |
|
57 |
|
|
58 |
// 情况二,有 tag 时,使用 tag 匹配服务实例 |
|
59 |
ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider.getIfAvailable(NoopServiceInstanceListSupplier::new); |
|
60 |
return supplier.get(request).next().map(list -> getInstanceResponse(list, tag)); |
|
61 |
} |
|
62 |
|
|
63 |
private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> instances, String tag) { |
|
64 |
// 如果服务实例为空,则直接返回 |
|
65 |
if (CollUtil.isEmpty(instances)) { |
|
66 |
log.warn("[getInstanceResponse][serviceId({}) 服务实例列表为空]", serviceId); |
|
67 |
return new EmptyResponse(); |
|
68 |
} |
|
69 |
|
|
70 |
// 筛选满足条件的实例列表 |
|
71 |
List<ServiceInstance> chooseInstances = CollectionUtils.filterList(instances, instance -> tag.equals(EnvUtils.getTag(instance))); |
|
72 |
if (CollUtil.isEmpty(chooseInstances)) { |
|
73 |
log.warn("[getInstanceResponse][serviceId({}) 没有满足 tag({}) 的服务实例列表,直接使用所有服务实例列表]", serviceId, tag); |
|
74 |
chooseInstances = instances; |
|
75 |
} |
|
76 |
|
|
77 |
// TODO iailab:https://juejin.cn/post/7056770721858469896 想通网段 |
|
78 |
|
|
79 |
// 随机 + 权重获取实例列表 TODO iailab:目前直接使用 Nacos 提供的方法,如果替换注册中心,需要重新失败该方法 |
|
80 |
return new DefaultResponse(NacosBalancer.getHostByRandomWeight3(chooseInstances)); |
|
81 |
} |
|
82 |
|
|
83 |
} |