Skip to content

Commit

Permalink
feat:support TSF router. (#1420)
Browse files Browse the repository at this point in the history
Co-authored-by: Haotian Zhang <skyebefreeman@qq.com>
  • Loading branch information
fuyuwei01 and SkyeBeFreeman committed Aug 28, 2024
1 parent 22592a2 commit e98c38e
Show file tree
Hide file tree
Showing 80 changed files with 1,177 additions and 2,453 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@
- [fix: memory cost too many when using wildcard feign calls](https://github.com/Tencent/spring-cloud-tencent/pull/1416)
- [feat:support consul config data. ](https://github.com/Tencent/spring-cloud-tencent/pull/1417)
- [feat: support otel trace](https://github.com/Tencent/spring-cloud-tencent/pull/1419)
- [feat:support TSF router.](https://github.com/Tencent/spring-cloud-tencent/pull/1420)
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.tencent.cloud.common.util.UrlUtils;
import com.tencent.cloud.metadata.provider.ReactiveMetadataProvider;
import com.tencent.cloud.polaris.context.config.PolarisContextProperties;
import com.tencent.polaris.api.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Mono;
Expand All @@ -39,8 +40,10 @@
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;

import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.APPLICATION_METADATA;
import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_DISPOSABLE_METADATA;
import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_METADATA;
import static com.tencent.polaris.metadata.core.constant.MetadataConstants.LOCAL_IP;

/**
* Filter used for storing the metadata from upstream temporarily when web application is
Expand All @@ -50,9 +53,8 @@
*/
public class DecodeTransferMetadataReactiveFilter implements WebFilter, Ordered {

private PolarisContextProperties polarisContextProperties;

private static final Logger LOG = LoggerFactory.getLogger(DecodeTransferMetadataReactiveFilter.class);
private PolarisContextProperties polarisContextProperties;

public DecodeTransferMetadataReactiveFilter(PolarisContextProperties polarisContextProperties) {
this.polarisContextProperties = polarisContextProperties;
Expand All @@ -67,16 +69,34 @@ public int getOrder() {
public Mono<Void> filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) {
// Get metadata string from http header.
ServerHttpRequest serverHttpRequest = serverWebExchange.getRequest();
Map<String, String> internalTransitiveMetadata = getIntervalMetadata(serverHttpRequest, CUSTOM_METADATA);
Map<String, String> customTransitiveMetadata = CustomTransitiveMetadataResolver.resolve(serverWebExchange);

// transitive metadata
// from specific header
Map<String, String> internalTransitiveMetadata = getInternalMetadata(serverHttpRequest, CUSTOM_METADATA);
// from header with specific prefix
Map<String, String> customTransitiveMetadata = CustomTransitiveMetadataResolver.resolve(serverWebExchange);
Map<String, String> mergedTransitiveMetadata = new HashMap<>();
mergedTransitiveMetadata.putAll(internalTransitiveMetadata);
mergedTransitiveMetadata.putAll(customTransitiveMetadata);
Map<String, String> internalDisposableMetadata = getIntervalMetadata(serverHttpRequest, CUSTOM_DISPOSABLE_METADATA);

// disposable metadata
// from specific header
Map<String, String> internalDisposableMetadata = getInternalMetadata(serverHttpRequest, CUSTOM_DISPOSABLE_METADATA);
Map<String, String> mergedDisposableMetadata = new HashMap<>(internalDisposableMetadata);
ReactiveMetadataProvider metadataProvider = new ReactiveMetadataProvider(serverHttpRequest, polarisContextProperties.getLocalIpAddress());
MetadataContextHolder.init(mergedTransitiveMetadata, mergedDisposableMetadata, metadataProvider);

// application metadata
Map<String, String> internalApplicationMetadata = getInternalMetadata(serverHttpRequest, APPLICATION_METADATA);
Map<String, String> mergedApplicationMetadata = new HashMap<>(internalApplicationMetadata);

String callerIp = "";
if (StringUtils.isNotBlank(mergedApplicationMetadata.get(LOCAL_IP))) {
callerIp = mergedApplicationMetadata.get(LOCAL_IP);
}
// message metadata
ReactiveMetadataProvider callerMessageMetadataProvider = new ReactiveMetadataProvider(serverHttpRequest, callerIp);

MetadataContextHolder.init(mergedTransitiveMetadata, mergedDisposableMetadata, mergedApplicationMetadata, callerMessageMetadataProvider);

// Save to ServerWebExchange.
serverWebExchange.getAttributes().put(
MetadataConstant.HeaderName.METADATA_CONTEXT,
Expand All @@ -89,7 +109,7 @@ public Mono<Void> filter(ServerWebExchange serverWebExchange, WebFilterChain web
.doFinally((type) -> MetadataContextHolder.remove());
}

private Map<String, String> getIntervalMetadata(ServerHttpRequest serverHttpRequest, String headerName) {
private Map<String, String> getInternalMetadata(ServerHttpRequest serverHttpRequest, String headerName) {
HttpHeaders httpHeaders = serverHttpRequest.getHeaders();
String customMetadataStr = UrlUtils.decode(httpHeaders.getFirst(headerName));
LOG.debug("Get upstream metadata string: {}", customMetadataStr);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.tencent.cloud.common.util.UrlUtils;
import com.tencent.cloud.metadata.provider.ServletMetadataProvider;
import com.tencent.cloud.polaris.context.config.PolarisContextProperties;
import com.tencent.polaris.api.utils.StringUtils;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
Expand All @@ -39,8 +40,10 @@
import org.springframework.lang.NonNull;
import org.springframework.web.filter.OncePerRequestFilter;

import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.APPLICATION_METADATA;
import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_DISPOSABLE_METADATA;
import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_METADATA;
import static com.tencent.polaris.metadata.core.constant.MetadataConstants.LOCAL_IP;

/**
* Filter used for storing the metadata from upstream temporarily when web application is
Expand All @@ -63,16 +66,32 @@ public DecodeTransferMetadataServletFilter(PolarisContextProperties polarisConte
protected void doFilterInternal(@NonNull HttpServletRequest httpServletRequest,
@NonNull HttpServletResponse httpServletResponse, FilterChain filterChain)
throws ServletException, IOException {
// transitive metadata
// from specific header
Map<String, String> internalTransitiveMetadata = getInternalMetadata(httpServletRequest, CUSTOM_METADATA);
// from header with specific prefix
Map<String, String> customTransitiveMetadata = CustomTransitiveMetadataResolver.resolve(httpServletRequest);

Map<String, String> mergedTransitiveMetadata = new HashMap<>();
mergedTransitiveMetadata.putAll(internalTransitiveMetadata);
mergedTransitiveMetadata.putAll(customTransitiveMetadata);

// disposable metadata
// from specific header
Map<String, String> internalDisposableMetadata = getInternalMetadata(httpServletRequest, CUSTOM_DISPOSABLE_METADATA);
Map<String, String> mergedDisposableMetadata = new HashMap<>(internalDisposableMetadata);
ServletMetadataProvider metadataProvider = new ServletMetadataProvider(httpServletRequest, polarisContextProperties.getLocalIpAddress());
MetadataContextHolder.init(mergedTransitiveMetadata, mergedDisposableMetadata, metadataProvider);

// application metadata
Map<String, String> internalApplicationMetadata = getInternalMetadata(httpServletRequest, APPLICATION_METADATA);
Map<String, String> mergedApplicationMetadata = new HashMap<>(internalApplicationMetadata);

String callerIp = "";
if (StringUtils.isNotBlank(mergedApplicationMetadata.get(LOCAL_IP))) {
callerIp = mergedApplicationMetadata.get(LOCAL_IP);
}
// message metadata
ServletMetadataProvider callerMessageMetadataProvider = new ServletMetadataProvider(httpServletRequest, callerIp);

MetadataContextHolder.init(mergedTransitiveMetadata, mergedDisposableMetadata, mergedApplicationMetadata, callerMessageMetadataProvider);

TransHeadersTransfer.transfer(httpServletRequest);
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@

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.CUSTOM_DISPOSABLE_METADATA;
import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_METADATA;

Expand All @@ -64,6 +65,7 @@ public void run(EnhancedPluginContext context) throws Throwable {
MetadataContext metadataContext = MetadataContextHolder.get();
Map<String, String> customMetadata = metadataContext.getCustomMetadata();
Map<String, String> disposableMetadata = metadataContext.getDisposableMetadata();
Map<String, String> applicationMetadata = metadataContext.getApplicationMetadata();
Map<String, String> transHeaders = metadataContext.getTransHeadersKV();

MessageMetadataContainer calleeMessageMetadataContainer = metadataContext.getMetadataContainer(MetadataType.MESSAGE, false);
Expand All @@ -77,6 +79,9 @@ public void run(EnhancedPluginContext context) throws Throwable {
// process custom metadata
this.buildMetadataHeader(request, customMetadata, CUSTOM_METADATA);

// add application metadata
this.buildMetadataHeader(request, applicationMetadata, APPLICATION_METADATA);

// set headers that need to be transmitted from the upstream
this.buildTransmittedHeader(request, transHeaders);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.springframework.http.HttpRequest;
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.CUSTOM_DISPOSABLE_METADATA;
import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_METADATA;

Expand All @@ -60,6 +61,7 @@ public void run(EnhancedPluginContext context) throws Throwable {
MetadataContext metadataContext = MetadataContextHolder.get();
Map<String, String> customMetadata = metadataContext.getCustomMetadata();
Map<String, String> disposableMetadata = metadataContext.getDisposableMetadata();
Map<String, String> applicationMetadata = metadataContext.getApplicationMetadata();
Map<String, String> transHeaders = metadataContext.getTransHeadersKV();
MessageMetadataContainer calleeMessageMetadataContainer = metadataContext.getMetadataContainer(MetadataType.MESSAGE, false);
Map<String, String> calleeTransitiveHeaders = calleeMessageMetadataContainer.getTransitiveHeaders();
Expand All @@ -72,6 +74,9 @@ public void run(EnhancedPluginContext context) throws Throwable {
// build custom metadata request header
this.buildMetadataHeader(httpRequest, customMetadata, CUSTOM_METADATA);

// build application metadata request header
this.buildMetadataHeader(httpRequest, applicationMetadata, APPLICATION_METADATA);

// set headers that need to be transmitted from the upstream
this.buildTransmittedHeader(httpRequest, transHeaders);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.springframework.util.CollectionUtils;
import org.springframework.web.server.ServerWebExchange;

import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.APPLICATION_METADATA;
import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_DISPOSABLE_METADATA;
import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_METADATA;

Expand Down Expand Up @@ -69,6 +70,7 @@ public void run(EnhancedPluginContext context) throws Throwable {

Map<String, String> customMetadata = metadataContext.getCustomMetadata();
Map<String, String> disposableMetadata = metadataContext.getDisposableMetadata();
Map<String, String> applicationMetadata = metadataContext.getApplicationMetadata();

MessageMetadataContainer calleeMessageMetadataContainer = metadataContext.getMetadataContainer(MetadataType.MESSAGE, false);
Map<String, String> calleeTransitiveHeaders = calleeMessageMetadataContainer.getTransitiveHeaders();
Expand All @@ -77,6 +79,7 @@ public void run(EnhancedPluginContext context) throws Throwable {

this.buildMetadataHeader(builder, customMetadata, CUSTOM_METADATA);
this.buildMetadataHeader(builder, disposableMetadata, CUSTOM_DISPOSABLE_METADATA);
this.buildMetadataHeader(builder, applicationMetadata, APPLICATION_METADATA);
TransHeadersTransfer.transfer(exchange.getRequest());

context.setOriginRequest(exchange.mutate().request(builder.build()).build());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.springframework.util.CollectionUtils;
import org.springframework.web.reactive.function.client.ClientRequest;

import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.APPLICATION_METADATA;
import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_DISPOSABLE_METADATA;
import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_METADATA;

Expand All @@ -59,6 +60,7 @@ public void run(EnhancedPluginContext context) throws Throwable {
MetadataContext metadataContext = MetadataContextHolder.get();
Map<String, String> customMetadata = metadataContext.getCustomMetadata();
Map<String, String> disposableMetadata = metadataContext.getDisposableMetadata();
Map<String, String> applicationMetadata = metadataContext.getApplicationMetadata();
Map<String, String> transHeaders = metadataContext.getTransHeadersKV();
MessageMetadataContainer calleeMessageMetadataContainer = metadataContext.getMetadataContainer(MetadataType.MESSAGE, false);
Map<String, String> calleeTransitiveHeaders = calleeMessageMetadataContainer.getTransitiveHeaders();
Expand All @@ -70,6 +72,7 @@ public void run(EnhancedPluginContext context) throws Throwable {

this.buildMetadataHeader(requestBuilder, customMetadata, CUSTOM_METADATA);
this.buildMetadataHeader(requestBuilder, disposableMetadata, CUSTOM_DISPOSABLE_METADATA);
this.buildMetadataHeader(requestBuilder, applicationMetadata, APPLICATION_METADATA);
this.buildTransmittedHeader(requestBuilder, transHeaders);

context.setOriginRequest(requestBuilder.build());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. 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.metadata.provider;

import java.net.URI;
import java.util.Collection;
import java.util.Map;

import com.tencent.cloud.common.util.UrlUtils;
import com.tencent.cloud.common.util.expresstion.ExpressionLabelUtils;
import com.tencent.polaris.metadata.core.MessageMetadataContainer;
import com.tencent.polaris.metadata.core.MetadataProvider;
import com.tencent.polaris.metadata.core.constant.MetadataConstants;
import com.tencent.polaris.metadata.core.manager.CalleeMetadataContainerGroup;
import feign.RequestTemplate;

/**
* MetadataProvider used for Feign RequestTemplate.
*
* @author Haotian Zhang
*/
public class FeignRequestTemplateMetadataProvider implements MetadataProvider {

private final RequestTemplate requestTemplate;

public FeignRequestTemplateMetadataProvider(RequestTemplate requestTemplate) {
this.requestTemplate = requestTemplate;
}

@Override
public String getRawMetadataStringValue(String key) {
switch (key) {
case MessageMetadataContainer.LABEL_KEY_METHOD:
return requestTemplate.method();
case MessageMetadataContainer.LABEL_KEY_PATH:
URI uri = URI.create(requestTemplate.request().url());
return UrlUtils.decode(uri.getPath());
case MessageMetadataContainer.LABEL_KEY_CALLER_IP:
return CalleeMetadataContainerGroup.getStaticApplicationMetadataContainer()
.getRawMetadataStringValue(MetadataConstants.LOCAL_IP);
default:
return null;
}
}

@Override
public String getRawMetadataMapValue(String key, String mapKey) {
Map<String, Collection<String>> headers = requestTemplate.headers();
switch (key) {
case MessageMetadataContainer.LABEL_MAP_KEY_HEADER:
return UrlUtils.decode(ExpressionLabelUtils.getFirstValue(headers, mapKey));
case MessageMetadataContainer.LABEL_MAP_KEY_COOKIE:
return UrlUtils.decode(ExpressionLabelUtils.getCookieFirstValue(headers, mapKey));
case MessageMetadataContainer.LABEL_MAP_KEY_QUERY:
return UrlUtils.decode(ExpressionLabelUtils.getFirstValue(requestTemplate.queries(), mapKey));
default:
return null;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. 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.metadata.provider;

import com.tencent.cloud.common.util.UrlUtils;
import com.tencent.cloud.common.util.expresstion.SpringWebExpressionLabelUtils;
import com.tencent.polaris.metadata.core.MessageMetadataContainer;
import com.tencent.polaris.metadata.core.MetadataProvider;
import com.tencent.polaris.metadata.core.constant.MetadataConstants;
import com.tencent.polaris.metadata.core.manager.CalleeMetadataContainerGroup;

import org.springframework.http.HttpRequest;

/**
* MetadataProvider used for RestTemplate HttpRequest.
*
* @author Haotian Zhang
*/
public class RestTemplateMetadataProvider implements MetadataProvider {

private final HttpRequest request;

public RestTemplateMetadataProvider(HttpRequest request) {
this.request = request;
}

@Override
public String getRawMetadataStringValue(String key) {
switch (key) {
case MessageMetadataContainer.LABEL_KEY_METHOD:
return request.getMethod().toString();
case MessageMetadataContainer.LABEL_KEY_PATH:
return UrlUtils.decode(request.getURI().getPath());
case MessageMetadataContainer.LABEL_KEY_CALLER_IP:
return CalleeMetadataContainerGroup.getStaticApplicationMetadataContainer()
.getRawMetadataStringValue(MetadataConstants.LOCAL_IP);
default:
return null;
}
}

@Override
public String getRawMetadataMapValue(String key, String mapKey) {
switch (key) {
case MessageMetadataContainer.LABEL_MAP_KEY_HEADER:
return UrlUtils.decode(SpringWebExpressionLabelUtils.getHeaderValue(request, mapKey));
case MessageMetadataContainer.LABEL_MAP_KEY_COOKIE:
return UrlUtils.decode(SpringWebExpressionLabelUtils.getCookieValue(request, mapKey));
case MessageMetadataContainer.LABEL_MAP_KEY_QUERY:
return UrlUtils.decode(SpringWebExpressionLabelUtils.getQueryValue(request, mapKey));
default:
return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public List<ServiceInstance> getInstances(String serviceId) throws PolarisExcept
InstancesResponse filteredInstances = polarisDiscoveryHandler.getHealthyInstances(serviceId);
ServiceInstances serviceInstances = filteredInstances.toServiceInstances();
for (Instance instance : serviceInstances.getInstances()) {
instances.add(new PolarisServiceInstance(instance));
instances.add(new PolarisServiceInstance(instance, filteredInstances.getMetadata()));
}
return instances;
}
Expand Down
Loading

0 comments on commit e98c38e

Please sign in to comment.