From 41d85abf23c123e948b1a585c413f5a0a29a504f Mon Sep 17 00:00:00 2001
From: bluejay <253316343@qq.com>
Date: 星期二, 08 四月 2025 09:05:49 +0800
Subject: [PATCH] gateway 根据matedate转发到本地服务
---
aps-gateway/src/main/java/com/aps/gateway/config/loadBalancer/GrayLoadBalancer.java | 10 +++
aps-gateway/src/main/java/com/aps/gateway/config/loadBalancer/GrayReactiveLoadBalancerClientFilter.java | 99 +++++++++++++++++++++++++++++++++
aps-gateway/src/main/java/com/aps/gateway/config/loadBalancer/VersionGrayLoadBalancer.java | 60 ++++++++++++++++++++
aps-gateway/pom.xml | 11 +++
4 files changed, 179 insertions(+), 1 deletions(-)
diff --git a/aps-gateway/pom.xml b/aps-gateway/pom.xml
index d5b6905..4e0cb1f 100644
--- a/aps-gateway/pom.xml
+++ b/aps-gateway/pom.xml
@@ -82,7 +82,16 @@
<artifactId>springdoc-openapi-starter-webflux-ui</artifactId>
<version>${springdoc.version}</version>
</dependency>
-
+ <dependency>
+ <groupId>org.projectlombok</groupId>
+ <artifactId>lombok</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>cn.hutool</groupId>
+ <artifactId>hutool-all</artifactId>
+ <version>5.8.37</version>
+ </dependency>
</dependencies>
<build>
diff --git a/aps-gateway/src/main/java/com/aps/gateway/config/loadBalancer/GrayLoadBalancer.java b/aps-gateway/src/main/java/com/aps/gateway/config/loadBalancer/GrayLoadBalancer.java
new file mode 100644
index 0000000..1bf7457
--- /dev/null
+++ b/aps-gateway/src/main/java/com/aps/gateway/config/loadBalancer/GrayLoadBalancer.java
@@ -0,0 +1,10 @@
+package com.aps.gateway.config.loadBalancer;
+
+import org.springframework.cloud.client.ServiceInstance;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+
+
+public interface GrayLoadBalancer {
+
+ ServiceInstance choose(String serviceId, ServerHttpRequest request);
+}
diff --git a/aps-gateway/src/main/java/com/aps/gateway/config/loadBalancer/GrayReactiveLoadBalancerClientFilter.java b/aps-gateway/src/main/java/com/aps/gateway/config/loadBalancer/GrayReactiveLoadBalancerClientFilter.java
new file mode 100644
index 0000000..fb73979
--- /dev/null
+++ b/aps-gateway/src/main/java/com/aps/gateway/config/loadBalancer/GrayReactiveLoadBalancerClientFilter.java
@@ -0,0 +1,99 @@
+package com.aps.gateway.config.loadBalancer;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.util.Asserts;
+import org.springframework.cloud.client.ServiceInstance;
+import org.springframework.cloud.client.loadbalancer.DefaultResponse;
+import org.springframework.cloud.client.loadbalancer.LoadBalancerUriTools;
+import org.springframework.cloud.client.loadbalancer.Response;
+import org.springframework.cloud.gateway.config.GatewayLoadBalancerProperties;
+import org.springframework.cloud.gateway.filter.GatewayFilterChain;
+import org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter;
+import org.springframework.cloud.gateway.support.DelegatingServiceInstance;
+import org.springframework.cloud.gateway.support.NotFoundException;
+import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
+import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Mono;
+
+import java.net.URI;
+
+
+@Slf4j
+@Component
+public class GrayReactiveLoadBalancerClientFilter extends ReactiveLoadBalancerClientFilter {
+
+ private final static String SCHEME = "lb";
+
+ private static final int LOAD_BALANCER_CLIENT_FILTER_ORDER = 10150;
+ private final GrayLoadBalancer grayLoadBalancer;
+ private final GatewayLoadBalancerProperties loadBalancerProperties;
+
+ public GrayReactiveLoadBalancerClientFilter(LoadBalancerClientFactory clientFactory, GatewayLoadBalancerProperties loadBalancerProperties, GrayLoadBalancer grayLoadBalancer) {
+ super(clientFactory, loadBalancerProperties);
+ this.loadBalancerProperties = loadBalancerProperties;
+ this.grayLoadBalancer = grayLoadBalancer;
+ }
+
+ @Override
+ public int getOrder() {
+ return LOAD_BALANCER_CLIENT_FILTER_ORDER;
+ }
+
+ @Override
+ public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+ URI url = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR);
+ String schemePrefix = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR);
+
+ // 鐩存帴鏀捐
+ if (url == null || (!SCHEME.equals(url.getScheme()) && !SCHEME.equals(schemePrefix))) {
+ return chain.filter(exchange);
+ }
+ // 淇濈暀鍘熷url
+ ServerWebExchangeUtils.addOriginalRequestUrl(exchange, url);
+
+ if (log.isTraceEnabled()) {
+ log.trace(ReactiveLoadBalancerClientFilter.class.getSimpleName() + " url before: " + url);
+ }
+
+ return choose(exchange).doOnNext(response -> {
+
+ if (!response.hasServer()) {
+ throw NotFoundException.create(loadBalancerProperties.isUse404(),
+ "Unable to find instance for " + url.getHost());
+ }
+
+ URI uri = exchange.getRequest().getURI();
+
+ // if the `lb:<scheme>` mechanism was used, use `<scheme>` as the default,
+ // if the loadbalancer doesn't provide one.
+ String overrideScheme = null;
+ if (schemePrefix != null) {
+ overrideScheme = url.getScheme();
+ }
+
+ DelegatingServiceInstance serviceInstance = new DelegatingServiceInstance(response.getServer(),
+ overrideScheme);
+
+ URI requestUrl = LoadBalancerUriTools.reconstructURI(serviceInstance, uri);
+
+ if (log.isTraceEnabled()) {
+ log.trace("LoadBalancerClientFilter url chosen: " + requestUrl);
+ }
+ exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR, requestUrl);
+ }).then(chain.filter(exchange));
+ }
+
+ /**
+ * 鑾峰彇瀹炰緥
+ * @param exchange ServerWebExchange
+ * @return ServiceInstance
+ */
+ private Mono<Response<ServiceInstance>> choose(ServerWebExchange exchange) {
+ URI uri = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR);
+ Asserts.notNull(uri, "uri");
+ ServiceInstance serviceInstance = grayLoadBalancer.choose(uri.getHost(), exchange.getRequest());
+ return Mono.just(new DefaultResponse(serviceInstance));
+ }
+}
\ No newline at end of file
diff --git a/aps-gateway/src/main/java/com/aps/gateway/config/loadBalancer/VersionGrayLoadBalancer.java b/aps-gateway/src/main/java/com/aps/gateway/config/loadBalancer/VersionGrayLoadBalancer.java
new file mode 100644
index 0000000..8946d45
--- /dev/null
+++ b/aps-gateway/src/main/java/com/aps/gateway/config/loadBalancer/VersionGrayLoadBalancer.java
@@ -0,0 +1,60 @@
+package com.aps.gateway.config.loadBalancer;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.map.MapUtil;
+import cn.hutool.core.util.RandomUtil;
+import cn.hutool.core.util.StrUtil;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.logging.log4j.util.Strings;
+import org.springframework.cloud.client.ServiceInstance;
+import org.springframework.cloud.client.discovery.DiscoveryClient;
+import org.springframework.cloud.gateway.support.NotFoundException;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Slf4j
+@RequiredArgsConstructor
+@Component
+public class VersionGrayLoadBalancer implements GrayLoadBalancer {
+
+ private final DiscoveryClient discoveryClient;
+ private final static String VERSION = "version";
+ /**
+ * 鏍规嵁serviceId 绛涢�夊彲鐢ㄦ湇鍔�
+ * @param serviceId 鏈嶅姟ID
+ * @param request 褰撳墠璇锋眰
+ * @return ServiceInstance
+ */
+ @Override
+ public ServiceInstance choose(String serviceId, ServerHttpRequest request) {
+ List<ServiceInstance> instances = discoveryClient.getInstances(serviceId);
+
+ // 娉ㄥ唽涓績鏃犲疄渚� 鎶涘嚭寮傚父
+ if (instances.isEmpty()) {
+ log.warn("No instance available for {}", serviceId);
+ throw new NotFoundException("No instance available for " + serviceId);
+ }
+
+ // 鑾峰彇璇锋眰version锛屾棤鍒欓殢鏈鸿繑鍥炲彲鐢ㄥ疄渚�
+ String reqVersion = request.getHeaders().getFirst(VERSION);
+ if (Strings.isBlank(reqVersion)) {
+ return instances.get(RandomUtil.randomInt(instances.size()));
+ }
+
+ // 閬嶅巻鍙互瀹炰緥鍏冩暟鎹紝鑻ュ尮閰嶅垯杩斿洖姝ゅ疄渚�
+ List<ServiceInstance> availableList = instances.stream()
+ .filter(instance -> reqVersion
+ .equalsIgnoreCase(MapUtil.getStr(instance.getMetadata(), VERSION)))
+ .collect(Collectors.toList());
+
+ if (CollUtil.isEmpty(availableList)) {
+ return instances.get(RandomUtil.randomInt(instances.size()));
+ }
+ return availableList.get(RandomUtil.randomInt(availableList.size()));
+
+ }
+}
+
--
Gitblit v1.9.3