diff --git a/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/config/GovernanceConfig.java b/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/config/GovernanceConfig.java index adc34d21..c2ebaace 100644 --- a/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/config/GovernanceConfig.java +++ b/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/config/GovernanceConfig.java @@ -76,11 +76,6 @@ public class GovernanceConfig { public static final String CONFIG_REGISTRY_ENABLED = CONFIG_SWITCH_REGISTRY + ENABLED; public static final String CONFIG_FLOW_CONTROL_ENABLED = CONFIG_SWITCH_FLOW_CONTROL + ENABLED; - public static final String CONFIG_CIRCUIT_BREAKER_ENABLED = CONFIG_SWITCH_FLOW_CONTROL + ".circuitbreaker"; - public static final String CONFIG_LOADBALANCE_ENABLED = CONFIG_SWITCH_FLOW_CONTROL + ".loadbalance"; - public static final String CONFIG_RETRY_ENABLED = CONFIG_SWITCH_FLOW_CONTROL + ".retry"; - public static final String CONFIG_STICKY_ENABLED = CONFIG_SWITCH_FLOW_CONTROL + ".sticky"; - public static final String CONFIG_LIMIT_ENABLED = CONFIG_SWITCH_FLOW_CONTROL + ".limit"; public static final String CONFIG_LOCALHOST_ENABLED = CONFIG_SWITCH_FLOW_CONTROL + ".localhost"; public static final String CONFIG_VIRTUAL_ENABLED = CONFIG_SWITCH_FLOW_CONTROL + ".virtual"; diff --git a/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/invoke/filter/inbound/AuthInboundFilter.java b/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/invoke/filter/inbound/AuthInboundFilter.java index 2cb722ba..34a68b6d 100644 --- a/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/invoke/filter/inbound/AuthInboundFilter.java +++ b/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/invoke/filter/inbound/AuthInboundFilter.java @@ -48,7 +48,7 @@ public class AuthInboundFilter implements InboundFilter { @Override public void filter(InboundInvocation invocation, InboundFilterChain chain) { ServicePolicy servicePolicy = invocation.getServiceMetadata().getServicePolicy(); - AuthPolicy authPolicy = servicePolicy.getAuthPolicy(); + AuthPolicy authPolicy = servicePolicy == null ? null : servicePolicy.getAuthPolicy(); if (authPolicy != null && authPolicy.getType() != null) { Authenticate authenticate = authenticates.get(authPolicy.getType()); if (authenticate != null) { diff --git a/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/invoke/filter/route/CircuitBreakerFilter.java b/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/invoke/filter/route/CircuitBreakerFilter.java index 1da03e65..c89bff6a 100644 --- a/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/invoke/filter/route/CircuitBreakerFilter.java +++ b/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/invoke/filter/route/CircuitBreakerFilter.java @@ -61,7 +61,6 @@ @Injectable @Extension(value = "CircuitBreakerFilter", order = RouteFilter.ORDER_CIRCUIT_BREAKER) @ConditionalOnProperty(value = GovernanceConfig.CONFIG_FLOW_CONTROL_ENABLED, matchIfMissing = true) -@ConditionalOnProperty(value = GovernanceConfig.CONFIG_CIRCUIT_BREAKER_ENABLED, matchIfMissing = true) public class CircuitBreakerFilter implements RouteFilter, ExtensionInitializer { private static final Logger logger = LoggerFactory.getLogger(CircuitBreakerFilter.class); diff --git a/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/policy/service/ServiceType.java b/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/policy/service/ServiceType.java index 132d85f6..780131fe 100644 --- a/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/policy/service/ServiceType.java +++ b/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/policy/service/ServiceType.java @@ -59,6 +59,7 @@ public PathMatchType getMatchType() { @Override public String normalize(String path) { + // The path will not be empty, and the default policy can be set at the group level. return path == null || path.isEmpty() ? "" : path; } }, diff --git a/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/policy/service/circuitbreak/DegradeConfig.java b/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/policy/service/circuitbreak/DegradeConfig.java index 764f7cac..7d24830b 100644 --- a/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/policy/service/circuitbreak/DegradeConfig.java +++ b/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/policy/service/circuitbreak/DegradeConfig.java @@ -33,9 +33,14 @@ @Builder public class DegradeConfig { + public static final String TYPE_STRING = "string"; + public static final String TYPE_APPLICATION_TEXT = "application/text"; + public static final String TYPE_APPLICATION_JSON = "application/json"; + public static final String TYPE_JSON = "json"; + private int responseCode = 200; - private String contentType = "application/json"; + private String contentType; private Map attributes; @@ -48,6 +53,10 @@ public DegradeConfig(DegradeConfig config) { this.responseBody = config.responseBody; } + public String contentType() { + return contentType == null ? TYPE_APPLICATION_JSON : contentType; + } + public void foreach(BiConsumer consumer) { if (attributes != null) { attributes.forEach(consumer); @@ -58,4 +67,11 @@ public int bodyLength() { return responseBody == null ? 0 : responseBody.length(); } + public boolean text() { + return TYPE_STRING.equalsIgnoreCase(contentType) + || TYPE_JSON.equalsIgnoreCase(contentType) + || TYPE_APPLICATION_TEXT.equalsIgnoreCase(contentType) + || TYPE_APPLICATION_JSON.equalsIgnoreCase(contentType); + } + } diff --git a/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/request/AbstractRpcRequest.java b/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/request/AbstractRpcRequest.java index 1a126a06..d39c309f 100644 --- a/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/request/AbstractRpcRequest.java +++ b/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/request/AbstractRpcRequest.java @@ -121,6 +121,24 @@ public Object getAttachment(String key) { return key == null || attachments == null ? null : attachments.get(key); } + /** + * Loads a class with the given name, using the class loader of the request class. + * If the class cannot be found, returns the default class instead. + * + * @param className The name of the class to load. + * @param def The default class to return if the requested class cannot be found. + * @return The loaded class, or the default class if the requested class cannot be found. + */ + public Class loadClass(String className, Class def) { + if (className != null && !className.isEmpty()) { + try { + return request.getClass().getClassLoader().loadClass(className); + } catch (ClassNotFoundException ignored) { + } + } + return def; + } + /** * Provides an abstract base class for inbound RPC requests. *

diff --git a/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/request/RpcRequest.java b/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/request/RpcRequest.java index b3a16ba7..d8bb6f01 100644 --- a/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/request/RpcRequest.java +++ b/joylive-core/joylive-governance-api/src/main/java/com/jd/live/agent/governance/request/RpcRequest.java @@ -83,5 +83,14 @@ interface RpcOutboundRequest extends RpcRequest, OutboundRequest { default boolean isDisabled() { return false; } + + /** + * Checks if this object is a generic type. + * + * @return true if this object is a generic type, false otherwise. + */ + default boolean isGeneric() { + return false; + } } } diff --git a/joylive-demo/joylive-demo-dubbo3/joylive-demo-dubbo3-consumer/src/main/java/com/jd/live/agent/demo/v3/consumer/service/ConsumerService.java b/joylive-demo/joylive-demo-dubbo3/joylive-demo-dubbo3-consumer/src/main/java/com/jd/live/agent/demo/v3/consumer/service/ConsumerService.java index 3719a91b..e9a6d3fd 100644 --- a/joylive-demo/joylive-demo-dubbo3/joylive-demo-dubbo3-consumer/src/main/java/com/jd/live/agent/demo/v3/consumer/service/ConsumerService.java +++ b/joylive-demo/joylive-demo-dubbo3/joylive-demo-dubbo3-consumer/src/main/java/com/jd/live/agent/demo/v3/consumer/service/ConsumerService.java @@ -100,9 +100,12 @@ private void invoke() { } private void doStatus(RpcContextAttachment attachment, int code) { - LiveResponse result = helloService.status(code); - addTrace(attachment, result); - output("Invoke status: \n{}", result); + Object result = genericService.$invoke("status", + new String[]{"int"}, + new Object[]{code}); + LiveResponse response = objectMapper.convertValue(result, LiveResponse.class); + addTrace(attachment, response); + output("Generic invoke status: \n{}", response); } private void doEcho(RpcContextAttachment attachment) { diff --git a/joylive-demo/joylive-demo-sofarpc/joylive-demo-sofarpc-consumer/src/main/java/com/jd/live/agent/demo/sofarpc/consumer/config/JacksonConfig.java b/joylive-demo/joylive-demo-sofarpc/joylive-demo-sofarpc-consumer/src/main/java/com/jd/live/agent/demo/sofarpc/consumer/config/JacksonConfig.java new file mode 100644 index 00000000..a5ee836e --- /dev/null +++ b/joylive-demo/joylive-demo-sofarpc/joylive-demo-sofarpc-consumer/src/main/java/com/jd/live/agent/demo/sofarpc/consumer/config/JacksonConfig.java @@ -0,0 +1,36 @@ +/* + * Copyright © ${year} ${owner} (${email}) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.jd.live.agent.demo.sofarpc.consumer.config; + +import com.alipay.hessian.generic.model.GenericObject; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.jd.live.agent.demo.sofarpc.consumer.json.GenericObjectSerializer; +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class JacksonConfig { + + @Bean + public Jackson2ObjectMapperBuilderCustomizer customizer() { + return builder -> { + SimpleModule module = new SimpleModule(); + module.addSerializer(GenericObject.class, new GenericObjectSerializer()); + builder.modules(module); + }; + } +} diff --git a/joylive-demo/joylive-demo-sofarpc/joylive-demo-sofarpc-consumer/src/main/java/com/jd/live/agent/demo/sofarpc/consumer/config/LiveConfig.java b/joylive-demo/joylive-demo-sofarpc/joylive-demo-sofarpc-consumer/src/main/java/com/jd/live/agent/demo/sofarpc/consumer/config/LiveConfig.java index 720d8f46..f2adbe06 100644 --- a/joylive-demo/joylive-demo-sofarpc/joylive-demo-sofarpc-consumer/src/main/java/com/jd/live/agent/demo/sofarpc/consumer/config/LiveConfig.java +++ b/joylive-demo/joylive-demo-sofarpc/joylive-demo-sofarpc-consumer/src/main/java/com/jd/live/agent/demo/sofarpc/consumer/config/LiveConfig.java @@ -19,6 +19,7 @@ import lombok.Getter; import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.ImportResource; import org.springframework.stereotype.Component; import java.util.function.BiConsumer; @@ -26,6 +27,7 @@ @Getter @Setter @Component +@ImportResource("classpath:sofa-rpc.xml") @ConfigurationProperties(prefix = "live") public class LiveConfig { diff --git a/joylive-demo/joylive-demo-sofarpc/joylive-demo-sofarpc-consumer/src/main/java/com/jd/live/agent/demo/sofarpc/consumer/json/GenericObjectSerializer.java b/joylive-demo/joylive-demo-sofarpc/joylive-demo-sofarpc-consumer/src/main/java/com/jd/live/agent/demo/sofarpc/consumer/json/GenericObjectSerializer.java new file mode 100644 index 00000000..859ac3b4 --- /dev/null +++ b/joylive-demo/joylive-demo-sofarpc/joylive-demo-sofarpc-consumer/src/main/java/com/jd/live/agent/demo/sofarpc/consumer/json/GenericObjectSerializer.java @@ -0,0 +1,38 @@ +/* + * Copyright © ${year} ${owner} (${email}) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.jd.live.agent.demo.sofarpc.consumer.json; + +import com.alipay.hessian.generic.model.GenericObject; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +import java.io.IOException; +import java.util.Map; + +public class GenericObjectSerializer extends JsonSerializer { + + @Override + public void serialize(GenericObject person, JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeStartObject(); + if (person.getFields() != null) { + for (Map.Entry entry : person.getFields().entrySet()) { + gen.writeObjectField(entry.getKey(), entry.getValue()); + } + } + gen.writeEndObject(); + } +} \ No newline at end of file diff --git a/joylive-demo/joylive-demo-sofarpc/joylive-demo-sofarpc-consumer/src/main/java/com/jd/live/agent/demo/sofarpc/consumer/service/ConsumerService.java b/joylive-demo/joylive-demo-sofarpc/joylive-demo-sofarpc-consumer/src/main/java/com/jd/live/agent/demo/sofarpc/consumer/service/ConsumerService.java index 3916a4f6..b1874fbd 100644 --- a/joylive-demo/joylive-demo-sofarpc/joylive-demo-sofarpc-consumer/src/main/java/com/jd/live/agent/demo/sofarpc/consumer/service/ConsumerService.java +++ b/joylive-demo/joylive-demo-sofarpc/joylive-demo-sofarpc-consumer/src/main/java/com/jd/live/agent/demo/sofarpc/consumer/service/ConsumerService.java @@ -15,6 +15,7 @@ */ package com.jd.live.agent.demo.sofarpc.consumer.service; +import com.alipay.sofa.rpc.api.GenericService; import com.alipay.sofa.rpc.context.RpcInvokeContext; import com.alipay.sofa.runtime.api.annotation.SofaReference; import com.alipay.sofa.runtime.api.annotation.SofaReferenceBinding; @@ -56,6 +57,9 @@ public class ConsumerService implements ApplicationListener + + + + + + + diff --git a/joylive-package/src/main/assembly/config/config.yaml b/joylive-package/src/main/assembly/config/config.yaml index bb62a981..1a22998c 100644 --- a/joylive-package/src/main/assembly/config/config.yaml +++ b/joylive-package/src/main/assembly/config/config.yaml @@ -101,9 +101,6 @@ agent: enabled: ${CONFIG_REGISTRY_ENABLED:true} flowcontrol: enabled: ${CONFIG_FLOW_CONTROL_ENABLED:true} - loadbalance: ${CONFIG_LOADBALANCE_ENABLED:true} - sticky: ${CONFIG_STICKY_ENABLED:false} - limit: ${CONFIG_LIMIT_ENABLED:true} localhost: ${CONFIG_LOCALHOST_ENABLED:false} virtual: ${CONFIG_VIRTUAL_ENABLED:false} protect: diff --git a/joylive-package/src/main/assembly/config/microservice.json b/joylive-package/src/main/assembly/config/microservice.json index 1153905c..0a468544 100644 --- a/joylive-package/src/main/assembly/config/microservice.json +++ b/joylive-package/src/main/assembly/config/microservice.json @@ -543,5 +543,67 @@ ] } ] + }, + { + "name": "com.jd.live.agent.demo.service.HelloService", + "serviceType": "RPC_INTERFACE", + "version": 0, + "groups": [ + { + "name": "default", + "defaultGroup": true, + "servicePolicy": { + "livePolicy": { + "unitPolicy": "UNIT", + "writeProtect": false, + "cellPolicy": "PREFER_LOCAL_CELL" + } + }, + "paths": [ + { + "path": "/", + "matchType": "EQUAL", + "methods": [ + { + "name": "status", + "servicePolicy": { + "circuitBreakPolicies": [ + { + "name": "cb1", + "level": "SERVICE", + "slidingWindowType": "count", + "slidingWindowSize": 5, + "minCallsThreshold": 1, + "errorCodes": [ + "3" + ], + "exceptions": [ + "java.lang.RuntimeException" + ], + "failureRateThreshold": 20, + "slowCallRateThreshold": 20, + "slowCallDurationThreshold": 1000, + "waitDurationInOpenState": 50, + "allowedCallsInHalfOpenState": 3, + "forceOpen": false, + "realizeType": "Resilience4j", + "degradeConfig": { + "responseCode": 200, + "attributes": { + "degrade-header-1": "service1", + "degrade-header-2": "service2" + }, + "responseBody": "{\"code\":200,\"traces\":[{\"service\":\"service-provider\",\"location\":{\"liveSpaceId\":\"v4bEh4kd6Jvu5QBX09qYq-qlbcs\",\"unit\":\"unit1\",\"cell\":\"cell1\",\"laneSpaceId\":\"1\",\"lane\":\"production\"},\"transmission\":{\"carrier\":\"header\"}}],\"data\":999}" + }, + "version": 1 + } + ] + } + } + ] + } + ] + } + ] } ] \ No newline at end of file diff --git a/joylive-plugin/joylive-router/joylive-router-dubbo2.6/src/main/java/com/alibaba/dubbo/rpc/cluster/support/Dubbo26Cluster.java b/joylive-plugin/joylive-router/joylive-router-dubbo2.6/src/main/java/com/alibaba/dubbo/rpc/cluster/support/Dubbo26Cluster.java index 66f1d1ad..33dca501 100644 --- a/joylive-plugin/joylive-router/joylive-router-dubbo2.6/src/main/java/com/alibaba/dubbo/rpc/cluster/support/Dubbo26Cluster.java +++ b/joylive-plugin/joylive-router/joylive-router-dubbo2.6/src/main/java/com/alibaba/dubbo/rpc/cluster/support/Dubbo26Cluster.java @@ -346,17 +346,22 @@ private Result createResponse(DubboOutboundRequest request, DegradeConfig degrad RpcResult result = new RpcResult(); result.setAttachments(degradeConfig.getAttributes()); if (body != null) { - // TODO generic & callback & async - Type[] types = RpcUtils.getReturnTypes(invocation); Object value; - if (types == null || types.length == 0) { - // happens when generic invoke or void return - value = null; - } else if (types.length == 1) { - Class type = (Class) types[0]; - value = String.class == type ? body : parser.read(new StringReader(body), type); + if (request.isGeneric()) { + value = degradeConfig.text() + ? body + : parser.read(new StringReader(body), request.loadClass(degradeConfig.getContentType(), Object.class)); } else { - value = parser.read(new StringReader(body), types[1]); + Type[] types = RpcUtils.getReturnTypes(invocation); + if (types == null || types.length == 0) { + // void return + value = null; + } else if (types.length == 1) { + Class type = (Class) types[0]; + value = String.class == type ? body : parser.read(new StringReader(body), type); + } else { + value = parser.read(new StringReader(body), types[1]); + } } result.setValue(value); } diff --git a/joylive-plugin/joylive-router/joylive-router-dubbo2.6/src/main/java/com/jd/live/agent/plugin/router/dubbo/v2_6/request/DubboRequest.java b/joylive-plugin/joylive-router/joylive-router-dubbo2.6/src/main/java/com/jd/live/agent/plugin/router/dubbo/v2_6/request/DubboRequest.java index 54f7cbc8..c6dbfe1d 100644 --- a/joylive-plugin/joylive-router/joylive-router-dubbo2.6/src/main/java/com/jd/live/agent/plugin/router/dubbo/v2_6/request/DubboRequest.java +++ b/joylive-plugin/joylive-router/joylive-router-dubbo2.6/src/main/java/com/jd/live/agent/plugin/router/dubbo/v2_6/request/DubboRequest.java @@ -18,7 +18,9 @@ import com.alibaba.dubbo.common.Constants; import com.alibaba.dubbo.common.URL; import com.alibaba.dubbo.rpc.Invocation; +import com.alibaba.dubbo.rpc.Invoker; import com.alibaba.dubbo.rpc.RpcContext; +import com.alibaba.dubbo.rpc.service.GenericService; import com.alibaba.dubbo.rpc.support.RpcUtils; import com.jd.live.agent.governance.request.AbstractRpcRequest.AbstractRpcInboundRequest; import com.jd.live.agent.governance.request.AbstractRpcRequest.AbstractRpcOutboundRequest; @@ -30,6 +32,11 @@ */ public interface DubboRequest { + /** + * generic call + */ + String METHOD_$INVOKE = "$invoke"; + /** * Represents an inbound request in a Dubbo RPC communication. *

@@ -81,5 +88,13 @@ public DubboOutboundRequest(Invocation request) { this.arguments = RpcUtils.getArguments(request); this.attachments = request.getAttachments(); } + + @Override + public boolean isGeneric() { + Invoker invoker = request.getInvoker(); + String methodName = request.getMethodName(); + return METHOD_$INVOKE.equals(methodName) + && invoker.getInterface().isAssignableFrom(GenericService.class); + } } } diff --git a/joylive-plugin/joylive-router/joylive-router-dubbo2.7/src/main/java/com/jd/live/agent/plugin/router/dubbo/v2_7/request/DubboRequest.java b/joylive-plugin/joylive-router/joylive-router-dubbo2.7/src/main/java/com/jd/live/agent/plugin/router/dubbo/v2_7/request/DubboRequest.java index a5aaf477..13d29938 100644 --- a/joylive-plugin/joylive-router/joylive-router-dubbo2.7/src/main/java/com/jd/live/agent/plugin/router/dubbo/v2_7/request/DubboRequest.java +++ b/joylive-plugin/joylive-router/joylive-router-dubbo2.7/src/main/java/com/jd/live/agent/plugin/router/dubbo/v2_7/request/DubboRequest.java @@ -21,7 +21,9 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.RpcContext; +import org.apache.dubbo.rpc.service.GenericService; import static org.apache.dubbo.common.constants.RegistryConstants.*; @@ -34,6 +36,13 @@ public interface DubboRequest { String METADATA_SERVICE = "org.apache.dubbo.metadata.MetadataService"; + /** + * generic call + */ + String METHOD_$INVOKE = "$invoke"; + + String METHOD_$INVOKE_ASYNC = "$invokeAsync"; + /** * Represents an inbound request in a Dubbo RPC communication. *

@@ -112,5 +121,15 @@ public DubboOutboundRequest(Invocation request) { public boolean isSystem() { return METADATA_SERVICE.equals(interfaceName); } + + @Override + public boolean isGeneric() { + Invoker invoker = request.getInvoker(); + String methodName = request.getMethodName(); + return (( + METHOD_$INVOKE.equals(methodName) + || METHOD_$INVOKE_ASYNC.equals(methodName)) + && invoker.getInterface().isAssignableFrom(GenericService.class)); + } } } diff --git a/joylive-plugin/joylive-router/joylive-router-dubbo2.7/src/main/java/org/apache/dubbo/rpc/cluster/support/Dubbo27Cluster.java b/joylive-plugin/joylive-router/joylive-router-dubbo2.7/src/main/java/org/apache/dubbo/rpc/cluster/support/Dubbo27Cluster.java index fabdcfe3..6e71e955 100644 --- a/joylive-plugin/joylive-router/joylive-router-dubbo2.7/src/main/java/org/apache/dubbo/rpc/cluster/support/Dubbo27Cluster.java +++ b/joylive-plugin/joylive-router/joylive-router-dubbo2.7/src/main/java/org/apache/dubbo/rpc/cluster/support/Dubbo27Cluster.java @@ -343,17 +343,22 @@ private Result createResponse(DubboOutboundRequest request, DegradeConfig degrad AppResponse response = new AppResponse(); response.setAttachments(degradeConfig.getAttributes()); if (body != null) { - // TODO generic & callback & async - Type[] types = RpcUtils.getReturnTypes(invocation); Object value; - if (types == null || types.length == 0) { - // happens when generic invoke or void return - value = null; - } else if (types.length == 1) { - Class type = (Class) types[0]; - value = String.class == type ? body : parser.read(new StringReader(body), type); + if (request.isGeneric()) { + value = degradeConfig.text() + ? body + : parser.read(new StringReader(body), request.loadClass(degradeConfig.getContentType(), Object.class)); } else { - value = parser.read(new StringReader(body), types[1]); + Type[] types = RpcUtils.getReturnTypes(invocation); + if (types == null || types.length == 0) { + // void return + value = null; + } else if (types.length == 1) { + Class type = (Class) types[0]; + value = String.class == type ? body : parser.read(new StringReader(body), type); + } else { + value = parser.read(new StringReader(body), types[1]); + } } response.setValue(value); } diff --git a/joylive-plugin/joylive-router/joylive-router-dubbo3/src/main/java/com/jd/live/agent/plugin/router/dubbo/v3/request/DubboRequest.java b/joylive-plugin/joylive-router/joylive-router-dubbo3/src/main/java/com/jd/live/agent/plugin/router/dubbo/v3/request/DubboRequest.java index 9947d86e..234feae4 100644 --- a/joylive-plugin/joylive-router/joylive-router-dubbo3/src/main/java/com/jd/live/agent/plugin/router/dubbo/v3/request/DubboRequest.java +++ b/joylive-plugin/joylive-router/joylive-router-dubbo3/src/main/java/com/jd/live/agent/plugin/router/dubbo/v3/request/DubboRequest.java @@ -21,8 +21,10 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.RpcContext; import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.service.GenericService; import static org.apache.dubbo.common.constants.RegistryConstants.*; @@ -35,6 +37,13 @@ public interface DubboRequest { String METADATA_SERVICE = "org.apache.dubbo.metadata.MetadataService"; + /** + * generic call + */ + String METHOD_$INVOKE = "$invoke"; + + String METHOD_$INVOKE_ASYNC = "$invokeAsync"; + /** * Represents an inbound request in a Dubbo RPC communication. *

@@ -131,5 +140,15 @@ public Throwable getCause(Throwable throwable) { } return super.getCause(throwable); } + + @Override + public boolean isGeneric() { + Invoker invoker = request.getInvoker(); + String methodName = request.getMethodName(); + return (( + METHOD_$INVOKE.equals(methodName) + || METHOD_$INVOKE_ASYNC.equals(methodName)) + && invoker.getInterface().isAssignableFrom(GenericService.class)); + } } } diff --git a/joylive-plugin/joylive-router/joylive-router-dubbo3/src/main/java/org/apache/dubbo/rpc/cluster/support/Dubbo3Cluster.java b/joylive-plugin/joylive-router/joylive-router-dubbo3/src/main/java/org/apache/dubbo/rpc/cluster/support/Dubbo3Cluster.java index 7e3907c2..6423248c 100644 --- a/joylive-plugin/joylive-router/joylive-router-dubbo3/src/main/java/org/apache/dubbo/rpc/cluster/support/Dubbo3Cluster.java +++ b/joylive-plugin/joylive-router/joylive-router-dubbo3/src/main/java/org/apache/dubbo/rpc/cluster/support/Dubbo3Cluster.java @@ -342,17 +342,22 @@ private Result createResponse(DubboOutboundRequest request, DegradeConfig degrad AppResponse response = new AppResponse(); response.setAttachments(degradeConfig.getAttributes()); if (body != null) { - // TODO generic & callback & async - Type[] types = RpcUtils.getReturnTypes(invocation); Object value; - if (types == null || types.length == 0) { - // happens when generic invoke or void return - value = null; - } else if (types.length == 1) { - Class type = (Class) types[0]; - value = String.class == type ? body : parser.read(new StringReader(body), type); + if (request.isGeneric()) { + value = degradeConfig.text() + ? body + : parser.read(new StringReader(body), request.loadClass(degradeConfig.getContentType(), Object.class)); } else { - value = parser.read(new StringReader(body), types[1]); + Type[] types = RpcUtils.getReturnTypes(invocation); + if (types == null || types.length == 0) { + // void return + value = null; + } else if (types.length == 1) { + Class type = (Class) types[0]; + value = String.class == type ? body : parser.read(new StringReader(body), type); + } else { + value = parser.read(new StringReader(body), types[1]); + } } response.setValue(value); } diff --git a/joylive-plugin/joylive-router/joylive-router-sofarpc/src/main/java/com/jd/live/agent/plugin/router/sofarpc/cluster/SofaRpcCluster.java b/joylive-plugin/joylive-router/joylive-router-sofarpc/src/main/java/com/jd/live/agent/plugin/router/sofarpc/cluster/SofaRpcCluster.java index a556543d..70ef3f23 100644 --- a/joylive-plugin/joylive-router/joylive-router-sofarpc/src/main/java/com/jd/live/agent/plugin/router/sofarpc/cluster/SofaRpcCluster.java +++ b/joylive-plugin/joylive-router/joylive-router-sofarpc/src/main/java/com/jd/live/agent/plugin/router/sofarpc/cluster/SofaRpcCluster.java @@ -15,7 +15,9 @@ */ package com.jd.live.agent.plugin.router.sofarpc.cluster; +import com.alipay.hessian.generic.model.GenericObject; import com.alipay.sofa.rpc.client.*; +import com.alipay.sofa.rpc.common.RemotingConstants; import com.alipay.sofa.rpc.common.RpcConstants; import com.alipay.sofa.rpc.config.ConsumerConfig; import com.alipay.sofa.rpc.context.RpcInternalContext; @@ -47,6 +49,7 @@ import com.jd.live.agent.governance.policy.service.cluster.RetryPolicy; import com.jd.live.agent.governance.response.ServiceError; import com.jd.live.agent.plugin.router.sofarpc.instance.SofaRpcEndpoint; +import com.jd.live.agent.plugin.router.sofarpc.request.SofaRpcRequest.GenericType; import com.jd.live.agent.plugin.router.sofarpc.request.SofaRpcRequest.SofaRpcOutboundRequest; import com.jd.live.agent.plugin.router.sofarpc.response.SofaRpcResponse.SofaRpcOutboundResponse; @@ -56,6 +59,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; @@ -398,20 +402,44 @@ private SofaResponse createResponse(SofaRpcOutboundRequest request, DegradeConfi result.setResponseProps(new HashMap<>(degradeConfig.getAttributes())); } if (body != null) { - // TODO generic & callback & async - Method method = sofaRequest.getMethod(); - Type type = method.getGenericReturnType(); Object value; - if (void.class == type) { - // happens when generic invoke or void return - value = null; + if (request.isGeneric()) { + GenericType genericType = request.getGenericType(); + if (degradeConfig.text()) { + value = body; + } else if (RemotingConstants.SERIALIZE_FACTORY_GENERIC.equals(genericType.getType())) { + value = convertGenericObject(parser.read(new StringReader(body), Object.class)); + } else if (RemotingConstants.SERIALIZE_FACTORY_MIX.equals(genericType.getType())) { + value = parser.read(new StringReader(body), genericType.getReturnType()); + } else { + value = parser.read(new StringReader(body), request.loadClass(degradeConfig.getContentType(), Object.class)); + } } else { - value = parser.read(new StringReader(body), type); + Method method = sofaRequest.getMethod(); + Type type = method.getGenericReturnType(); + if (void.class == type) { + // void return + value = null; + } else { + value = parser.read(new StringReader(body), type); + } } result.setAppResponse(value); } return result; } + + private Object convertGenericObject(Object value) { + if (value instanceof Map) { + GenericObject object = new GenericObject(value.getClass().getName()); + for (Map.Entry entry : ((Map) value).entrySet()) { + object.putField(entry.getKey().toString(), convertGenericObject(entry.getValue())); + } + return object; + } else { + return value; + } + } } diff --git a/joylive-plugin/joylive-router/joylive-router-sofarpc/src/main/java/com/jd/live/agent/plugin/router/sofarpc/request/SofaRpcRequest.java b/joylive-plugin/joylive-router/joylive-router-sofarpc/src/main/java/com/jd/live/agent/plugin/router/sofarpc/request/SofaRpcRequest.java index a58273cb..40af4be1 100644 --- a/joylive-plugin/joylive-router/joylive-router-sofarpc/src/main/java/com/jd/live/agent/plugin/router/sofarpc/request/SofaRpcRequest.java +++ b/joylive-plugin/joylive-router/joylive-router-sofarpc/src/main/java/com/jd/live/agent/plugin/router/sofarpc/request/SofaRpcRequest.java @@ -15,6 +15,8 @@ */ package com.jd.live.agent.plugin.router.sofarpc.request; +import com.alipay.sofa.rpc.api.GenericContext; +import com.alipay.sofa.rpc.common.RemotingConstants; import com.alipay.sofa.rpc.context.RpcInternalContext; import com.alipay.sofa.rpc.core.request.SofaRequest; import com.jd.live.agent.governance.request.AbstractRpcRequest.AbstractRpcInboundRequest; @@ -28,6 +30,13 @@ */ public interface SofaRpcRequest { + /** + * generic call + */ + String METHOD_$INVOKE = "$invoke"; + + String METHOD_$GENERIC_INVOKE = "$genericInvoke"; + /** * Represents an inbound RPC request for the SOFA framework, encapsulating the necessary * details for processing the request on the server side. @@ -86,6 +95,8 @@ class SofaRpcOutboundRequest extends AbstractRpcOutboundRequest imp private final StickyRequest stickyRequest; + private final GenericType genericType; + /** * Creates a new SofaRpcOutboundRequest without a sticky session identifier. This constructor is used * when sticky session routing is not required for the RPC call. @@ -111,12 +122,13 @@ public SofaRpcOutboundRequest(SofaRequest request) { public SofaRpcOutboundRequest(SofaRequest request, StickyRequest stickyRequest) { super(request); this.stickyRequest = stickyRequest; - this.service = request.getInterfaceName(); + this.genericType = computeGenericType(); String uniqueName = request.getTargetServiceUniqueName(); - int pos = uniqueName.lastIndexOf(':'); + int pos = uniqueName.indexOf(':'); this.group = pos < 0 ? null : uniqueName.substring(pos + 1); - this.method = request.getMethodName(); - this.arguments = request.getMethodArgs(); + this.service = pos < 0 ? uniqueName : uniqueName.substring(0, pos); + this.method = genericType == null ? request.getMethodName() : (String) request.getMethodArgs()[0]; + this.arguments = genericType == null ? request.getMethodArgs() : (Object[]) request.getMethodArgs()[2]; this.attachments = request.getRequestProps(); } @@ -131,5 +143,64 @@ public void setStickyId(String stickyId) { stickyRequest.setStickyId(stickyId); } } + + @Override + public boolean isGeneric() { + return genericType != null; + } + + public GenericType getGenericType() { + return genericType; + } + + /** + * Computes the generic type based on the request method name and arguments. + * + * @return The computed generic type, or null if no generic type could be determined. + */ + private GenericType computeGenericType() { + String methodName = request.getMethodName(); + if (METHOD_$INVOKE.equals(methodName)) { + return new GenericType(RemotingConstants.SERIALIZE_FACTORY_NORMAL, null); + } else if (METHOD_$GENERIC_INVOKE.equals(methodName)) { + Object[] args = request.getMethodArgs(); + if (args.length == 3) { + return new GenericType(RemotingConstants.SERIALIZE_FACTORY_GENERIC, null); + } else if (args.length == 4) { + if (args[3] instanceof GenericContext) { + return new GenericType(RemotingConstants.SERIALIZE_FACTORY_GENERIC, null); + } + if (args[3] instanceof Class) { + return new GenericType(RemotingConstants.SERIALIZE_FACTORY_MIX, (Class) args[3]); + } + } else if (args.length == 5) { + return new GenericType(RemotingConstants.SERIALIZE_FACTORY_MIX, (Class) args[3]); + } + } + return null; + } + } + + /** + * Represents a generic type with a specified type and return type. + */ + class GenericType { + + private final String type; + + private final Class returnType; + + public GenericType(String type, Class returnType) { + this.type = type; + this.returnType = returnType; + } + + public String getType() { + return type; + } + + public Class getReturnType() { + return returnType; + } } } diff --git a/joylive-plugin/joylive-router/joylive-router-sofarpc/src/main/java/com/jd/live/agent/plugin/router/sofarpc/response/SofaRpcResponse.java b/joylive-plugin/joylive-router/joylive-router-sofarpc/src/main/java/com/jd/live/agent/plugin/router/sofarpc/response/SofaRpcResponse.java index bc3837b0..7b2f05f7 100644 --- a/joylive-plugin/joylive-router/joylive-router-sofarpc/src/main/java/com/jd/live/agent/plugin/router/sofarpc/response/SofaRpcResponse.java +++ b/joylive-plugin/joylive-router/joylive-router-sofarpc/src/main/java/com/jd/live/agent/plugin/router/sofarpc/response/SofaRpcResponse.java @@ -58,7 +58,7 @@ public SofaRpcOutboundResponse(SofaResponse response) { * if retry logic is not applicable. */ public SofaRpcOutboundResponse(SofaResponse response, Predicate predicate) { - super(response, response != null && response.isError() ? new ServiceError(response.getErrorMsg(), true) : null, predicate); + super(response, getError(response), predicate); } /** @@ -73,6 +73,23 @@ public SofaRpcOutboundResponse(ServiceError error, Predicate predicat super(null, error, predicate); } + /** + * Extracts the error information from a SofaResponse object. + * + * @param response The SofaResponse object to extract the error information from. + * @return A ServiceError object containing the error information, or null if no error is found. + */ + private static ServiceError getError(SofaResponse response) { + if (response == null) { + return null; + } else if (response.isError()) { + return new ServiceError(response.getErrorMsg(), true); + } else if (response.getAppResponse() instanceof Throwable) { + return new ServiceError((Throwable) response.getAppResponse(), true); + } + return null; + } + } } diff --git a/joylive-plugin/joylive-router/joylive-router-springcloud3/src/main/java/com/jd/live/agent/plugin/router/springcloud/v3/cluster/BlockingCluster.java b/joylive-plugin/joylive-router/joylive-router-springcloud3/src/main/java/com/jd/live/agent/plugin/router/springcloud/v3/cluster/BlockingCluster.java index 97f24c90..aa944e5c 100644 --- a/joylive-plugin/joylive-router/joylive-router-springcloud3/src/main/java/com/jd/live/agent/plugin/router/springcloud/v3/cluster/BlockingCluster.java +++ b/joylive-plugin/joylive-router/joylive-router-springcloud3/src/main/java/com/jd/live/agent/plugin/router/springcloud/v3/cluster/BlockingCluster.java @@ -253,7 +253,7 @@ public HttpHeaders getHeaders() { if (attributes != null) { attributes.forEach(headers::add); } - headers.set(HttpHeaders.CONTENT_TYPE, degradeConfig.getContentType()); + headers.set(HttpHeaders.CONTENT_TYPE, degradeConfig.contentType()); headers.set(HttpHeaders.CONTENT_LENGTH, String.valueOf(length)); return headers; } diff --git a/joylive-plugin/joylive-router/joylive-router-springcloud3/src/main/java/com/jd/live/agent/plugin/router/springcloud/v3/cluster/FeignCluster.java b/joylive-plugin/joylive-router/joylive-router-springcloud3/src/main/java/com/jd/live/agent/plugin/router/springcloud/v3/cluster/FeignCluster.java index 69cb0907..652c3767 100644 --- a/joylive-plugin/joylive-router/joylive-router-springcloud3/src/main/java/com/jd/live/agent/plugin/router/springcloud/v3/cluster/FeignCluster.java +++ b/joylive-plugin/joylive-router/joylive-router-springcloud3/src/main/java/com/jd/live/agent/plugin/router/springcloud/v3/cluster/FeignCluster.java @@ -44,7 +44,11 @@ import static com.jd.live.agent.bootstrap.exception.RejectException.RejectCircuitBreakException.getCircuitBreakException; - +/** + * A cluster implementation for Feign clients that manages a group of servers and provides load balancing and failover capabilities. + * + * @see AbstractClientCluster + */ public class FeignCluster extends AbstractClientCluster { private static final Logger logger = LoggerFactory.getLogger(FeignCluster.class); @@ -161,7 +165,7 @@ private feign.Response createResponse(FeignClusterRequest request, DegradeConfig degradeConfig.getAttributes().forEach((k, v) -> headers.computeIfAbsent(k, k1 -> new ArrayList<>()).add(v)); } headers.put(HttpHeaders.CONTENT_LENGTH, Collections.singletonList(String.valueOf(data.length))); - headers.put(HttpHeaders.CONTENT_TYPE, Collections.singletonList(degradeConfig.getContentType())); + headers.put(HttpHeaders.CONTENT_TYPE, Collections.singletonList(degradeConfig.contentType())); return feign.Response.builder() .status(degradeConfig.getResponseCode()) diff --git a/joylive-plugin/joylive-router/joylive-router-springcloud3/src/main/java/com/jd/live/agent/plugin/router/springcloud/v3/cluster/ReactiveCluster.java b/joylive-plugin/joylive-router/joylive-router-springcloud3/src/main/java/com/jd/live/agent/plugin/router/springcloud/v3/cluster/ReactiveCluster.java index c14a675f..0f06f77d 100644 --- a/joylive-plugin/joylive-router/joylive-router-springcloud3/src/main/java/com/jd/live/agent/plugin/router/springcloud/v3/cluster/ReactiveCluster.java +++ b/joylive-plugin/joylive-router/joylive-router-springcloud3/src/main/java/com/jd/live/agent/plugin/router/springcloud/v3/cluster/ReactiveCluster.java @@ -222,7 +222,7 @@ private ClientResponse createResponse(ReactiveClusterRequest request, DegradeCon .headers(headers -> { headers.addAll(request.getRequest().headers()); degradeConfig.foreach(headers::add); - headers.set(HttpHeaders.CONTENT_TYPE, degradeConfig.getContentType()); + headers.set(HttpHeaders.CONTENT_TYPE, degradeConfig.contentType()); headers.set(HttpHeaders.CONTENT_LENGTH, String.valueOf(degradeConfig.bodyLength())); }).build(); } diff --git a/joylive-plugin/joylive-router/joylive-router-springcloud4/src/main/java/com/jd/live/agent/plugin/router/springcloud/v4/cluster/BlockingCluster.java b/joylive-plugin/joylive-router/joylive-router-springcloud4/src/main/java/com/jd/live/agent/plugin/router/springcloud/v4/cluster/BlockingCluster.java index 1f60b4bf..e5761e7f 100644 --- a/joylive-plugin/joylive-router/joylive-router-springcloud4/src/main/java/com/jd/live/agent/plugin/router/springcloud/v4/cluster/BlockingCluster.java +++ b/joylive-plugin/joylive-router/joylive-router-springcloud4/src/main/java/com/jd/live/agent/plugin/router/springcloud/v4/cluster/BlockingCluster.java @@ -242,7 +242,7 @@ public HttpHeaders getHeaders() { if (attributes != null) { attributes.forEach(headers::add); } - headers.set(HttpHeaders.CONTENT_TYPE, degradeConfig.getContentType()); + headers.set(HttpHeaders.CONTENT_TYPE, degradeConfig.contentType()); headers.set(HttpHeaders.CONTENT_LENGTH, String.valueOf(length)); return headers; } diff --git a/joylive-plugin/joylive-router/joylive-router-springcloud4/src/main/java/com/jd/live/agent/plugin/router/springcloud/v4/cluster/FeignCluster.java b/joylive-plugin/joylive-router/joylive-router-springcloud4/src/main/java/com/jd/live/agent/plugin/router/springcloud/v4/cluster/FeignCluster.java index aafab18d..9f697bea 100644 --- a/joylive-plugin/joylive-router/joylive-router-springcloud4/src/main/java/com/jd/live/agent/plugin/router/springcloud/v4/cluster/FeignCluster.java +++ b/joylive-plugin/joylive-router/joylive-router-springcloud4/src/main/java/com/jd/live/agent/plugin/router/springcloud/v4/cluster/FeignCluster.java @@ -164,7 +164,7 @@ private feign.Response createResponse(FeignClusterRequest request, DegradeConfig degradeConfig.getAttributes().forEach((k, v) -> headers.computeIfAbsent(k, k1 -> new ArrayList<>()).add(v)); } headers.put(HttpHeaders.CONTENT_LENGTH, Collections.singletonList(String.valueOf(data.length))); - headers.put(HttpHeaders.CONTENT_TYPE, Collections.singletonList(degradeConfig.getContentType())); + headers.put(HttpHeaders.CONTENT_TYPE, Collections.singletonList(degradeConfig.contentType())); return feign.Response.builder() .status(degradeConfig.getResponseCode()) 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 8b9ff253..35339e9a 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 @@ -208,7 +208,7 @@ private ServerHttpResponse createResponse(GatewayClusterRequest httpRequest, Deg } response.setRawStatusCode(degradeConfig.getResponseCode()); response.setStatusCode(HttpStatus.valueOf(degradeConfig.getResponseCode())); - headers.set(HttpHeaders.CONTENT_TYPE, degradeConfig.getContentType()); + headers.set(HttpHeaders.CONTENT_TYPE, degradeConfig.contentType()); response.writeWith(Flux.just(buffer)).block(); return response; 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 275c8997..a0c44944 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 @@ -209,7 +209,7 @@ private ServerHttpResponse createResponse(GatewayClusterRequest httpRequest, Deg } response.setRawStatusCode(degradeConfig.getResponseCode()); response.setStatusCode(HttpStatus.valueOf(degradeConfig.getResponseCode())); - headers.set(HttpHeaders.CONTENT_TYPE, degradeConfig.getContentType()); + headers.set(HttpHeaders.CONTENT_TYPE, degradeConfig.contentType()); response.writeWith(Flux.just(buffer)).block(); return response; diff --git a/joylive-test/joylive-test-bytebuddy/src/test/resources/config/config.yaml b/joylive-test/joylive-test-bytebuddy/src/test/resources/config/config.yaml index 0f379771..5f50b0fc 100644 --- a/joylive-test/joylive-test-bytebuddy/src/test/resources/config/config.yaml +++ b/joylive-test/joylive-test-bytebuddy/src/test/resources/config/config.yaml @@ -99,9 +99,6 @@ agent: enabled: ${CONFIG_REGISTRY_ENABLED:true} flowcontrol: enabled: ${CONFIG_FLOW_CONTROL_ENABLED:true} - loadbalance: ${CONFIG_LOADBALANCE_ENABLED:true} - sticky: ${CONFIG_STICKY_ENABLED:false} - limit: ${CONFIG_LIMIT_ENABLED:true} localhost: ${CONFIG_LOCALHOST_ENABLED:false} virtual: ${CONFIG_VIRTUAL_ENABLED:false} protect: