完善 gateway 服务,支持 tag 过滤服务实例
parent
b8fb106aaf
commit
97b931f782
1
pom.xml
1
pom.xml
|
@ -16,7 +16,6 @@
|
|||
<!-- <module>yudao-module-bpm</module>-->
|
||||
<module>yudao-module-system</module>
|
||||
<module>yudao-module-infra</module>
|
||||
<module>yudao-spring-boot-starter-env</module>
|
||||
<!-- <module>yudao-module-pay</module>-->
|
||||
</modules>
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
<packaging>pom</packaging>
|
||||
<modules>
|
||||
<module>yudao-common</module>
|
||||
<module>yudao-spring-boot-starter-env</module>
|
||||
<module>yudao-spring-boot-starter-banner</module>
|
||||
<module>yudao-spring-boot-starter-mybatis</module>
|
||||
<module>yudao-spring-boot-starter-redis</module>
|
||||
|
|
|
@ -3,6 +3,7 @@ package cn.iocoder.yudao.gateway.filter.grey;
|
|||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.gateway.util.EnvUtils;
|
||||
import com.alibaba.cloud.nacos.balancer.NacosBalancer;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
@ -62,7 +63,7 @@ public class GrayLoadBalancer implements ReactorServiceInstanceLoadBalancer {
|
|||
return new EmptyResponse();
|
||||
}
|
||||
|
||||
// 筛选满足条件的实例列表
|
||||
// 筛选满足 version 条件的实例列表
|
||||
String version = headers.getFirst(VERSION);
|
||||
List<ServiceInstance> chooseInstances;
|
||||
if (StrUtil.isEmpty(version)) {
|
||||
|
@ -70,12 +71,41 @@ public class GrayLoadBalancer implements ReactorServiceInstanceLoadBalancer {
|
|||
} else {
|
||||
chooseInstances = CollectionUtils.filterList(instances, instance -> version.equals(instance.getMetadata().get("version")));
|
||||
if (CollUtil.isEmpty(chooseInstances)) {
|
||||
log.warn("[getInstanceResponse][serviceId({}) 没有满足版本的服务实例列表,直接使用所有服务实例列表]", serviceId);
|
||||
log.warn("[getInstanceResponse][serviceId({}) 没有满足版本({})的服务实例列表,直接使用所有服务实例列表]", serviceId, version);
|
||||
chooseInstances = instances;
|
||||
}
|
||||
}
|
||||
|
||||
// 基于 tag 过滤实例列表
|
||||
chooseInstances = filterTagServiceInstances(chooseInstances, headers);
|
||||
|
||||
// 随机 + 权重获取实例列表 TODO 芋艿:目前直接使用 Nacos 提供的方法,如果替换注册中心,需要重新失败该方法
|
||||
return new DefaultResponse(NacosBalancer.getHostByRandomWeight3(chooseInstances));
|
||||
}
|
||||
|
||||
/**
|
||||
* 基于 tag 请求头,过滤匹配 tag 的服务实例列表
|
||||
*
|
||||
* copy from EnvLoadBalancerClient
|
||||
*
|
||||
* @param instances 服务实例列表
|
||||
* @param headers 请求头
|
||||
* @return 服务实例列表
|
||||
*/
|
||||
private List<ServiceInstance> filterTagServiceInstances(List<ServiceInstance> instances, HttpHeaders headers) {
|
||||
// 情况一,没有 tag 时,直接返回
|
||||
String tag = EnvUtils.getTag(headers);
|
||||
if (StrUtil.isEmpty(tag)) {
|
||||
return instances;
|
||||
}
|
||||
|
||||
// 情况二,有 tag 时,使用 tag 匹配服务实例
|
||||
List<ServiceInstance> chooseInstances = CollectionUtils.filterList(instances, instance -> tag.equals(EnvUtils.getTag(instance)));
|
||||
if (CollUtil.isEmpty(chooseInstances)) {
|
||||
log.warn("[filterTagServiceInstances][serviceId({}) 没有满足 tag({}) 的服务实例列表,直接使用所有服务实例列表]", serviceId, tag);
|
||||
chooseInstances = instances;
|
||||
}
|
||||
return chooseInstances;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
package cn.iocoder.yudao.gateway.util;
|
||||
|
||||
import cn.hutool.core.net.NetUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 环境 Utils
|
||||
*
|
||||
* copy from yudao-spring-boot-starter-env 的 EnvUtils 类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public class EnvUtils {
|
||||
|
||||
private static final String HEADER_TAG = "tag";
|
||||
|
||||
public static final String HOST_NAME_VALUE = "${HOSTNAME}";
|
||||
|
||||
public static String getTag(HttpHeaders headers) {
|
||||
String tag = headers.getFirst(HEADER_TAG);
|
||||
// 如果请求的是 "${HOSTNAME}",则解析成对应的本地主机名
|
||||
// 目的:特殊逻辑,解决 IDEA Rest Client 不支持环境变量的读取,所以就服务器来做
|
||||
return Objects.equals(tag, HOST_NAME_VALUE) ? getHostName() : tag;
|
||||
}
|
||||
|
||||
public static String getTag(ServiceInstance instance) {
|
||||
return instance.getMetadata().get(HEADER_TAG);
|
||||
}
|
||||
|
||||
public static String getHostName() {
|
||||
return StrUtil.blankToDefault(NetUtil.getLocalHostName(), IdUtil.fastSimpleUUID());
|
||||
}
|
||||
|
||||
}
|
|
@ -26,9 +26,10 @@ import reactor.core.publisher.Mono;
|
|||
@Slf4j
|
||||
public class WebFrameworkUtils {
|
||||
|
||||
@SuppressWarnings("UastIncorrectHttpHeaderInspection")
|
||||
private static final String HEADER_TENANT_ID = "tenant-id";
|
||||
|
||||
private static final String HEADER_TAG = "tag";
|
||||
|
||||
private WebFrameworkUtils() {}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue