Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

75 fix degraded response errors during generic calls #76

Merged
merged 4 commits into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public class AuthInboundFilter implements InboundFilter {
@Override
public <T extends InboundRequest> void filter(InboundInvocation<T> 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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<String, String> attributes;

Expand All @@ -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<String, String> consumer) {
if (attributes != null) {
attributes.forEach(consumer);
Expand All @@ -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);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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.
* <p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@
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;

@Getter
@Setter
@Component
@ImportResource("classpath:sofa-rpc.xml")
@ConfigurationProperties(prefix = "live")
public class LiveConfig {

Expand Down
Original file line number Diff line number Diff line change
@@ -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<GenericObject> {

@Override
public void serialize(GenericObject person, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeStartObject();
if (person.getFields() != null) {
for (Map.Entry<String, Object> entry : person.getFields().entrySet()) {
gen.writeObjectField(entry.getKey(), entry.getValue());
}
}
gen.writeEndObject();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -56,6 +57,9 @@ public class ConsumerService implements ApplicationListener<ApplicationReadyEven
binding = @SofaReferenceBinding(bindingType = "bolt"))
private HelloService helloService;

@Resource
private GenericService genericService;


@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
Expand All @@ -73,20 +77,26 @@ private void invoke() {
long status = 0;
while (!Thread.currentThread().isInterrupted()) {
try {
int remain = (int) (counter++ % 2);
int remain = (int) (counter++ % 4);
switch (remain) {
case 0:
doEcho(context);
break;
case 1:
doGenericEcho(context);
break;
case 2:
doGenericStatus(context);
break;
default:
doStatus(context, (status++ % 20) == 0 ? 200 : 500);
break;
}
} catch (Throwable e) {
logger.error(e.getMessage(), e);
}
try {
countDownLatch.await(1000L, TimeUnit.MILLISECONDS);
countDownLatch.await(300L, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
Expand All @@ -95,9 +105,12 @@ private void invoke() {
}

private void doStatus(RpcInvokeContext attachment, int code) {
LiveResponse result = helloService.status(code);
addTrace(attachment, result);
output("Invoke status: \n{}", result);
Object result = genericService.$genericInvoke("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(RpcInvokeContext attachment) {
Expand All @@ -106,6 +119,24 @@ private void doEcho(RpcInvokeContext attachment) {
output("Invoke result: \n{}", result);
}

private void doGenericEcho(RpcInvokeContext attachment) {
Object result = genericService.$genericInvoke("echo",
new String[]{"java.lang.String"},
new Object[]{"hello"});
LiveResponse response = objectMapper.convertValue(result, LiveResponse.class);
addTrace(attachment, response);
output("Generic invoke result: \n{}", response);
}

private void doGenericStatus(RpcInvokeContext attachment) {
Object result = genericService.$invoke("echo",
new String[]{"java.lang.String"},
new Object[]{"hello"});
LiveResponse response = objectMapper.convertValue(result, LiveResponse.class);
addTrace(attachment, response);
output("Generic invoke result: \n{}", response);
}


private void addTrace(RpcInvokeContext context, LiveResponse result) {
result.addFirst(new LiveTrace(applicationName, LiveLocation.build(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ spring:
default-property-inclusion: non_null
serialization:
indent_output: true

live:
live-space-id: v4bEh4kd6Jvu5QBX09qYq-qlbcs
rule-id: 1003
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sofa="http://sofastack.io/schema/sofaboot"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://sofastack.io/schema/sofaboot http://sofastack.io/schema/sofaboot.xsd">
<sofa:reference id="genericService" jvm-first="false" interface="com.alipay.sofa.rpc.api.GenericService">
<sofa:binding.bolt>
<sofa:global-attrs generic-interface="com.jd.live.agent.demo.service.HelloService"/>
</sofa:binding.bolt>
</sofa:reference>
</beans>
3 changes: 0 additions & 3 deletions joylive-package/src/main/assembly/config/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
Loading
Loading