fix: tsf related bugfixes

pull/1698/head
shedfreewu 2 months ago committed by Haotian Zhang
parent 3cb0c07121
commit 71d54f3778

@ -16,7 +16,7 @@ header:
CONDITIONS OF ANY KIND, either express or implied. See the License for the CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License. specific language governing permissions and limitations under the License.
paths: paths:
- "**/tencent/**" - "**/*.java"
language: language:
Java: Java:
extensions: extensions:

@ -5,4 +5,5 @@
- [fix: fix ConfigChangeListener and unit test](https://github.com/Tencent/spring-cloud-tencent/pull/1654) - [fix: fix ConfigChangeListener and unit test](https://github.com/Tencent/spring-cloud-tencent/pull/1654)
- [feat: support spring-retry and feign config refresh and feign eager load support schema](https://github.com/Tencent/spring-cloud-tencent/pull/1649) - [feat: support spring-retry and feign config refresh and feign eager load support schema](https://github.com/Tencent/spring-cloud-tencent/pull/1649)
- [fix: fix ConfigChangeListener ut bug](https://github.com/Tencent/spring-cloud-tencent/pull/1659) - [fix: fix ConfigChangeListener ut bug](https://github.com/Tencent/spring-cloud-tencent/pull/1659)
- [feat: support tsf gw.](https://github.com/Tencent/spring-cloud-tencent/pull/1696) - [feat: support tsf gw.](https://github.com/Tencent/spring-cloud-tencent/pull/1697)
- [fix: tsf related bugfixes](https://github.com/Tencent/spring-cloud-tencent/pull/1698)

@ -17,32 +17,20 @@
package com.tencent.cloud.metadata.config; package com.tencent.cloud.metadata.config;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.tencent.cloud.common.constant.OrderConstant; import com.tencent.cloud.common.constant.OrderConstant;
import com.tencent.cloud.metadata.core.DecodeTransferMetadataReactiveFilter; import com.tencent.cloud.metadata.core.DecodeTransferMetadataReactiveFilter;
import com.tencent.cloud.metadata.core.DecodeTransferMetadataServletFilter; import com.tencent.cloud.metadata.core.DecodeTransferMetadataServletFilter;
import com.tencent.cloud.metadata.core.EncodeTransferMedataFeignEnhancedPlugin; import com.tencent.cloud.metadata.core.EncodeTransferMedataFeignEnhancedPlugin;
import com.tencent.cloud.metadata.core.EncodeTransferMedataRestTemplateInterceptor; import com.tencent.cloud.metadata.core.EncodeTransferMedataRestTemplateEnhancedPlugin;
import com.tencent.cloud.metadata.core.EncodeTransferMedataScgEnhancedPlugin; import com.tencent.cloud.metadata.core.EncodeTransferMedataScgEnhancedPlugin;
import com.tencent.cloud.metadata.core.EncodeTransferMedataWebClientEnhancedPlugin; import com.tencent.cloud.metadata.core.EncodeTransferMedataWebClientEnhancedPlugin;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor;
import org.springframework.cloud.client.loadbalancer.RestTemplateCustomizer;
import org.springframework.cloud.client.loadbalancer.RetryLoadBalancerInterceptor;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;
import static javax.servlet.DispatcherType.ASYNC; import static javax.servlet.DispatcherType.ASYNC;
import static javax.servlet.DispatcherType.ERROR; import static javax.servlet.DispatcherType.ERROR;
@ -130,59 +118,9 @@ public class MetadataTransferAutoConfiguration {
@ConditionalOnProperty(value = "spring.cloud.tencent.rpc-enhancement.enabled", havingValue = "true", matchIfMissing = true) @ConditionalOnProperty(value = "spring.cloud.tencent.rpc-enhancement.enabled", havingValue = "true", matchIfMissing = true)
protected static class MetadataTransferRestTemplateConfig { protected static class MetadataTransferRestTemplateConfig {
@Autowired(required = false)
private List<RestTemplate> restTemplates = Collections.emptyList();
@Bean
public EncodeTransferMedataRestTemplateInterceptor encodeTransferMedataRestTemplateInterceptor() {
return new EncodeTransferMedataRestTemplateInterceptor();
}
@Bean
public SmartInitializingSingleton addEncodeTransferMetadataInterceptorForRestTemplate(EncodeTransferMedataRestTemplateInterceptor interceptor) {
return () -> restTemplates.forEach(restTemplate -> {
List<ClientHttpRequestInterceptor> list = new ArrayList<>(restTemplate.getInterceptors());
list.add(interceptor);
restTemplate.setInterceptors(list);
});
}
@Bean @Bean
public RestTemplateCustomizer polarisRestTemplateCustomizer( public EncodeTransferMedataRestTemplateEnhancedPlugin encodeTransferMedataRestTemplateEnhancedPlugin() {
@Autowired(required = false) RetryLoadBalancerInterceptor retryLoadBalancerInterceptor, return new EncodeTransferMedataRestTemplateEnhancedPlugin();
@Autowired(required = false) LoadBalancerInterceptor loadBalancerInterceptor) {
return restTemplate -> {
List<ClientHttpRequestInterceptor> list = new ArrayList<>(restTemplate.getInterceptors());
// LoadBalancerInterceptor must invoke before EncodeTransferMedataRestTemplateInterceptor
int addIndex = list.size();
if (CollectionUtils.containsInstance(list, retryLoadBalancerInterceptor) || CollectionUtils.containsInstance(list, loadBalancerInterceptor)) {
ClientHttpRequestInterceptor enhancedRestTemplateInterceptor = null;
for (int i = 0; i < list.size(); i++) {
if (list.get(i) instanceof EncodeTransferMedataRestTemplateInterceptor) {
enhancedRestTemplateInterceptor = list.get(i);
addIndex = i;
}
}
if (enhancedRestTemplateInterceptor != null) {
list.remove(addIndex);
list.add(enhancedRestTemplateInterceptor);
}
}
else {
if (retryLoadBalancerInterceptor != null || loadBalancerInterceptor != null) {
for (int i = 0; i < list.size(); i++) {
if (list.get(i) instanceof EncodeTransferMedataRestTemplateInterceptor) {
addIndex = i;
}
}
list.add(addIndex,
retryLoadBalancerInterceptor != null
? retryLoadBalancerInterceptor
: loadBalancerInterceptor);
}
}
restTemplate.setInterceptors(list);
};
} }
} }

@ -17,27 +17,23 @@
package com.tencent.cloud.metadata.core; package com.tencent.cloud.metadata.core;
import java.io.IOException;
import java.util.Map; import java.util.Map;
import com.tencent.cloud.common.constant.OrderConstant;
import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder; import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.tsf.TsfContextUtils; import com.tencent.cloud.common.tsf.TsfContextUtils;
import com.tencent.cloud.common.util.JacksonUtils; import com.tencent.cloud.common.util.JacksonUtils;
import com.tencent.cloud.common.util.TsfTagUtils; import com.tencent.cloud.common.util.TsfTagUtils;
import com.tencent.cloud.common.util.UrlUtils; import com.tencent.cloud.common.util.UrlUtils;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant;
import com.tencent.polaris.metadata.core.MessageMetadataContainer; import com.tencent.polaris.metadata.core.MessageMetadataContainer;
import com.tencent.polaris.metadata.core.MetadataType; import com.tencent.polaris.metadata.core.MetadataType;
import shade.polaris.com.google.common.collect.ImmutableMap; import shade.polaris.com.google.common.collect.ImmutableMap;
import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor;
import org.springframework.core.Ordered;
import org.springframework.http.HttpRequest; import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.lang.NonNull;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.APPLICATION_METADATA; import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.APPLICATION_METADATA;
@ -45,23 +41,23 @@ import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUST
import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_METADATA; import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_METADATA;
/** /**
* Interceptor used for adding the metadata in http headers from context when web client * Pre EnhancedPlugin for rest template to encode transfer metadata.
* is RestTemplate.
* *
* It needs to execute after {@link LoadBalancerInterceptor}, because LaneRouter may add calleeTransitiveHeaders. * @author Shedfree Wu
*
* @author Haotian Zhang
*/ */
public class EncodeTransferMedataRestTemplateInterceptor implements ClientHttpRequestInterceptor, Ordered { public class EncodeTransferMedataRestTemplateEnhancedPlugin implements EnhancedPlugin {
@Override @Override
public int getOrder() { public EnhancedPluginType getType() {
return OrderConstant.Client.RestTemplate.ENCODE_TRANSFER_METADATA_INTERCEPTOR_ORDER; return EnhancedPluginType.Client.BEFORE_CALLING;
} }
@Override @Override
public ClientHttpResponse intercept(@NonNull HttpRequest httpRequest, @NonNull byte[] bytes, public void run(EnhancedPluginContext context) throws Throwable {
@NonNull ClientHttpRequestExecution clientHttpRequestExecution) throws IOException { if (!(context.getOriginRequest() instanceof HttpRequest)) {
return;
}
HttpRequest httpRequest = (HttpRequest) context.getOriginRequest();
// get metadata of current thread // get metadata of current thread
MetadataContext metadataContext = MetadataContextHolder.get(); MetadataContext metadataContext = MetadataContextHolder.get();
Map<String, String> customMetadata = metadataContext.getCustomMetadata(); Map<String, String> customMetadata = metadataContext.getCustomMetadata();
@ -91,8 +87,6 @@ public class EncodeTransferMedataRestTemplateInterceptor implements ClientHttpRe
} }
// set headers that need to be transmitted from the upstream // set headers that need to be transmitted from the upstream
this.buildTransmittedHeader(httpRequest, transHeaders); this.buildTransmittedHeader(httpRequest, transHeaders);
return clientHttpRequestExecution.execute(httpRequest, bytes);
} }
private void buildTransmittedHeader(HttpRequest request, Map<String, String> transHeaders) { private void buildTransmittedHeader(HttpRequest request, Map<String, String> transHeaders) {
@ -121,4 +115,9 @@ public class EncodeTransferMedataRestTemplateInterceptor implements ClientHttpRe
buildHeaderMap(request, ImmutableMap.of(headerName, JacksonUtils.serialize2Json(metadata))); buildHeaderMap(request, ImmutableMap.of(headerName, JacksonUtils.serialize2Json(metadata)));
} }
} }
@Override
public int getOrder() {
return PluginOrderConstant.ClientPluginOrder.CONSUMER_TRANSFER_METADATA_PLUGIN_ORDER;
}
} }

@ -22,6 +22,7 @@ import java.util.Map;
import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder; import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.rpc.enhancement.instrument.resttemplate.EnhancedRestTemplateInterceptor;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
@ -43,16 +44,16 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
/** /**
* Test for {@link EncodeTransferMedataRestTemplateInterceptor}. * Test for {@link EnhancedRestTemplateInterceptor}.
* *
* @author Haotian Zhang * @author Haotian Zhang
*/ */
@ExtendWith(SpringExtension.class) @ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = RANDOM_PORT, @SpringBootTest(webEnvironment = RANDOM_PORT,
classes = EncodeTransferMedataRestTemplateInterceptorTest.TestApplication.class, classes = EnhancedRestTemplateInterceptorTest.TestApplication.class,
properties = {"spring.config.location = classpath:application-test.yml", properties = {"spring.config.location = classpath:application-test.yml",
"spring.main.web-application-type = reactive"}) "spring.main.web-application-type = reactive"})
public class EncodeTransferMedataRestTemplateInterceptorTest { public class EnhancedRestTemplateInterceptorTest {
@Autowired @Autowired
private RestTemplate restTemplate; private RestTemplate restTemplate;

@ -65,7 +65,7 @@ public final class ConsulDiscoveryUtil {
if (StringUtils.isNotBlank(appName)) { if (StringUtils.isNotBlank(appName)) {
return appName; return appName;
} }
return env.getProperty("spring.application.name", "application"); return env.getProperty("spring.application.name");
} }
public static String getInstanceId(ConsulDiscoveryProperties properties, ApplicationContext context) { public static String getInstanceId(ConsulDiscoveryProperties properties, ApplicationContext context) {

@ -25,6 +25,7 @@ import java.util.concurrent.ScheduledExecutorService;
import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.StaticMetadataManager; import com.tencent.cloud.common.metadata.StaticMetadataManager;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.common.util.OkHttpUtil; import com.tencent.cloud.common.util.OkHttpUtil;
import com.tencent.cloud.common.util.OtUtils; import com.tencent.cloud.common.util.OtUtils;
import com.tencent.cloud.polaris.PolarisDiscoveryProperties; import com.tencent.cloud.polaris.PolarisDiscoveryProperties;
@ -101,13 +102,18 @@ public class PolarisServiceRegistry implements ServiceRegistry<PolarisRegistrati
@Override @Override
public void register(PolarisRegistration registration) { public void register(PolarisRegistration registration) {
if (StringUtils.isBlank(registration.getServiceId())) { String serviceId = registration.getServiceId();
if (StringUtils.isBlank(serviceId)) {
serviceId = ApplicationContextAwareUtils.getProperties("spring.application.name");
}
if (StringUtils.isBlank(serviceId)) {
LOGGER.warn("No service to register for polaris client..."); LOGGER.warn("No service to register for polaris client...");
return; return;
} }
registration.customize(); registration.customize();
String serviceId = registration.getServiceId();
MetadataContext.setLocalService(serviceId); MetadataContext.setLocalService(serviceId);
MetadataContext.setLocalNamespace(polarisDiscoveryProperties.getNamespace());
// Register instance. // Register instance.
InstanceRegisterRequest instanceRegisterRequest = new InstanceRegisterRequest(); InstanceRegisterRequest instanceRegisterRequest = new InstanceRegisterRequest();

@ -76,6 +76,8 @@ public class RouterUtilsTest {
mockedMetadataContextHolder.when(MetadataContextHolder::get).thenReturn(metadataContext); mockedMetadataContextHolder.when(MetadataContextHolder::get).thenReturn(metadataContext);
Mockito.when(metadataContext.getContext(anyString(), anyString(), anyString())) Mockito.when(metadataContext.getContext(anyString(), anyString(), anyString()))
.thenReturn(testNamespaceAndService); .thenReturn(testNamespaceAndService);
Mockito.when(metadataContext.getContext(anyString(), anyString()))
.thenReturn(testNamespaceAndService);
int instanceSize = 100; int instanceSize = 100;
int weight = 50; int weight = 50;

@ -40,6 +40,14 @@ public final class ContextConstant {
* Default registry heartbeat time interval: 5 (s). * Default registry heartbeat time interval: 5 (s).
*/ */
public static final Integer DEFAULT_REGISTRY_HEARTBEAT_TIME_INTERVAL = 5; public static final Integer DEFAULT_REGISTRY_HEARTBEAT_TIME_INTERVAL = 5;
/**
* ENHANCED_PLUGIN_CONTEXT.
*/
public static final String ENHANCED_PLUGIN_CONTEXT = "ENHANCED_PLUGIN_CONTEXT";
/**
* LANE_TAG.
*/
public static final String LANE_TAG = "LANE_TAG";
private ContextConstant() { private ContextConstant() {
} }
@ -62,4 +70,15 @@ public final class ContextConstant {
} }
} }
public static final class Trace {
/**
* EXTRA_TRACE_ATTRIBUTES.
*/
public static final String EXTRA_TRACE_ATTRIBUTES = "EXTRA_TRACE_ATTRIBUTES";
private Trace() {
}
}
} }

@ -49,14 +49,14 @@ public class OrderConstant {
*/ */
public static class RestTemplate { public static class RestTemplate {
/** /**
* Order of encode transfer metadata interceptor. * Order of encode enhance interceptor.
*/ */
public static final int ENCODE_TRANSFER_METADATA_INTERCEPTOR_ORDER = Ordered.LOWEST_PRECEDENCE; public static final int ENHANCE_INTERCEPTOR_ORDER = Ordered.LOWEST_PRECEDENCE;
/** /**
* Order of encode router label interceptor. * Order of encode router label interceptor.
*/ */
public static final int ROUTER_LABEL_INTERCEPTOR_ORDER = Ordered.LOWEST_PRECEDENCE; public static final int ROUTER_LABEL_INTERCEPTOR_ORDER = 0;
} }
/** /**

@ -133,6 +133,10 @@ public class MetadataContext extends com.tencent.polaris.metadata.core.manager.M
LOCAL_SERVICE = service; LOCAL_SERVICE = service;
} }
public static void setLocalNamespace(String namespace) {
LOCAL_NAMESPACE = namespace;
}
private Map<String, String> getMetadataAsMap(MetadataType metadataType, TransitiveType transitiveType, boolean caller) { private Map<String, String> getMetadataAsMap(MetadataType metadataType, TransitiveType transitiveType, boolean caller) {
MetadataContainer metadataContainer = getMetadataContainer(metadataType, caller); MetadataContainer metadataContainer = getMetadataContainer(metadataType, caller);
Map<String, String> values = new HashMap<>(); Map<String, String> values = new HashMap<>();

@ -0,0 +1,49 @@
/*
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
*
* Copyright (C) 2021 Tencent. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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.tencent.cloud.common.util;
import java.util.Optional;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.polaris.metadata.core.MetadataObjectValue;
import com.tencent.polaris.metadata.core.MetadataType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Utils for MetadataContext.
*
* @author Shedfree Wu
*/
public final class MetadataContextUtils {
private static final Logger LOG = LoggerFactory.getLogger(MetadataContextUtils.class);
private MetadataContextUtils() {
}
public static void putMetadataObjectValue(String key, Object value) {
MetadataContextHolder.get().getMetadataContainer(MetadataType.APPLICATION, true).
putMetadataObjectValue(key, value);
}
public static boolean existMetadataValue(MetadataObjectValue<?> metadataObjectValue) {
return Optional.ofNullable(metadataObjectValue).map(MetadataObjectValue::getObjectValue).
map(Optional::isPresent).orElse(false);
}
}

@ -27,6 +27,7 @@ import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import com.tencent.cloud.common.constant.ContextConstant;
import com.tencent.cloud.common.constant.MetadataConstant; import com.tencent.cloud.common.constant.MetadataConstant;
import com.tencent.cloud.common.tsf.TsfContextUtils; import com.tencent.cloud.common.tsf.TsfContextUtils;
import com.tencent.polaris.api.utils.CollectionUtils; import com.tencent.polaris.api.utils.CollectionUtils;
@ -114,6 +115,7 @@ public final class TsfTagUtils {
if (laneTag != null) { if (laneTag != null) {
tsfSystemTags.add(laneTag); tsfSystemTags.add(laneTag);
MetadataContextUtils.putMetadataObjectValue(ContextConstant.LANE_TAG, laneTag);
} }
if (CollectionUtils.isNotEmpty(tsfUserTags)) { if (CollectionUtils.isNotEmpty(tsfUserTags)) {

@ -28,9 +28,11 @@ import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import com.tencent.cloud.common.constant.ContextConstant;
import com.tencent.cloud.common.constant.MetadataConstant; import com.tencent.cloud.common.constant.MetadataConstant;
import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder; import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.util.MetadataContextUtils;
import com.tencent.polaris.api.utils.CollectionUtils; import com.tencent.polaris.api.utils.CollectionUtils;
import com.tencent.polaris.api.utils.StringUtils; import com.tencent.polaris.api.utils.StringUtils;
import com.tencent.tsf.gateway.core.TsfGatewayRequest; import com.tencent.tsf.gateway.core.TsfGatewayRequest;
@ -240,6 +242,7 @@ public class ContextGatewayFilter implements GatewayFilter, Ordered {
throw NotFoundException.create(true, msg); throw NotFoundException.create(true, msg);
} }
updateRouteMetadata(exchange, contextRoute); updateRouteMetadata(exchange, contextRoute);
setTraceAttributes(contextRoute, GatewayConstant.NON_UNIT_TYPE, GatewayConstant.NON_UNIT_TRANSFER_TYPE);
exchange.getAttributes().put(GatewayConstant.CONTEXT_ROUTE, contextRoute); exchange.getAttributes().put(GatewayConstant.CONTEXT_ROUTE, contextRoute);
URI requestUri = URI.create(contextRoute.getHost() + apis[1]); URI requestUri = URI.create(contextRoute.getHost() + apis[1]);
@ -261,6 +264,7 @@ public class ContextGatewayFilter implements GatewayFilter, Ordered {
throw NotFoundException.create(true, msg); throw NotFoundException.create(true, msg);
} }
updateRouteMetadata(exchange, contextRoute); updateRouteMetadata(exchange, contextRoute);
setTraceAttributes(contextRoute, GatewayConstant.NON_UNIT_TYPE, GatewayConstant.NON_UNIT_TRANSFER_TYPE);
exchange.getAttributes().put(GatewayConstant.CONTEXT_ROUTE, contextRoute); exchange.getAttributes().put(GatewayConstant.CONTEXT_ROUTE, contextRoute);
MetadataContext metadataContext = exchange.getAttribute( MetadataContext metadataContext = exchange.getAttribute(
@ -494,4 +498,22 @@ public class ContextGatewayFilter implements GatewayFilter, Ordered {
throw new IllegalStateException("Invalid URI query: \"" + query + "\""); throw new IllegalStateException("Invalid URI query: \"" + query + "\"");
} }
} }
private void setTraceAttributes(GroupContext.ContextRoute contextRoute, String unitType, String unitTransferType) {
Map<String, String> traceAttributes = new HashMap<>();
traceAttributes.put("tsf-ms-type", "MSGW");
traceAttributes.put("tsf-unit-type", unitType);
traceAttributes.put("tsf-unit-transfer-type", unitTransferType);
traceAttributes.put("destination.namespace-id", contextRoute.getNamespaceId());
traceAttributes.put("tsf-msgw-group", config.getGroup());
traceAttributes.put("tsf-msgw-groupApi", contextRoute.getApiId());
traceAttributes.put("tsf-msgw-apiPath", contextRoute.getPath());
traceAttributes.put("tsf-msgw-apiMethod", contextRoute.getMethod());
traceAttributes.put("tsf-msgw-namespaceName", contextRoute.getNamespace());
traceAttributes.put("tsf-msgw-serviceName", contextRoute.getService());
traceAttributes.put("localComponent", "msgw");
MetadataContextUtils.putMetadataObjectValue(ContextConstant.Trace.EXTRA_TRACE_ATTRIBUTES, traceAttributes);
}
} }

@ -18,8 +18,10 @@
package com.tencent.cloud.plugin.gateway.context; package com.tencent.cloud.plugin.gateway.context;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
import java.net.URI; import java.net.URI;
import java.util.ArrayList; import java.util.ArrayList;
@ -63,6 +65,7 @@ import com.tencent.tsf.gateway.core.model.PathWildcardRule;
import com.tencent.tsf.gateway.core.model.PluginInstanceInfoResult; import com.tencent.tsf.gateway.core.model.PluginInstanceInfoResult;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import shade.polaris.org.apache.commons.io.IOUtils;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent; import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.filter.FilterDefinition; import org.springframework.cloud.gateway.filter.FilterDefinition;
@ -126,6 +129,10 @@ public class GatewayConsulRepo {
if (listResponse.getValue() != null) { if (listResponse.getValue() != null) {
refreshGatewayGroupConfig(parseGroupResponse(listResponse)); refreshGatewayGroupConfig(parseGroupResponse(listResponse));
} }
else {
logger.info("try to load gateway group config from local file.");
refreshGatewayGroupConfig(loadResponseFromFile());
}
scheduledExecutorService.scheduleAtFixedRate(() -> { scheduledExecutorService.scheduleAtFixedRate(() -> {
try { try {
@ -257,6 +264,35 @@ public class GatewayConsulRepo {
} }
private GatewayAllResult loadResponseFromFile() {
GroupResult groupResult = (GroupResult) readLocalRepo(GatewayConstant.GROUP_FILE_NAME, GroupResult.class);
GroupApiResult groupApiResult = (GroupApiResult) readLocalRepo(GatewayConstant.API_FILE_NAME, GroupApiResult.class);
PathRewriteResult pathRewriteResult = (PathRewriteResult) readLocalRepo(GatewayConstant.PATH_REWRITE_FILE_NAME, PathRewriteResult.class);
PathWildcardResult pathWildcardResult = (PathWildcardResult) readLocalRepo(GatewayConstant.PATH_WILDCARD_FILE_NAME, PathWildcardResult.class);
return new GatewayAllResult(groupResult, groupApiResult, pathRewriteResult, pathWildcardResult);
}
private Object readLocalRepo(String type, Class<?> repoResultClazz) {
byte[] bytes;
try (FileInputStream fin = new FileInputStream(getRepoStoreFile(type)); InputStreamReader isr = new InputStreamReader(fin)) {
bytes = IOUtils.toByteArray(isr, "utf-8");
if (bytes == null || bytes.length == 0) {
return null;
}
}
catch (IOException t) {
logger.warn("[readLocalRepo] read group info from file occur exception: {}", t.getMessage());
return null;
}
try {
return JacksonUtils.deserialize(new String(bytes, "utf-8"), repoResultClazz);
}
catch (Throwable t) {
logger.warn("[readLocalRepo] json serialize data to group occur exception: {}", t.getMessage());
return null;
}
}
private GatewayAllResult parseGroupResponse(Response<List<GetValue>> listResponse) { private GatewayAllResult parseGroupResponse(Response<List<GetValue>> listResponse) {
GroupResult groupResult = null; GroupResult groupResult = null;
GroupApiResult groupApiResult = new GroupApiResult(); GroupApiResult groupApiResult = new GroupApiResult();
@ -362,30 +398,32 @@ public class GatewayConsulRepo {
} }
} }
for (GroupApi groupApi : groupApiResult.getResult()) { if (groupApiResult != null) {
GroupContext groupContext = groups.get(groupApi.getGroupId()); for (GroupApi groupApi : groupApiResult.getResult()) {
if (groupContext == null) { GroupContext groupContext = groups.get(groupApi.getGroupId());
if (logger.isDebugEnabled()) { if (groupContext == null) {
logger.debug("group api {} not found in group {}", groupApi.getApiId(), groupApi.getGroupId()); if (logger.isDebugEnabled()) {
logger.debug("group api {} not found in group {}", groupApi.getApiId(), groupApi.getGroupId());
}
continue;
} }
continue;
}
GroupContext.ContextRoute contextRoute = new GroupContext.ContextRoute(); GroupContext.ContextRoute contextRoute = new GroupContext.ContextRoute();
contextRoute.setApiId(groupApi.getApiId()); contextRoute.setApiId(groupApi.getApiId());
contextRoute.setHost(groupApi.getHost()); contextRoute.setHost(groupApi.getHost());
contextRoute.setPath(groupApi.getPath()); contextRoute.setPath(groupApi.getPath());
contextRoute.setPathMapping(groupApi.getPathMapping()); contextRoute.setPathMapping(groupApi.getPathMapping());
contextRoute.setMethod(groupApi.getMethod()); contextRoute.setMethod(groupApi.getMethod());
contextRoute.setService(groupApi.getServiceName()); contextRoute.setService(groupApi.getServiceName());
contextRoute.setNamespaceId(groupApi.getNamespaceId()); contextRoute.setNamespaceId(groupApi.getNamespaceId());
contextRoute.setNamespace(groupApi.getNamespaceName()); contextRoute.setNamespace(groupApi.getNamespaceName());
if (groupApi.getTimeout() != null) { if (groupApi.getTimeout() != null) {
Map<String, String> metadata = new HashMap<>(); Map<String, String> metadata = new HashMap<>();
metadata.put("response-timeout", String.valueOf(groupApi.getTimeout())); metadata.put("response-timeout", String.valueOf(groupApi.getTimeout()));
contextRoute.setMetadata(metadata); contextRoute.setMetadata(metadata);
}
groupContext.getRoutes().add(contextRoute);
} }
groupContext.getRoutes().add(contextRoute);
} }
if (pathWildcardResult != null && pathWildcardResult.getResult() != null) { if (pathWildcardResult != null && pathWildcardResult.getResult() != null) {
@ -410,7 +448,7 @@ public class GatewayConsulRepo {
contextGatewayProperties.setGroups(groups); contextGatewayProperties.setGroups(groups);
contextGatewayProperties.setRoutes(routes); contextGatewayProperties.setRoutes(routes);
contextGatewayProperties.setPathRewrites(Optional.ofNullable(pathRewriteResult.getResult()) contextGatewayProperties.setPathRewrites(Optional.ofNullable(pathRewriteResult).map(PathRewriteResult::getResult)
.orElse(new ArrayList<>())); .orElse(new ArrayList<>()));
logger.debug("Gateway config loaded. :{}", JacksonUtils.serialize2Json(contextGatewayProperties)); logger.debug("Gateway config loaded. :{}", JacksonUtils.serialize2Json(contextGatewayProperties));

@ -74,6 +74,22 @@ public final class GatewayConstant {
* Gateway . * Gateway .
*/ */
public static final String GATEWAY_REPO_PREFIX = GATEWAY_REPO_ROOT + "/tsf/gateway/"; public static final String GATEWAY_REPO_PREFIX = GATEWAY_REPO_ROOT + "/tsf/gateway/";
/**
* NON_UNIT_TYPE.
*/
public static final String NON_UNIT_TYPE = "non-unit";
/**
* NON_UNIT_TRANSFER_TYPE.
*/
public static final String NON_UNIT_TRANSFER_TYPE = "non-unit";
/**
* UNIT_TYPE.
*/
public static final String UNIT_TYPE = "unit";
/**
* UNIT_TRANSFER_TYPE.
*/
public static final String UNIT_TRANSFER_TYPE = "ms_unit_proxy";
private GatewayConstant() { private GatewayConstant() {

@ -28,6 +28,7 @@ import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.util.JacksonUtils; import com.tencent.cloud.common.util.JacksonUtils;
import com.tencent.cloud.plugin.gateway.context.Position; import com.tencent.cloud.plugin.gateway.context.Position;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager; import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import com.tencent.polaris.api.utils.ClassUtils;
import com.tencent.polaris.api.utils.StringUtils; import com.tencent.polaris.api.utils.StringUtils;
import com.tencent.polaris.assembly.api.AssemblyAPI; import com.tencent.polaris.assembly.api.AssemblyAPI;
import com.tencent.polaris.assembly.api.pojo.TraceAttributes; import com.tencent.polaris.assembly.api.pojo.TraceAttributes;
@ -39,6 +40,7 @@ import com.tencent.tsf.gateway.core.http.HttpConnectionPoolUtil;
import com.tencent.tsf.gateway.core.model.OAuthPlugin; import com.tencent.tsf.gateway.core.model.OAuthPlugin;
import com.tencent.tsf.gateway.core.model.OAuthResult; import com.tencent.tsf.gateway.core.model.OAuthResult;
import com.tencent.tsf.gateway.core.model.PluginPayload; import com.tencent.tsf.gateway.core.model.PluginPayload;
import io.opentelemetry.context.Scope;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -196,7 +198,7 @@ public class OAuthGatewayPlugin implements IGatewayPlugin<OAuthPlugin> {
throw new TsfGatewayException(TsfGatewayError.GATEWAY_REQUEST_NOT_FOUND, "Unable to find instance for " + pluginInfo.getTokenAuthServiceName()); throw new TsfGatewayException(TsfGatewayError.GATEWAY_REQUEST_NOT_FOUND, "Unable to find instance for " + pluginInfo.getTokenAuthServiceName());
} }
fillTracingContext(namespace, serviceName); Object otScope = fillTracingContext(namespace, serviceName);
String newRequestUrl = uri.getScheme() + "://" + GATEWAY_WILDCARD_SERVICE_NAME + tokenAuthUrl; String newRequestUrl = uri.getScheme() + "://" + GATEWAY_WILDCARD_SERVICE_NAME + tokenAuthUrl;
URI newUri = new URI(newRequestUrl); URI newUri = new URI(newRequestUrl);
@ -204,7 +206,12 @@ public class OAuthGatewayPlugin implements IGatewayPlugin<OAuthPlugin> {
// http://127.0.0.1:8080/group1/namespace1/Consumer-demo/echo-rest/1?user=1 // http://127.0.0.1:8080/group1/namespace1/Consumer-demo/echo-rest/1?user=1
URI requestUrl = this.reconstructURI(new OauthDelegatingServiceInstance(instance.getServer()), newUri); URI requestUrl = this.reconstructURI(new OauthDelegatingServiceInstance(instance.getServer()), newUri);
logger.debug("LoadBalancerClientFilter url chosen: " + requestUrl); logger.debug("LoadBalancerClientFilter url chosen: " + requestUrl);
return sendAuthRequestByHttpMethod(paramsMap, headerParamsMap, requestUrl.toASCIIString(), tokenAuthMethod, timeout); String result = sendAuthRequestByHttpMethod(paramsMap, headerParamsMap, requestUrl.toASCIIString(), tokenAuthMethod, timeout);
if (ClassUtils.isClassPresent("io.opentelemetry.context.Scope") && otScope instanceof Scope) {
((Scope) otScope).close();
}
return result;
} }
catch (Exception e) { catch (Exception e) {
logger.error("MicroService {} Request Auth Server Error", tokenAuthMethod, e); logger.error("MicroService {} Request Auth Server Error", tokenAuthMethod, e);
@ -244,7 +251,7 @@ public class OAuthGatewayPlugin implements IGatewayPlugin<OAuthPlugin> {
} }
} }
void fillTracingContext(String namespace, String serviceName) { Object fillTracingContext(String namespace, String serviceName) {
Map<String, String> attributes = new HashMap<>(); Map<String, String> attributes = new HashMap<>();
attributes.put("net.peer.service", serviceName); attributes.put("net.peer.service", serviceName);
@ -256,6 +263,8 @@ public class OAuthGatewayPlugin implements IGatewayPlugin<OAuthPlugin> {
AssemblyAPI assemblyAPI = polarisSDKContextManager.getAssemblyAPI(); AssemblyAPI assemblyAPI = polarisSDKContextManager.getAssemblyAPI();
assemblyAPI.updateTraceAttributes(traceAttributes); assemblyAPI.updateTraceAttributes(traceAttributes);
return traceAttributes.getOtScope();
} }
class OauthDelegatingServiceInstance implements ServiceInstance { class OauthDelegatingServiceInstance implements ServiceInstance {

@ -44,7 +44,7 @@ public class TraceClientPreEnhancedPlugin implements EnhancedPlugin {
@Override @Override
public EnhancedPluginType getType() { public EnhancedPluginType getType() {
return EnhancedPluginType.Client.PRE; return EnhancedPluginType.Client.BEFORE_CALLING;
} }
@Override @Override

@ -0,0 +1,74 @@
/*
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
*
* Copyright (C) 2021 Tencent. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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.tencent.cloud.plugin.trace;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.tencent.cloud.plugin.trace.attribute.SpanAttributesProvider;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant;
import com.tencent.polaris.api.utils.CollectionUtils;
import com.tencent.polaris.assembly.api.AssemblyAPI;
import com.tencent.polaris.assembly.api.pojo.TraceAttributes;
public class TraceServerFinallyEnhancedPlugin implements EnhancedPlugin {
private final PolarisSDKContextManager polarisSDKContextManager;
private final List<SpanAttributesProvider> spanAttributesProviderList;
public TraceServerFinallyEnhancedPlugin(PolarisSDKContextManager polarisSDKContextManager, List<SpanAttributesProvider> spanAttributesProviderList) {
this.polarisSDKContextManager = polarisSDKContextManager;
this.spanAttributesProviderList = spanAttributesProviderList;
}
@Override
public EnhancedPluginType getType() {
return EnhancedPluginType.Server.FINALLY;
}
@Override
public void run(EnhancedPluginContext context) throws Throwable {
Map<String, String> attributes = new HashMap<>();
if (CollectionUtils.isNotEmpty(spanAttributesProviderList)) {
for (SpanAttributesProvider spanAttributesProvider : spanAttributesProviderList) {
Map<String, String> additionalAttributes = spanAttributesProvider.getServerFinallySpanAttributes(context);
if (CollectionUtils.isNotEmpty(additionalAttributes)) {
attributes.putAll(additionalAttributes);
}
}
}
TraceAttributes traceAttributes = new TraceAttributes();
traceAttributes.setAttributes(attributes);
traceAttributes.setAttributeLocation(TraceAttributes.AttributeLocation.SPAN);
AssemblyAPI assemblyAPI = polarisSDKContextManager.getAssemblyAPI();
assemblyAPI.updateTraceAttributes(traceAttributes);
}
@Override
public int getOrder() {
return PluginOrderConstant.ServerPluginOrder.TRACE_SERVER_PRE_PLUGIN_ORDER;
}
}

@ -52,7 +52,7 @@ public class TraceServerPreEnhancedPlugin implements EnhancedPlugin {
Map<String, String> attributes = new HashMap<>(); Map<String, String> attributes = new HashMap<>();
if (CollectionUtils.isNotEmpty(spanAttributesProviderList)) { if (CollectionUtils.isNotEmpty(spanAttributesProviderList)) {
for (SpanAttributesProvider spanAttributesProvider : spanAttributesProviderList) { for (SpanAttributesProvider spanAttributesProvider : spanAttributesProviderList) {
Map<String, String> additionalAttributes = spanAttributesProvider.getServerSpanAttributes(context); Map<String, String> additionalAttributes = spanAttributesProvider.getServerPreSpanAttributes(context);
if (CollectionUtils.isNotEmpty(additionalAttributes)) { if (CollectionUtils.isNotEmpty(additionalAttributes)) {
attributes.putAll(additionalAttributes); attributes.putAll(additionalAttributes);
} }

@ -20,6 +20,7 @@ package com.tencent.cloud.plugin.trace.attribute;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import com.tencent.cloud.common.constant.MetadataConstant;
import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder; import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
@ -40,7 +41,7 @@ import static com.tencent.polaris.plugins.router.lane.LaneRouter.TRAFFIC_STAIN_L
*/ */
public class PolarisSpanAttributesProvider implements SpanAttributesProvider { public class PolarisSpanAttributesProvider implements SpanAttributesProvider {
@Override @Override
public Map<String, String> getServerSpanAttributes(EnhancedPluginContext context) { public Map<String, String> getServerPreSpanAttributes(EnhancedPluginContext context) {
Map<String, String> attributes = new HashMap<>(); Map<String, String> attributes = new HashMap<>();
MetadataContext metadataContext = MetadataContextHolder.get(); MetadataContext metadataContext = MetadataContextHolder.get();
Map<String, String> transitiveCustomAttributes = metadataContext.getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE); Map<String, String> transitiveCustomAttributes = metadataContext.getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE);
@ -59,6 +60,9 @@ public class PolarisSpanAttributesProvider implements SpanAttributesProvider {
if (CollectionUtils.isNotEmpty(upstreamDisposableCustomAttributes)) { if (CollectionUtils.isNotEmpty(upstreamDisposableCustomAttributes)) {
for (Map.Entry<String, String> entry : upstreamDisposableCustomAttributes.entrySet()) { for (Map.Entry<String, String> entry : upstreamDisposableCustomAttributes.entrySet()) {
attributes.put("custom." + entry.getKey(), entry.getValue()); attributes.put("custom." + entry.getKey(), entry.getValue());
if (MetadataConstant.DefaultMetadata.DEFAULT_METADATA_SOURCE_SERVICE_NAME.equals(entry.getKey())) {
attributes.put("net.peer.service", entry.getValue());
}
} }
} }
attributes.put("http.port", CalleeMetadataContainerGroup.getStaticApplicationMetadataContainer() attributes.put("http.port", CalleeMetadataContainerGroup.getStaticApplicationMetadataContainer()

@ -29,7 +29,11 @@ public interface SpanAttributesProvider {
*/ */
String OT_SCOPE_KEY = "OT_SCOPE_KEY"; String OT_SCOPE_KEY = "OT_SCOPE_KEY";
default Map<String, String> getServerSpanAttributes(EnhancedPluginContext context) { default Map<String, String> getServerPreSpanAttributes(EnhancedPluginContext context) {
return new HashMap<>();
}
default Map<String, String> getServerFinallySpanAttributes(EnhancedPluginContext context) {
return new HashMap<>(); return new HashMap<>();
} }

@ -20,13 +20,22 @@ package com.tencent.cloud.plugin.trace.attribute.tsf;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import com.tencent.cloud.common.constant.ContextConstant;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.util.MetadataContextUtils;
import com.tencent.cloud.common.util.OtUtils;
import com.tencent.cloud.plugin.trace.attribute.SpanAttributesProvider; import com.tencent.cloud.plugin.trace.attribute.SpanAttributesProvider;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.polaris.api.utils.CollectionUtils; import com.tencent.polaris.api.utils.CollectionUtils;
import com.tencent.polaris.api.utils.StringUtils; import com.tencent.polaris.api.utils.StringUtils;
import com.tencent.polaris.metadata.core.MetadataObjectValue;
import com.tencent.polaris.metadata.core.MetadataType;
import com.tencent.polaris.metadata.core.constant.TsfMetadataConstants; import com.tencent.polaris.metadata.core.constant.TsfMetadataConstants;
import com.tencent.polaris.plugins.router.lane.LaneRouter;
import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.ServiceInstance;
import org.springframework.tsf.core.entity.Tag;
public class TsfSpanAttributesProvider implements SpanAttributesProvider { public class TsfSpanAttributesProvider implements SpanAttributesProvider {
@ -54,6 +63,50 @@ public class TsfSpanAttributesProvider implements SpanAttributesProvider {
if (StringUtils.isBlank(attributes.get("remote.namespace-id"))) { if (StringUtils.isBlank(attributes.get("remote.namespace-id"))) {
attributes.put("remote.namespace-id", context.getRequest().getGovernanceNamespace()); attributes.put("remote.namespace-id", context.getRequest().getGovernanceNamespace());
} }
MetadataObjectValue<Tag> langTagObject = MetadataContextHolder.get().
getMetadataContainer(MetadataType.APPLICATION, true).
getMetadataValue(ContextConstant.LANE_TAG);
if (MetadataContextUtils.existMetadataValue(langTagObject)) {
attributes.put(OtUtils.OTEL_LANE_ID_KEY, langTagObject.getObjectValue().get().getValue());
}
MetadataObjectValue<Map<String, String>> extraTraceAttributeObject = MetadataContextHolder.get().
getMetadataContainer(MetadataType.APPLICATION, true).
getMetadataValue(ContextConstant.Trace.EXTRA_TRACE_ATTRIBUTES);
if (MetadataContextUtils.existMetadataValue(extraTraceAttributeObject)) {
Map<String, String> extraTraceAttributes = extraTraceAttributeObject.getObjectValue().get();
attributes.putAll(extraTraceAttributes);
}
return attributes;
}
@Override
public Map<String, String> getServerPreSpanAttributes(EnhancedPluginContext context) {
Map<String, String> attributes = new HashMap<>();
MetadataContext metadataContext = MetadataContextHolder.get();
Map<String, String> upstreamDisposableCustomAttributes = metadataContext.getFragmentContext(MetadataContext.FRAGMENT_UPSTREAM_DISPOSABLE);
if (CollectionUtils.isNotEmpty(upstreamDisposableCustomAttributes)) {
for (Map.Entry<String, String> entry : upstreamDisposableCustomAttributes.entrySet()) {
if (LaneRouter.TRAFFIC_STAIN_LABEL.equals(entry.getKey()) && entry.getValue().startsWith("tsf/")) {
attributes.put(OtUtils.OTEL_LANE_ID_KEY, entry.getValue().split("/")[1]);
}
}
}
return attributes;
}
@Override
public Map<String, String> getServerFinallySpanAttributes(EnhancedPluginContext context) {
Map<String, String> attributes = new HashMap<>();
MetadataObjectValue<Map<String, String>> extraTraceAttributeObject = MetadataContextHolder.get().
getMetadataContainer(MetadataType.APPLICATION, true).
getMetadataValue(ContextConstant.Trace.EXTRA_TRACE_ATTRIBUTES);
if (MetadataContextUtils.existMetadataValue(extraTraceAttributeObject)) {
Map<String, String> extraTraceAttributes = extraTraceAttributeObject.getObjectValue().get();
attributes.putAll(extraTraceAttributes);
}
return attributes; return attributes;
} }
} }

@ -21,6 +21,7 @@ import java.util.List;
import com.tencent.cloud.plugin.trace.TraceClientFinallyEnhancedPlugin; import com.tencent.cloud.plugin.trace.TraceClientFinallyEnhancedPlugin;
import com.tencent.cloud.plugin.trace.TraceClientPreEnhancedPlugin; import com.tencent.cloud.plugin.trace.TraceClientPreEnhancedPlugin;
import com.tencent.cloud.plugin.trace.TraceServerFinallyEnhancedPlugin;
import com.tencent.cloud.plugin.trace.TraceServerPreEnhancedPlugin; import com.tencent.cloud.plugin.trace.TraceServerPreEnhancedPlugin;
import com.tencent.cloud.plugin.trace.attribute.PolarisSpanAttributesProvider; import com.tencent.cloud.plugin.trace.attribute.PolarisSpanAttributesProvider;
import com.tencent.cloud.plugin.trace.attribute.SpanAttributesProvider; import com.tencent.cloud.plugin.trace.attribute.SpanAttributesProvider;
@ -46,6 +47,12 @@ public class TraceEnhancedPluginAutoConfiguration {
return new TraceServerPreEnhancedPlugin(polarisSDKContextManager, spanAttributesProviderList); return new TraceServerPreEnhancedPlugin(polarisSDKContextManager, spanAttributesProviderList);
} }
@Bean
public TraceServerFinallyEnhancedPlugin traceServerFinallyEnhancedPlugin(
PolarisSDKContextManager polarisSDKContextManager, @Autowired(required = false) List<SpanAttributesProvider> spanAttributesProviderList) {
return new TraceServerFinallyEnhancedPlugin(polarisSDKContextManager, spanAttributesProviderList);
}
@Bean @Bean
public TraceClientPreEnhancedPlugin traceClientPreEnhancedPlugin( public TraceClientPreEnhancedPlugin traceClientPreEnhancedPlugin(
PolarisSDKContextManager polarisSDKContextManager, @Autowired(required = false) List<SpanAttributesProvider> spanAttributesProviderList) { PolarisSDKContextManager polarisSDKContextManager, @Autowired(required = false) List<SpanAttributesProvider> spanAttributesProviderList) {

@ -40,7 +40,7 @@ public class PostInitPolarisSDKContext {
if (StringUtils.isNotBlank(region)) { if (StringUtils.isNotBlank(region)) {
valueContext.setValue(RoutingProto.NearbyRoutingConfig.LocationLevel.REGION.name(), region); valueContext.setValue(RoutingProto.NearbyRoutingConfig.LocationLevel.REGION.name(), region);
} }
if (StringUtils.isNotBlank(zone)) { if (zone != null) {
valueContext.setValue(RoutingProto.NearbyRoutingConfig.LocationLevel.ZONE.name(), zone); valueContext.setValue(RoutingProto.NearbyRoutingConfig.LocationLevel.ZONE.name(), zone);
} }
if (StringUtils.isNotBlank(campus)) { if (StringUtils.isNotBlank(campus)) {

@ -96,7 +96,7 @@ public final class PolarisContextEnvironmentPostProcessor implements Environment
// zone // zone
String zone = environment.getProperty("tsf_zone"); String zone = environment.getProperty("tsf_zone");
if (StringUtils.isNotBlank(zone)) { if (zone != null) {
polarisEnvProperties.put("spring.cloud.tencent.metadata.content.zone", zone); polarisEnvProperties.put("spring.cloud.tencent.metadata.content.zone", zone);
} }

@ -68,7 +68,7 @@ public class TsfInstanceMetadataProvider implements InstanceMetadataProvider {
tsfMetadata.put(TsfMetadataConstants.TSF_REGION, tsfCoreProperties.getTsfRegion()); tsfMetadata.put(TsfMetadataConstants.TSF_REGION, tsfCoreProperties.getTsfRegion());
} }
if (StringUtils.isNotBlank(tsfCoreProperties.getTsfZone())) { if (tsfCoreProperties.getTsfZone() != null) {
tsfMetadata.put(TsfMetadataConstants.TSF_ZONE, tsfCoreProperties.getTsfZone()); tsfMetadata.put(TsfMetadataConstants.TSF_ZONE, tsfCoreProperties.getTsfZone());
} }

@ -17,6 +17,7 @@
package com.tencent.cloud.rpc.enhancement.config; package com.tencent.cloud.rpc.enhancement.config;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -28,6 +29,7 @@ import com.tencent.cloud.rpc.enhancement.instrument.feign.EnhancedFeignBeanPostP
import com.tencent.cloud.rpc.enhancement.instrument.feign.EnhancedLoadBalancerClientAspect; import com.tencent.cloud.rpc.enhancement.instrument.feign.EnhancedLoadBalancerClientAspect;
import com.tencent.cloud.rpc.enhancement.instrument.filter.EnhancedReactiveFilter; import com.tencent.cloud.rpc.enhancement.instrument.filter.EnhancedReactiveFilter;
import com.tencent.cloud.rpc.enhancement.instrument.filter.EnhancedServletFilter; import com.tencent.cloud.rpc.enhancement.instrument.filter.EnhancedServletFilter;
import com.tencent.cloud.rpc.enhancement.instrument.resttemplate.EnhancedRestTemplateInterceptor;
import com.tencent.cloud.rpc.enhancement.instrument.resttemplate.PolarisLoadBalancerRequestTransformer; import com.tencent.cloud.rpc.enhancement.instrument.resttemplate.PolarisLoadBalancerRequestTransformer;
import com.tencent.cloud.rpc.enhancement.instrument.scg.EnhancedGatewayGlobalFilter; import com.tencent.cloud.rpc.enhancement.instrument.scg.EnhancedGatewayGlobalFilter;
import com.tencent.cloud.rpc.enhancement.instrument.webclient.EnhancedWebClientExchangeFilterFunction; import com.tencent.cloud.rpc.enhancement.instrument.webclient.EnhancedWebClientExchangeFilterFunction;
@ -53,12 +55,17 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor;
import org.springframework.cloud.client.loadbalancer.RestTemplateCustomizer;
import org.springframework.cloud.client.loadbalancer.RetryLoadBalancerInterceptor;
import org.springframework.cloud.client.serviceregistry.Registration; import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Role; import org.springframework.context.annotation.Role;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.reactive.function.client.WebClient;
@ -182,6 +189,9 @@ public class RpcEnhancementAutoConfiguration {
@ConditionalOnClass(name = "org.springframework.web.client.RestTemplate") @ConditionalOnClass(name = "org.springframework.web.client.RestTemplate")
protected static class PolarisRestTemplateAutoConfiguration { protected static class PolarisRestTemplateAutoConfiguration {
@Autowired(required = false)
private List<RestTemplate> restTemplates = Collections.emptyList();
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
@ConditionalOnClass(name = {"org.springframework.cloud.client.loadbalancer.LoadBalancerRequestTransformer"}) @ConditionalOnClass(name = {"org.springframework.cloud.client.loadbalancer.LoadBalancerRequestTransformer"})
@ -195,6 +205,57 @@ public class RpcEnhancementAutoConfiguration {
return new BlockingLoadBalancerClientBeanPostProcessor(); return new BlockingLoadBalancerClientBeanPostProcessor();
} }
@Bean
public EnhancedRestTemplateInterceptor enhancedRestTemplateInterceptor(EnhancedPluginRunner pluginRunner) {
return new EnhancedRestTemplateInterceptor(pluginRunner);
}
@Bean
public SmartInitializingSingleton addEncodeTransferMetadataInterceptorForRestTemplate(EnhancedRestTemplateInterceptor interceptor) {
return () -> restTemplates.forEach(restTemplate -> {
List<ClientHttpRequestInterceptor> list = new ArrayList<>(restTemplate.getInterceptors());
list.add(interceptor);
restTemplate.setInterceptors(list);
});
}
@Bean
public RestTemplateCustomizer polarisRestTemplateCustomizer(
@Autowired(required = false) RetryLoadBalancerInterceptor retryLoadBalancerInterceptor,
@Autowired(required = false) LoadBalancerInterceptor loadBalancerInterceptor) {
return restTemplate -> {
List<ClientHttpRequestInterceptor> list = new ArrayList<>(restTemplate.getInterceptors());
// LoadBalancerInterceptor must invoke before EncodeTransferMedataRestTemplateInterceptor
int addIndex = list.size();
if (CollectionUtils.containsInstance(list, retryLoadBalancerInterceptor) || CollectionUtils.containsInstance(list, loadBalancerInterceptor)) {
ClientHttpRequestInterceptor enhancedRestTemplateInterceptor = null;
for (int i = 0; i < list.size(); i++) {
if (list.get(i) instanceof EnhancedRestTemplateInterceptor) {
enhancedRestTemplateInterceptor = list.get(i);
addIndex = i;
}
}
if (enhancedRestTemplateInterceptor != null) {
list.remove(addIndex);
list.add(enhancedRestTemplateInterceptor);
}
}
else {
if (retryLoadBalancerInterceptor != null || loadBalancerInterceptor != null) {
for (int i = 0; i < list.size(); i++) {
if (list.get(i) instanceof EnhancedRestTemplateInterceptor) {
addIndex = i;
}
}
list.add(addIndex,
retryLoadBalancerInterceptor != null
? retryLoadBalancerInterceptor
: loadBalancerInterceptor);
}
}
restTemplate.setInterceptors(list);
};
}
} }
/** /**

@ -26,11 +26,15 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import com.tencent.cloud.common.constant.MetadataConstant;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import com.tencent.cloud.rpc.enhancement.util.EnhancedPluginUtils;
import com.tencent.polaris.api.pojo.CircuitBreakerStatus; import com.tencent.polaris.api.pojo.CircuitBreakerStatus;
import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException; import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException;
import feign.Client; import feign.Client;
@ -63,7 +67,7 @@ public class EnhancedFeignClient implements Client {
@Override @Override
public Response execute(Request request, Options options) throws IOException { public Response execute(Request request, Options options) throws IOException {
EnhancedPluginContext enhancedPluginContext = new EnhancedPluginContext(); EnhancedPluginContext enhancedPluginContext = EnhancedPluginUtils.createEnhancedPluginContext();
HttpHeaders requestHeaders = new HttpHeaders(); HttpHeaders requestHeaders = new HttpHeaders();
request.headers().forEach((s, strings) -> requestHeaders.addAll(s, new ArrayList<>(strings))); request.headers().forEach((s, strings) -> requestHeaders.addAll(s, new ArrayList<>(strings)));
@ -71,11 +75,15 @@ public class EnhancedFeignClient implements Client {
URI serviceUrl = url.resolve(request.requestTemplate().url()); URI serviceUrl = url.resolve(request.requestTemplate().url());
String governanceNamespace = MetadataContextHolder.get().getContext(MetadataContext.FRAGMENT_APPLICATION_NONE,
MetadataConstant.POLARIS_TARGET_NAMESPACE, MetadataContext.LOCAL_NAMESPACE);
EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder() EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder()
.httpHeaders(requestHeaders) .httpHeaders(requestHeaders)
.httpMethod(HttpMethod.valueOf(request.httpMethod().name())) .httpMethod(HttpMethod.valueOf(request.httpMethod().name()))
.url(url) .url(url)
.serviceUrl(serviceUrl) .serviceUrl(serviceUrl)
.governanceNamespace(governanceNamespace)
.build(); .build();
enhancedPluginContext.setRequest(enhancedRequestContext); enhancedPluginContext.setRequest(enhancedRequestContext);
enhancedPluginContext.setOriginRequest(request); enhancedPluginContext.setOriginRequest(request);
@ -97,6 +105,7 @@ public class EnhancedFeignClient implements Client {
try { try {
// Run pre enhanced plugins. // Run pre enhanced plugins.
pluginRunner.run(EnhancedPluginType.Client.PRE, enhancedPluginContext); pluginRunner.run(EnhancedPluginType.Client.PRE, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.BEFORE_CALLING, enhancedPluginContext);
startMillis = System.currentTimeMillis(); startMillis = System.currentTimeMillis();
Response response = delegate.execute(request, options); Response response = delegate.execute(request, options);

@ -17,12 +17,16 @@
package com.tencent.cloud.rpc.enhancement.instrument.filter; package com.tencent.cloud.rpc.enhancement.instrument.filter;
import com.tencent.cloud.common.constant.MetadataConstant;
import com.tencent.cloud.common.constant.OrderConstant; import com.tencent.cloud.common.constant.OrderConstant;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import com.tencent.cloud.rpc.enhancement.util.EnhancedPluginUtils;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
@ -45,7 +49,7 @@ public class EnhancedReactiveFilter implements WebFilter, Ordered {
@Override @Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) { public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
EnhancedPluginContext enhancedPluginContext = new EnhancedPluginContext(); EnhancedPluginContext enhancedPluginContext = EnhancedPluginUtils.createEnhancedPluginContext();
EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder() EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder()
.httpHeaders(exchange.getRequest().getHeaders()) .httpHeaders(exchange.getRequest().getHeaders())
@ -80,6 +84,10 @@ public class EnhancedReactiveFilter implements WebFilter, Ordered {
pluginRunner.run(EnhancedPluginType.Server.EXCEPTION, enhancedPluginContext); pluginRunner.run(EnhancedPluginType.Server.EXCEPTION, enhancedPluginContext);
}) })
.doFinally(v -> { .doFinally(v -> {
if (exchange.getAttributes().containsKey(MetadataConstant.HeaderName.METADATA_CONTEXT)) {
MetadataContextHolder.set((MetadataContext) exchange.getAttributes().get(
MetadataConstant.HeaderName.METADATA_CONTEXT));
}
// Run finally enhanced plugins. // Run finally enhanced plugins.
pluginRunner.run(EnhancedPluginType.Server.FINALLY, enhancedPluginContext); pluginRunner.run(EnhancedPluginType.Server.FINALLY, enhancedPluginContext);
}); });

@ -35,6 +35,7 @@ import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import com.tencent.cloud.rpc.enhancement.util.EnhancedPluginUtils;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
@ -57,7 +58,7 @@ public class EnhancedServletFilter extends OncePerRequestFilter {
@Override @Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
EnhancedPluginContext enhancedPluginContext = new EnhancedPluginContext(); EnhancedPluginContext enhancedPluginContext = EnhancedPluginUtils.createEnhancedPluginContext();
HttpHeaders requestHeaders = new HttpHeaders(); HttpHeaders requestHeaders = new HttpHeaders();
Enumeration<String> requestHeaderNames = request.getHeaderNames(); Enumeration<String> requestHeaderNames = request.getHeaderNames();

@ -22,12 +22,15 @@ import java.net.URI;
import java.util.Optional; import java.util.Optional;
import com.tencent.cloud.common.constant.ContextConstant; import com.tencent.cloud.common.constant.ContextConstant;
import com.tencent.cloud.common.constant.MetadataConstant;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder; import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import com.tencent.cloud.rpc.enhancement.util.EnhancedPluginUtils;
import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException; import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException;
import com.tencent.polaris.metadata.core.MetadataObjectValue; import com.tencent.polaris.metadata.core.MetadataObjectValue;
import com.tencent.polaris.metadata.core.MetadataType; import com.tencent.polaris.metadata.core.MetadataType;
@ -42,17 +45,17 @@ import org.springframework.http.client.ClientHttpResponse;
import static com.tencent.cloud.rpc.enhancement.instrument.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE; import static com.tencent.cloud.rpc.enhancement.instrument.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE;
/** /**
* EnhancedRestTemplateInterceptor. * Interceptor used for pre-plugin, post-plugin, exception-plugin, and final-plugin in RestTemplate.
* *
* @author sean yu * @author sean yu
*/ */
public class EnhancedRestTemplateWrapInterceptor { public class EnhancedRestTemplateBlockingLoadBalancerClientInterceptor {
private final EnhancedPluginRunner pluginRunner; private final EnhancedPluginRunner pluginRunner;
private final LoadBalancerClient delegate; private final LoadBalancerClient delegate;
public EnhancedRestTemplateWrapInterceptor(EnhancedPluginRunner pluginRunner, LoadBalancerClient delegate) { public EnhancedRestTemplateBlockingLoadBalancerClientInterceptor(EnhancedPluginRunner pluginRunner, LoadBalancerClient delegate) {
this.pluginRunner = pluginRunner; this.pluginRunner = pluginRunner;
this.delegate = delegate; this.delegate = delegate;
} }
@ -61,18 +64,22 @@ public class EnhancedRestTemplateWrapInterceptor {
public <T> T intercept(HttpRequest httpRequest, String serviceId, ServiceInstance serviceInstance, public <T> T intercept(HttpRequest httpRequest, String serviceId, ServiceInstance serviceInstance,
LoadBalancerRequest<T> loadBalancerRequest) throws IOException { LoadBalancerRequest<T> loadBalancerRequest) throws IOException {
EnhancedPluginContext enhancedPluginContext = new EnhancedPluginContext(); EnhancedPluginContext enhancedPluginContext = EnhancedPluginUtils.createEnhancedPluginContext();
URI serviceUrl = httpRequest.getURI(); URI serviceUrl = httpRequest.getURI();
if (httpRequest instanceof ServiceRequestWrapper) { if (httpRequest instanceof ServiceRequestWrapper) {
serviceUrl = ((ServiceRequestWrapper) httpRequest).getRequest().getURI(); serviceUrl = ((ServiceRequestWrapper) httpRequest).getRequest().getURI();
} }
String governanceNamespace = MetadataContextHolder.get().getContext(MetadataContext.FRAGMENT_APPLICATION_NONE,
MetadataConstant.POLARIS_TARGET_NAMESPACE, MetadataContext.LOCAL_NAMESPACE);
EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder() EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder()
.httpHeaders(httpRequest.getHeaders()) .httpHeaders(httpRequest.getHeaders())
.httpMethod(httpRequest.getMethod()) .httpMethod(httpRequest.getMethod())
.url(httpRequest.getURI()) .url(httpRequest.getURI())
.serviceUrl(serviceUrl) .serviceUrl(serviceUrl)
.governanceNamespace(governanceNamespace)
.build(); .build();
enhancedPluginContext.setRequest(enhancedRequestContext); enhancedPluginContext.setRequest(enhancedRequestContext);
enhancedPluginContext.setOriginRequest(httpRequest); enhancedPluginContext.setOriginRequest(httpRequest);

@ -0,0 +1,75 @@
/*
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
*
* Copyright (C) 2021 Tencent. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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.tencent.cloud.rpc.enhancement.instrument.resttemplate;
import java.io.IOException;
import com.tencent.cloud.common.constant.OrderConstant;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.util.EnhancedPluginUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor;
import org.springframework.core.Ordered;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.lang.NonNull;
/**
* Interceptor used for before calling plugin in RestTemplate.
*
* It needs to execute after {@link LoadBalancerInterceptor}, because LaneRouter may add calleeTransitiveHeaders.
*
* @author Haotian Zhang
*/
public class EnhancedRestTemplateInterceptor implements ClientHttpRequestInterceptor, Ordered {
private static final Logger LOG = LoggerFactory.getLogger(EnhancedRestTemplateInterceptor.class);
private final EnhancedPluginRunner pluginRunner;
public EnhancedRestTemplateInterceptor(EnhancedPluginRunner pluginRunner) {
this.pluginRunner = pluginRunner;
}
@Override
public int getOrder() {
return OrderConstant.Client.RestTemplate.ENHANCE_INTERCEPTOR_ORDER;
}
@Override
public ClientHttpResponse intercept(@NonNull HttpRequest httpRequest, @NonNull byte[] bytes,
@NonNull ClientHttpRequestExecution clientHttpRequestExecution) throws IOException {
EnhancedPluginContext enhancedPluginContext = EnhancedPluginUtils.getEnhancedPluginContextFromMetadataContext();
if (enhancedPluginContext != null) {
pluginRunner.run(EnhancedPluginType.Client.BEFORE_CALLING, enhancedPluginContext);
}
else {
LOG.debug("No exist enhanced plugin context, request:{}", httpRequest.getURI());
}
return clientHttpRequestExecution.execute(httpRequest, bytes);
}
}

@ -55,8 +55,8 @@ public class PolarisBlockingLoadBalancerClient extends BlockingLoadBalancerClien
if (httpRequest == null || enhancedPluginRunner == null) { if (httpRequest == null || enhancedPluginRunner == null) {
return delegate.execute(serviceId, request); return delegate.execute(serviceId, request);
} }
EnhancedRestTemplateWrapInterceptor enhancedRestTemplateWrapInterceptor = new EnhancedRestTemplateWrapInterceptor(enhancedPluginRunner, delegate); EnhancedRestTemplateBlockingLoadBalancerClientInterceptor enhancedRestTemplateBlockingLoadBalancerClientInterceptor = new EnhancedRestTemplateBlockingLoadBalancerClientInterceptor(enhancedPluginRunner, delegate);
return enhancedRestTemplateWrapInterceptor.intercept(httpRequest, serviceId, null, request); return enhancedRestTemplateBlockingLoadBalancerClientInterceptor.intercept(httpRequest, serviceId, null, request);
} }
/** /**
@ -68,7 +68,7 @@ public class PolarisBlockingLoadBalancerClient extends BlockingLoadBalancerClien
if (httpRequest == null || serviceInstance == null || enhancedPluginRunner == null) { if (httpRequest == null || serviceInstance == null || enhancedPluginRunner == null) {
return delegate.execute(serviceId, serviceInstance, request); return delegate.execute(serviceId, serviceInstance, request);
} }
EnhancedRestTemplateWrapInterceptor enhancedRestTemplateWrapInterceptor = new EnhancedRestTemplateWrapInterceptor(enhancedPluginRunner, delegate); EnhancedRestTemplateBlockingLoadBalancerClientInterceptor enhancedRestTemplateBlockingLoadBalancerClientInterceptor = new EnhancedRestTemplateBlockingLoadBalancerClientInterceptor(enhancedPluginRunner, delegate);
return enhancedRestTemplateWrapInterceptor.intercept(httpRequest, serviceId, serviceInstance, request); return enhancedRestTemplateBlockingLoadBalancerClientInterceptor.intercept(httpRequest, serviceId, serviceInstance, request);
} }
} }

@ -18,6 +18,8 @@
package com.tencent.cloud.rpc.enhancement.instrument.resttemplate; package com.tencent.cloud.rpc.enhancement.instrument.resttemplate;
import com.tencent.cloud.common.metadata.MetadataContextHolder; import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.util.EnhancedPluginUtils;
import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerRequestTransformer; import org.springframework.cloud.client.loadbalancer.LoadBalancerRequestTransformer;
@ -45,6 +47,10 @@ public class PolarisLoadBalancerRequestTransformer implements LoadBalancerReques
public HttpRequest transformRequest(HttpRequest request, ServiceInstance instance) { public HttpRequest transformRequest(HttpRequest request, ServiceInstance instance) {
if (instance != null) { if (instance != null) {
MetadataContextHolder.get().setLoadbalancer(LOAD_BALANCER_SERVICE_INSTANCE, instance); MetadataContextHolder.get().setLoadbalancer(LOAD_BALANCER_SERVICE_INSTANCE, instance);
EnhancedPluginContext enhancedPluginContext = EnhancedPluginUtils.getEnhancedPluginContextFromMetadataContext();
if (enhancedPluginContext != null) {
enhancedPluginContext.setTargetServiceInstance(instance, request.getURI());
}
} }
return request; return request;
} }

@ -30,6 +30,7 @@ import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import com.tencent.cloud.rpc.enhancement.util.EnhancedPluginUtils;
import com.tencent.polaris.api.utils.CollectionUtils; import com.tencent.polaris.api.utils.CollectionUtils;
import com.tencent.polaris.api.utils.StringUtils; import com.tencent.polaris.api.utils.StringUtils;
import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException; import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException;
@ -83,7 +84,7 @@ public class EnhancedGatewayGlobalFilter implements GlobalFilter, Ordered {
MetadataConstant.POLARIS_TARGET_NAMESPACE, MetadataContext.LOCAL_NAMESPACE); MetadataConstant.POLARIS_TARGET_NAMESPACE, MetadataContext.LOCAL_NAMESPACE);
EnhancedPluginContext enhancedPluginContext = new EnhancedPluginContext(); EnhancedPluginContext enhancedPluginContext = EnhancedPluginUtils.createEnhancedPluginContext();
EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder() EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder()
.httpHeaders(originExchange.getRequest().getHeaders()) .httpHeaders(originExchange.getRequest().getHeaders())
@ -137,6 +138,7 @@ public class EnhancedGatewayGlobalFilter implements GlobalFilter, Ordered {
enhancedPluginContext.setTargetServiceInstance(null, uri); enhancedPluginContext.setTargetServiceInstance(null, uri);
} }
} }
pluginRunner.run(EnhancedPluginType.Client.BEFORE_CALLING, enhancedPluginContext);
}) })
.doOnSuccess(v -> { .doOnSuccess(v -> {
MetadataContext metadataContextOnSuccess = originExchange.getAttribute( MetadataContext metadataContextOnSuccess = originExchange.getAttribute(

@ -21,12 +21,15 @@ import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.util.Optional; import java.util.Optional;
import com.tencent.cloud.common.constant.MetadataConstant;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder; import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import com.tencent.cloud.rpc.enhancement.util.EnhancedPluginUtils;
import com.tencent.polaris.api.utils.CollectionUtils; import com.tencent.polaris.api.utils.CollectionUtils;
import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException; import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
@ -54,13 +57,17 @@ public class EnhancedWebClientExchangeFilterFunction implements ExchangeFilterFu
@Override @Override
public Mono<ClientResponse> filter(ClientRequest originRequest, ExchangeFunction next) { public Mono<ClientResponse> filter(ClientRequest originRequest, ExchangeFunction next) {
EnhancedPluginContext enhancedPluginContext = new EnhancedPluginContext(); EnhancedPluginContext enhancedPluginContext = EnhancedPluginUtils.createEnhancedPluginContext();
String governanceNamespace = MetadataContextHolder.get().getContext(MetadataContext.FRAGMENT_APPLICATION_NONE,
MetadataConstant.POLARIS_TARGET_NAMESPACE, MetadataContext.LOCAL_NAMESPACE);
EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder() EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder()
.httpHeaders(originRequest.headers()) .httpHeaders(originRequest.headers())
.httpMethod(originRequest.method()) .httpMethod(originRequest.method())
.url(originRequest.url()) .url(originRequest.url())
.serviceUrl(getServiceUri(originRequest)) .serviceUrl(getServiceUri(originRequest))
.governanceNamespace(governanceNamespace)
.build(); .build();
enhancedPluginContext.setRequest(enhancedRequestContext); enhancedPluginContext.setRequest(enhancedRequestContext);
enhancedPluginContext.setOriginRequest(originRequest); enhancedPluginContext.setOriginRequest(originRequest);
@ -72,6 +79,7 @@ public class EnhancedWebClientExchangeFilterFunction implements ExchangeFilterFu
// Run post enhanced plugins. // Run post enhanced plugins.
try { try {
pluginRunner.run(EnhancedPluginType.Client.PRE, enhancedPluginContext); pluginRunner.run(EnhancedPluginType.Client.PRE, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.BEFORE_CALLING, enhancedPluginContext);
} }
catch (CallAbortedException e) { catch (CallAbortedException e) {
// Run finally enhanced plugins. // Run finally enhanced plugins.

@ -29,6 +29,10 @@ public interface EnhancedPluginType {
* Pre Client plugin. * Pre Client plugin.
*/ */
PRE, PRE,
/**
* Before calling the Client plugin.
*/
BEFORE_CALLING,
/** /**
* Post Client plugin. * Post Client plugin.

@ -70,7 +70,7 @@ public class PluginOrderConstant {
* and * and
* {@link com.tencent.cloud.plugin.trace.TraceClientFinallyEnhancedPlugin}. * {@link com.tencent.cloud.plugin.trace.TraceClientFinallyEnhancedPlugin}.
*/ */
public static final int TRACE_CLIENT_PLUGIN_ORDER = Ordered.HIGHEST_PRECEDENCE + 3; public static final int TRACE_CLIENT_PLUGIN_ORDER = CONSUMER_TRANSFER_METADATA_PLUGIN_ORDER + 3;
} }
public static class ServerPluginOrder { public static class ServerPluginOrder {

@ -23,6 +23,8 @@ import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.pojo.PolarisServiceInstance; import com.tencent.cloud.common.pojo.PolarisServiceInstance;
import com.tencent.polaris.api.pojo.DefaultInstance; import com.tencent.polaris.api.pojo.DefaultInstance;
import com.tencent.polaris.api.utils.CollectionUtils; import com.tencent.polaris.api.utils.CollectionUtils;
import com.tencent.polaris.api.utils.StringUtils;
import com.tencent.polaris.metadata.core.constant.TsfMetadataConstants;
import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.ServiceInstance;
@ -47,7 +49,16 @@ public class PolarisInstanceTransformer implements InstanceTransformer {
} }
String namespace = MetadataContextHolder.get().getContext(MetadataContext.FRAGMENT_APPLICATION_NONE, String namespace = MetadataContextHolder.get().getContext(MetadataContext.FRAGMENT_APPLICATION_NONE,
MetadataConstant.POLARIS_TARGET_NAMESPACE, instance.getNamespace()); MetadataConstant.POLARIS_TARGET_NAMESPACE);
if (StringUtils.isBlank(namespace) && serviceInstance.getMetadata() != null &&
serviceInstance.getMetadata().containsKey(TsfMetadataConstants.TSF_NAMESPACE_ID)) {
namespace = serviceInstance.getMetadata().get(TsfMetadataConstants.TSF_NAMESPACE_ID);
}
if (StringUtils.isBlank(namespace)) {
namespace = instance.getNamespace();
}
instance.setNamespace(namespace); instance.setNamespace(namespace);
} }

@ -0,0 +1,54 @@
/*
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
*
* Copyright (C) 2021 Tencent. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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.tencent.cloud.rpc.enhancement.util;
import com.tencent.cloud.common.constant.ContextConstant;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.util.MetadataContextUtils;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.polaris.metadata.core.MetadataObjectValue;
import com.tencent.polaris.metadata.core.MetadataType;
/**
* EnhancedPluginUtils.
*
* @author Shedfree Wu
*/
public final class EnhancedPluginUtils {
private EnhancedPluginUtils() {
}
public static EnhancedPluginContext createEnhancedPluginContext() {
EnhancedPluginContext context = new EnhancedPluginContext();
MetadataContextUtils.putMetadataObjectValue(ContextConstant.ENHANCED_PLUGIN_CONTEXT, context);
return context;
}
public static EnhancedPluginContext getEnhancedPluginContextFromMetadataContext() {
MetadataObjectValue<EnhancedPluginContext> enhancedPluginContextObject = MetadataContextHolder.get().
getMetadataContainer(MetadataType.APPLICATION, true).
getMetadataValue(ContextConstant.ENHANCED_PLUGIN_CONTEXT);
if (MetadataContextUtils.existMetadataValue(enhancedPluginContextObject)) {
return enhancedPluginContextObject.getObjectValue().get();
}
return null;
}
}
Loading…
Cancel
Save