From 8ea61f7f5c5839a9fd0e0ea3820c4ad0cc0609a1 Mon Sep 17 00:00:00 2001 From: hexiaofeng Date: Mon, 21 Oct 2024 10:12:46 +0800 Subject: [PATCH] Fix the issue where Spring Cloud Gateway gets a null response content when trying to judge the circuit breaker --- .../v3/cluster/GatewayCluster.java | 13 ++++++------- .../v3/response/GatewayClusterResponse.java | 15 +++++++++++++++ .../v4/cluster/GatewayCluster.java | 9 ++++----- .../v4/response/GatewayClusterResponse.java | 18 +++++++++++++++++- 4 files changed, 42 insertions(+), 13 deletions(-) diff --git a/joylive-plugin/joylive-router/joylive-router-springgateway3/src/main/java/com/jd/live/agent/plugin/router/springgateway/v3/cluster/GatewayCluster.java b/joylive-plugin/joylive-router/joylive-router-springgateway3/src/main/java/com/jd/live/agent/plugin/router/springgateway/v3/cluster/GatewayCluster.java index c30bbb0e..5adebb1d 100644 --- a/joylive-plugin/joylive-router/joylive-router-springgateway3/src/main/java/com/jd/live/agent/plugin/router/springgateway/v3/cluster/GatewayCluster.java +++ b/joylive-plugin/joylive-router/joylive-router-springgateway3/src/main/java/com/jd/live/agent/plugin/router/springgateway/v3/cluster/GatewayCluster.java @@ -16,14 +16,14 @@ package com.jd.live.agent.plugin.router.springgateway.v3.cluster; import com.jd.live.agent.core.util.Futures; +import com.jd.live.agent.governance.exception.ErrorPredicate; +import com.jd.live.agent.governance.exception.ServiceError; import com.jd.live.agent.governance.invoke.cluster.ClusterInvoker; import com.jd.live.agent.governance.policy.service.circuitbreak.DegradeConfig; import com.jd.live.agent.governance.policy.service.cluster.ClusterPolicy; import com.jd.live.agent.governance.policy.service.cluster.RetryPolicy; import com.jd.live.agent.governance.policy.service.exception.CodePolicy; import com.jd.live.agent.governance.request.Request; -import com.jd.live.agent.governance.exception.ErrorPredicate; -import com.jd.live.agent.governance.exception.ServiceError; import com.jd.live.agent.plugin.router.springcloud.v3.cluster.AbstractClientCluster; import com.jd.live.agent.plugin.router.springcloud.v3.instance.SpringEndpoint; import com.jd.live.agent.plugin.router.springgateway.v3.request.GatewayClusterRequest; @@ -110,11 +110,10 @@ protected boolean isRetryable() { public CompletionStage invoke(GatewayClusterRequest request, SpringEndpoint endpoint) { try { Set codePolicies = request.getAttribute(Request.KEY_CODE_POLICY); - ServerWebExchange exchange = request.getExchange(); - if (codePolicies != null && !codePolicies.isEmpty()) { - exchange = exchange.mutate().response(new BodyResponseDecorator(exchange, codePolicies)).build(); - } - GatewayClusterResponse response = new GatewayClusterResponse(exchange.getResponse()); + ServerWebExchange exchange = codePolicies != null && !codePolicies.isEmpty() + ? request.getExchange().mutate().response(new BodyResponseDecorator(request.getExchange(), codePolicies)).build() + : request.getExchange(); + GatewayClusterResponse response = new GatewayClusterResponse(exchange.getResponse(), () -> (String) exchange.getAttributes().get(Request.KEY_RESPONSE_BODY)); return request.getChain().filter(exchange).toFuture().thenApply(v -> response); } catch (Throwable e) { return Futures.future(e); diff --git a/joylive-plugin/joylive-router/joylive-router-springgateway3/src/main/java/com/jd/live/agent/plugin/router/springgateway/v3/response/GatewayClusterResponse.java b/joylive-plugin/joylive-router/joylive-router-springgateway3/src/main/java/com/jd/live/agent/plugin/router/springgateway/v3/response/GatewayClusterResponse.java index c063d2f6..5110c87d 100644 --- a/joylive-plugin/joylive-router/joylive-router-springgateway3/src/main/java/com/jd/live/agent/plugin/router/springgateway/v3/response/GatewayClusterResponse.java +++ b/joylive-plugin/joylive-router/joylive-router-springgateway3/src/main/java/com/jd/live/agent/plugin/router/springgateway/v3/response/GatewayClusterResponse.java @@ -15,11 +15,14 @@ */ package com.jd.live.agent.plugin.router.springgateway.v3.response; +import com.jd.live.agent.core.util.cache.LazyObject; import com.jd.live.agent.governance.exception.ErrorPredicate; import com.jd.live.agent.governance.exception.ServiceError; import com.jd.live.agent.governance.response.AbstractHttpResponse.AbstractHttpOutboundResponse; import org.springframework.http.server.reactive.ServerHttpResponse; +import java.util.function.Supplier; + /** * GatewayClusterResponse * @@ -27,12 +30,20 @@ */ public class GatewayClusterResponse extends AbstractHttpOutboundResponse { + private final LazyObject body; + public GatewayClusterResponse(ServerHttpResponse response) { + this(response, null); + } + + public GatewayClusterResponse(ServerHttpResponse response, Supplier supplier) { super(response); + this.body = new LazyObject<>(supplier); } public GatewayClusterResponse(ServiceError error, ErrorPredicate predicate) { super(error, predicate); + this.body = null; } @Override @@ -41,4 +52,8 @@ public String getCode() { return code == null ? null : code.toString(); } + @Override + public Object getResult() { + return body == null ? null : body.get(); + } } diff --git a/joylive-plugin/joylive-router/joylive-router-springgateway4/src/main/java/com/jd/live/agent/plugin/router/springgateway/v4/cluster/GatewayCluster.java b/joylive-plugin/joylive-router/joylive-router-springgateway4/src/main/java/com/jd/live/agent/plugin/router/springgateway/v4/cluster/GatewayCluster.java index a880043f..6f078ccb 100644 --- a/joylive-plugin/joylive-router/joylive-router-springgateway4/src/main/java/com/jd/live/agent/plugin/router/springgateway/v4/cluster/GatewayCluster.java +++ b/joylive-plugin/joylive-router/joylive-router-springgateway4/src/main/java/com/jd/live/agent/plugin/router/springgateway/v4/cluster/GatewayCluster.java @@ -113,11 +113,10 @@ protected boolean isRetryable() { public CompletionStage invoke(GatewayClusterRequest request, SpringEndpoint endpoint) { try { Set codePolicies = request.getAttribute(Request.KEY_CODE_POLICY); - ServerWebExchange exchange = request.getExchange(); - if (codePolicies != null && !codePolicies.isEmpty()) { - exchange = exchange.mutate().response(new BodyResponseDecorator(exchange, codePolicies)).build(); - } - GatewayClusterResponse response = new GatewayClusterResponse(exchange.getResponse()); + ServerWebExchange exchange = codePolicies != null && !codePolicies.isEmpty() + ? request.getExchange().mutate().response(new BodyResponseDecorator(request.getExchange(), codePolicies)).build() + : request.getExchange(); + GatewayClusterResponse response = new GatewayClusterResponse(exchange.getResponse(), () -> (String) exchange.getAttributes().get(Request.KEY_RESPONSE_BODY)); return request.getChain().filter(exchange).toFuture().thenApply(v -> response); } catch (Throwable e) { return Futures.future(e); diff --git a/joylive-plugin/joylive-router/joylive-router-springgateway4/src/main/java/com/jd/live/agent/plugin/router/springgateway/v4/response/GatewayClusterResponse.java b/joylive-plugin/joylive-router/joylive-router-springgateway4/src/main/java/com/jd/live/agent/plugin/router/springgateway/v4/response/GatewayClusterResponse.java index 9664b549..555664bf 100644 --- a/joylive-plugin/joylive-router/joylive-router-springgateway4/src/main/java/com/jd/live/agent/plugin/router/springgateway/v4/response/GatewayClusterResponse.java +++ b/joylive-plugin/joylive-router/joylive-router-springgateway4/src/main/java/com/jd/live/agent/plugin/router/springgateway/v4/response/GatewayClusterResponse.java @@ -15,12 +15,15 @@ */ package com.jd.live.agent.plugin.router.springgateway.v4.response; -import com.jd.live.agent.governance.response.AbstractHttpResponse.AbstractHttpOutboundResponse; +import com.jd.live.agent.core.util.cache.LazyObject; import com.jd.live.agent.governance.exception.ErrorPredicate; import com.jd.live.agent.governance.exception.ServiceError; +import com.jd.live.agent.governance.response.AbstractHttpResponse.AbstractHttpOutboundResponse; import org.springframework.http.HttpStatusCode; import org.springframework.http.server.reactive.ServerHttpResponse; +import java.util.function.Supplier; + /** * GatewayClusterResponse * @@ -28,12 +31,20 @@ */ public class GatewayClusterResponse extends AbstractHttpOutboundResponse { + private final LazyObject body; + public GatewayClusterResponse(ServerHttpResponse response) { + this(response, null); + } + + public GatewayClusterResponse(ServerHttpResponse response, Supplier supplier) { super(response); + this.body = new LazyObject<>(supplier); } public GatewayClusterResponse(ServiceError error, ErrorPredicate predicate) { super(error, predicate); + this.body = null; } @Override @@ -42,4 +53,9 @@ public String getCode() { return status == null ? null : String.valueOf(status.value()); } + @Override + public Object getResult() { + return body == null ? null : body.get(); + } + }