feat: support before calling client plugin.

pull/1664/head
shedfreewu 2 months ago
parent 0f79c5e36e
commit cd099792cb

@ -17,32 +17,20 @@
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.metadata.core.DecodeTransferMetadataReactiveFilter;
import com.tencent.cloud.metadata.core.DecodeTransferMetadataServletFilter;
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.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.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
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.Configuration;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;
import static jakarta.servlet.DispatcherType.ASYNC;
import static jakarta.servlet.DispatcherType.ERROR;
@ -130,59 +118,9 @@ public class MetadataTransferAutoConfiguration {
@ConditionalOnProperty(value = "spring.cloud.tencent.rpc-enhancement.enabled", havingValue = "true", matchIfMissing = true)
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
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 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);
};
public EncodeTransferMedataRestTemplateEnhancedPlugin encodeTransferMedataRestTemplateEnhancedPlugin() {
return new EncodeTransferMedataRestTemplateEnhancedPlugin();
}
}

@ -17,27 +17,23 @@
package com.tencent.cloud.metadata.core;
import java.io.IOException;
import java.util.Map;
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.common.tsf.TsfContextUtils;
import com.tencent.cloud.common.util.JacksonUtils;
import com.tencent.cloud.common.util.TsfTagUtils;
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.MetadataType;
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.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 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;
/**
* Interceptor used for adding the metadata in http headers from context when web client
* is RestTemplate.
* Pre EnhancedPlugin for rest template to encode transfer metadata.
*
* It needs to execute after {@link LoadBalancerInterceptor}, because LaneRouter may add calleeTransitiveHeaders.
*
* @author Haotian Zhang
* @author Shedfree Wu
*/
public class EncodeTransferMedataRestTemplateInterceptor implements ClientHttpRequestInterceptor, Ordered {
public class EncodeTransferMedataRestTemplateEnhancedPlugin implements EnhancedPlugin {
@Override
public int getOrder() {
return OrderConstant.Client.RestTemplate.ENCODE_TRANSFER_METADATA_INTERCEPTOR_ORDER;
public EnhancedPluginType getType() {
return EnhancedPluginType.Client.BEFORE_CALLING;
}
@Override
public ClientHttpResponse intercept(@NonNull HttpRequest httpRequest, @NonNull byte[] bytes,
@NonNull ClientHttpRequestExecution clientHttpRequestExecution) throws IOException {
public void run(EnhancedPluginContext context) throws Throwable {
if (!(context.getOriginRequest() instanceof HttpRequest)) {
return;
}
HttpRequest httpRequest = (HttpRequest) context.getOriginRequest();
// get metadata of current thread
MetadataContext metadataContext = MetadataContextHolder.get();
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
this.buildTransmittedHeader(httpRequest, transHeaders);
return clientHttpRequestExecution.execute(httpRequest, bytes);
}
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)));
}
}
@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.MetadataContextHolder;
import com.tencent.cloud.rpc.enhancement.instrument.resttemplate.EnhancedRestTemplateInterceptor;
import org.junit.jupiter.api.Test;
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;
/**
* Test for {@link EncodeTransferMedataRestTemplateInterceptor}.
* Test for {@link EnhancedRestTemplateInterceptor}.
*
* @author Haotian Zhang
*/
@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = RANDOM_PORT,
classes = EncodeTransferMedataRestTemplateInterceptorTest.TestApplication.class,
classes = EnhancedRestTemplateInterceptorTest.TestApplication.class,
properties = {"spring.config.location = classpath:application-test.yml",
"spring.main.web-application-type = reactive"})
public class EncodeTransferMedataRestTemplateInterceptorTest {
public class EnhancedRestTemplateInterceptorTest {
@Autowired
private RestTemplate restTemplate;

@ -40,6 +40,14 @@ public final class ContextConstant {
* Default registry heartbeat time interval: 5 (s).
*/
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() {
}

@ -49,9 +49,9 @@ public class OrderConstant {
*/
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.

@ -27,6 +27,7 @@ import java.util.Optional;
import java.util.Set;
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.tsf.TsfContextUtils;
import com.tencent.polaris.api.utils.CollectionUtils;
@ -114,6 +115,7 @@ public final class TsfTagUtils {
if (laneTag != null) {
tsfSystemTags.add(laneTag);
MetadataContextUtils.putMetadataObjectValue(ContextConstant.LANE_TAG, laneTag);
}
if (CollectionUtils.isNotEmpty(tsfUserTags)) {

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

@ -21,8 +21,10 @@ import java.util.HashMap;
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.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.polaris.api.utils.CollectionUtils;
@ -30,8 +32,10 @@ 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.plugins.router.lane.LaneRouter;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.tsf.core.entity.Tag;
public class TsfSpanAttributesProvider implements SpanAttributesProvider {
@ -60,6 +64,13 @@ public class TsfSpanAttributesProvider implements SpanAttributesProvider {
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);
@ -70,6 +81,22 @@ public class TsfSpanAttributesProvider implements SpanAttributesProvider {
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<>();

@ -17,6 +17,7 @@
package com.tencent.cloud.rpc.enhancement.config;
import java.util.ArrayList;
import java.util.Collections;
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.PolarisLoadBalancerFeignRequestTransformer;
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.resttemplate.EnhancedRestTemplateInterceptor;
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.webclient.EnhancedWebClientExchangeFilterFunction;
@ -53,12 +55,17 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
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.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Role;
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.reactive.function.client.WebClient;
@ -195,6 +202,60 @@ public class RpcEnhancementAutoConfiguration {
return new PolarisLoadBalancerRequestTransformer();
}
@Autowired(required = false)
private List<RestTemplate> restTemplates = Collections.emptyList();
@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);
};
}
}

@ -34,6 +34,7 @@ import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
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.circuitbreak.client.exception.CallAbortedException;
import feign.Client;
@ -66,7 +67,7 @@ public class EnhancedFeignClient implements Client {
@Override
public Response execute(Request request, Options options) throws IOException {
EnhancedPluginContext enhancedPluginContext = new EnhancedPluginContext();
EnhancedPluginContext enhancedPluginContext = EnhancedPluginUtils.createEnhancedPluginContext();
HttpHeaders requestHeaders = new HttpHeaders();
request.headers().forEach((s, strings) -> requestHeaders.addAll(s, new ArrayList<>(strings)));
@ -104,6 +105,7 @@ public class EnhancedFeignClient implements Client {
try {
// Run pre enhanced plugins.
pluginRunner.run(EnhancedPluginType.Client.PRE, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.BEFORE_CALLING, enhancedPluginContext);
startMillis = System.currentTimeMillis();
Response response = delegate.execute(request, options);

@ -26,6 +26,7 @@ import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import com.tencent.cloud.rpc.enhancement.util.EnhancedPluginUtils;
import reactor.core.publisher.Mono;
import org.springframework.core.Ordered;
@ -48,7 +49,7 @@ public class EnhancedReactiveFilter implements WebFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
EnhancedPluginContext enhancedPluginContext = new EnhancedPluginContext();
EnhancedPluginContext enhancedPluginContext = EnhancedPluginUtils.createEnhancedPluginContext();
EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder()
.httpHeaders(exchange.getRequest().getHeaders())

@ -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.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import com.tencent.cloud.rpc.enhancement.util.EnhancedPluginUtils;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
@ -56,7 +57,7 @@ public class EnhancedServletFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
EnhancedPluginContext enhancedPluginContext = new EnhancedPluginContext();
EnhancedPluginContext enhancedPluginContext = EnhancedPluginUtils.createEnhancedPluginContext();
HttpHeaders requestHeaders = new HttpHeaders();
Enumeration<String> requestHeaderNames = request.getHeaderNames();

@ -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.EnhancedRequestContext;
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.metadata.core.MetadataObjectValue;
import com.tencent.polaris.metadata.core.MetadataType;
@ -44,17 +45,17 @@ import org.springframework.http.client.ClientHttpResponse;
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
*/
public class EnhancedRestTemplateWrapInterceptor {
public class EnhancedRestTemplateBlockingLoadBalancerClientInterceptor {
private final EnhancedPluginRunner pluginRunner;
private final LoadBalancerClient delegate;
public EnhancedRestTemplateWrapInterceptor(EnhancedPluginRunner pluginRunner, LoadBalancerClient delegate) {
public EnhancedRestTemplateBlockingLoadBalancerClientInterceptor(EnhancedPluginRunner pluginRunner, LoadBalancerClient delegate) {
this.pluginRunner = pluginRunner;
this.delegate = delegate;
}
@ -63,7 +64,7 @@ public class EnhancedRestTemplateWrapInterceptor {
public <T> T intercept(HttpRequest httpRequest, String serviceId, ServiceInstance serviceInstance,
LoadBalancerRequest<T> loadBalancerRequest) throws IOException {
EnhancedPluginContext enhancedPluginContext = new EnhancedPluginContext();
EnhancedPluginContext enhancedPluginContext = EnhancedPluginUtils.createEnhancedPluginContext();
URI serviceUrl = httpRequest.getURI();
if (httpRequest instanceof ServiceRequestWrapper) {

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

@ -18,6 +18,8 @@
package com.tencent.cloud.rpc.enhancement.instrument.resttemplate;
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.loadbalancer.LoadBalancerRequestTransformer;
@ -45,6 +47,10 @@ public class PolarisLoadBalancerRequestTransformer implements LoadBalancerReques
public HttpRequest transformRequest(HttpRequest request, ServiceInstance instance) {
if (instance != null) {
MetadataContextHolder.get().setLoadbalancer(LOAD_BALANCER_SERVICE_INSTANCE, instance);
EnhancedPluginContext enhancedPluginContext = EnhancedPluginUtils.getEnhancedPluginContextFromMetadataContext();
if (enhancedPluginContext != null) {
enhancedPluginContext.setTargetServiceInstance(instance, request.getURI());
}
}
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.EnhancedRequestContext;
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.StringUtils;
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);
EnhancedPluginContext enhancedPluginContext = new EnhancedPluginContext();
EnhancedPluginContext enhancedPluginContext = EnhancedPluginUtils.createEnhancedPluginContext();
EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder()
.httpHeaders(originExchange.getRequest().getHeaders())
@ -137,6 +138,7 @@ public class EnhancedGatewayGlobalFilter implements GlobalFilter, Ordered {
enhancedPluginContext.setTargetServiceInstance(null, uri);
}
}
pluginRunner.run(EnhancedPluginType.Client.BEFORE_CALLING, enhancedPluginContext);
})
.doOnSuccess(v -> {
MetadataContext metadataContextOnSuccess = originExchange.getAttribute(

@ -29,6 +29,7 @@ import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
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.circuitbreak.client.exception.CallAbortedException;
import reactor.core.publisher.Mono;
@ -56,7 +57,7 @@ public class EnhancedWebClientExchangeFilterFunction implements ExchangeFilterFu
@Override
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);
@ -78,6 +79,7 @@ public class EnhancedWebClientExchangeFilterFunction implements ExchangeFilterFu
// Run post enhanced plugins.
try {
pluginRunner.run(EnhancedPluginType.Client.PRE, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.BEFORE_CALLING, enhancedPluginContext);
}
catch (CallAbortedException e) {
// Run finally enhanced plugins.

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

@ -70,7 +70,7 @@ public class PluginOrderConstant {
* and
* {@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 {

@ -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