diff --git a/CHANGELOG.md b/CHANGELOG.md index f0c153f59..6f2714f05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,4 +23,5 @@ - [fix:fix app starting failed when user using custom OpenAPI bean.](https://github.com/Tencent/spring-cloud-tencent/pull/1398) - [fix: memory cost too many when using wildcard feign calls](https://github.com/Tencent/spring-cloud-tencent/pull/1400) - [feat:support consul config data.](https://github.com/Tencent/spring-cloud-tencent/pull/1401) -- [feat: support otel trace](https://github.com/Tencent/spring-cloud-tencent/pull/1402) \ No newline at end of file +- [feat: support otel trace](https://github.com/Tencent/spring-cloud-tencent/pull/1402) +- [feat:support TSF router.](https://github.com/Tencent/spring-cloud-tencent/pull/1403) \ No newline at end of file diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/DecodeTransferMetadataReactiveFilter.java b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/DecodeTransferMetadataReactiveFilter.java index eb7c8a91c..564ed1a2b 100644 --- a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/DecodeTransferMetadataReactiveFilter.java +++ b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/DecodeTransferMetadataReactiveFilter.java @@ -28,6 +28,7 @@ import com.tencent.cloud.common.util.JacksonUtils; 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; @@ -39,8 +40,10 @@ import org.springframework.web.server.ServerWebExchange; 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 @@ -50,9 +53,8 @@ import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUST */ 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; @@ -67,16 +69,34 @@ public class DecodeTransferMetadataReactiveFilter implements WebFilter, Ordered public Mono filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) { // Get metadata string from http header. ServerHttpRequest serverHttpRequest = serverWebExchange.getRequest(); - Map internalTransitiveMetadata = getIntervalMetadata(serverHttpRequest, CUSTOM_METADATA); - Map customTransitiveMetadata = CustomTransitiveMetadataResolver.resolve(serverWebExchange); + // transitive metadata + // from specific header + Map internalTransitiveMetadata = getInternalMetadata(serverHttpRequest, CUSTOM_METADATA); + // from header with specific prefix + Map customTransitiveMetadata = CustomTransitiveMetadataResolver.resolve(serverWebExchange); Map mergedTransitiveMetadata = new HashMap<>(); mergedTransitiveMetadata.putAll(internalTransitiveMetadata); mergedTransitiveMetadata.putAll(customTransitiveMetadata); - Map internalDisposableMetadata = getIntervalMetadata(serverHttpRequest, CUSTOM_DISPOSABLE_METADATA); + + // disposable metadata + // from specific header + Map internalDisposableMetadata = getInternalMetadata(serverHttpRequest, CUSTOM_DISPOSABLE_METADATA); Map mergedDisposableMetadata = new HashMap<>(internalDisposableMetadata); - ReactiveMetadataProvider metadataProvider = new ReactiveMetadataProvider(serverHttpRequest, polarisContextProperties.getLocalIpAddress()); - MetadataContextHolder.init(mergedTransitiveMetadata, mergedDisposableMetadata, metadataProvider); + + // application metadata + Map internalApplicationMetadata = getInternalMetadata(serverHttpRequest, APPLICATION_METADATA); + Map 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, @@ -90,7 +110,7 @@ public class DecodeTransferMetadataReactiveFilter implements WebFilter, Ordered .doFinally((type) -> MetadataContextHolder.remove()); } - private Map getIntervalMetadata(ServerHttpRequest serverHttpRequest, String headerName) { + private Map getInternalMetadata(ServerHttpRequest serverHttpRequest, String headerName) { HttpHeaders httpHeaders = serverHttpRequest.getHeaders(); String customMetadataStr = UrlUtils.decode(httpHeaders.getFirst(headerName)); LOG.debug("Get upstream metadata string: {}", customMetadataStr); diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/DecodeTransferMetadataServletFilter.java b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/DecodeTransferMetadataServletFilter.java index 63abc08ec..cbf566022 100644 --- a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/DecodeTransferMetadataServletFilter.java +++ b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/DecodeTransferMetadataServletFilter.java @@ -33,6 +33,7 @@ import com.tencent.cloud.common.util.JacksonUtils; 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 org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,8 +41,10 @@ import org.springframework.core.annotation.Order; 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 @@ -64,16 +67,32 @@ public class DecodeTransferMetadataServletFilter extends OncePerRequestFilter { protected void doFilterInternal(@NonNull HttpServletRequest httpServletRequest, @NonNull HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException { + // transitive metadata + // from specific header Map internalTransitiveMetadata = getInternalMetadata(httpServletRequest, CUSTOM_METADATA); + // from header with specific prefix Map customTransitiveMetadata = CustomTransitiveMetadataResolver.resolve(httpServletRequest); - Map mergedTransitiveMetadata = new HashMap<>(); mergedTransitiveMetadata.putAll(internalTransitiveMetadata); mergedTransitiveMetadata.putAll(customTransitiveMetadata); + + // disposable metadata + // from specific header Map internalDisposableMetadata = getInternalMetadata(httpServletRequest, CUSTOM_DISPOSABLE_METADATA); Map mergedDisposableMetadata = new HashMap<>(internalDisposableMetadata); - ServletMetadataProvider metadataProvider = new ServletMetadataProvider(httpServletRequest, polarisContextProperties.getLocalIpAddress()); - MetadataContextHolder.init(mergedTransitiveMetadata, mergedDisposableMetadata, metadataProvider); + + // application metadata + Map internalApplicationMetadata = getInternalMetadata(httpServletRequest, APPLICATION_METADATA); + Map 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); diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataFeignEnhancedPlugin.java b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataFeignEnhancedPlugin.java index ff722edc6..3e07c3bf0 100644 --- a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataFeignEnhancedPlugin.java +++ b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataFeignEnhancedPlugin.java @@ -39,6 +39,7 @@ import feign.Request; 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; @@ -64,6 +65,7 @@ public class EncodeTransferMedataFeignEnhancedPlugin implements EnhancedPlugin { MetadataContext metadataContext = MetadataContextHolder.get(); Map customMetadata = metadataContext.getCustomMetadata(); Map disposableMetadata = metadataContext.getDisposableMetadata(); + Map applicationMetadata = metadataContext.getApplicationMetadata(); Map transHeaders = metadataContext.getTransHeadersKV(); MessageMetadataContainer calleeMessageMetadataContainer = metadataContext.getMetadataContainer(MetadataType.MESSAGE, false); @@ -77,6 +79,9 @@ public class EncodeTransferMedataFeignEnhancedPlugin implements EnhancedPlugin { // 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); } diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataRestTemplateEnhancedPlugin.java b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataRestTemplateEnhancedPlugin.java index 50e42885b..f3637494e 100644 --- a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataRestTemplateEnhancedPlugin.java +++ b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataRestTemplateEnhancedPlugin.java @@ -35,6 +35,7 @@ import com.tencent.polaris.metadata.core.MetadataType; 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; @@ -60,6 +61,7 @@ public class EncodeTransferMedataRestTemplateEnhancedPlugin implements EnhancedP MetadataContext metadataContext = MetadataContextHolder.get(); Map customMetadata = metadataContext.getCustomMetadata(); Map disposableMetadata = metadataContext.getDisposableMetadata(); + Map applicationMetadata = metadataContext.getApplicationMetadata(); Map transHeaders = metadataContext.getTransHeadersKV(); MessageMetadataContainer calleeMessageMetadataContainer = metadataContext.getMetadataContainer(MetadataType.MESSAGE, false); Map calleeTransitiveHeaders = calleeMessageMetadataContainer.getTransitiveHeaders(); @@ -72,6 +74,9 @@ public class EncodeTransferMedataRestTemplateEnhancedPlugin implements EnhancedP // 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); } diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataScgEnhancedPlugin.java b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataScgEnhancedPlugin.java index 8c996bbf1..7974bd71d 100644 --- a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataScgEnhancedPlugin.java +++ b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataScgEnhancedPlugin.java @@ -37,6 +37,7 @@ import org.springframework.http.server.reactive.ServerHttpRequest; 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; @@ -69,6 +70,7 @@ public class EncodeTransferMedataScgEnhancedPlugin implements EnhancedPlugin { Map customMetadata = metadataContext.getCustomMetadata(); Map disposableMetadata = metadataContext.getDisposableMetadata(); + Map applicationMetadata = metadataContext.getApplicationMetadata(); MessageMetadataContainer calleeMessageMetadataContainer = metadataContext.getMetadataContainer(MetadataType.MESSAGE, false); Map calleeTransitiveHeaders = calleeMessageMetadataContainer.getTransitiveHeaders(); @@ -77,6 +79,7 @@ public class EncodeTransferMedataScgEnhancedPlugin implements EnhancedPlugin { 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()); diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataWebClientEnhancedPlugin.java b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataWebClientEnhancedPlugin.java index 2967a2b4c..441b33446 100644 --- a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataWebClientEnhancedPlugin.java +++ b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataWebClientEnhancedPlugin.java @@ -35,6 +35,7 @@ import com.tencent.polaris.metadata.core.MetadataType; 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; @@ -59,6 +60,7 @@ public class EncodeTransferMedataWebClientEnhancedPlugin implements EnhancedPlug MetadataContext metadataContext = MetadataContextHolder.get(); Map customMetadata = metadataContext.getCustomMetadata(); Map disposableMetadata = metadataContext.getDisposableMetadata(); + Map applicationMetadata = metadataContext.getApplicationMetadata(); Map transHeaders = metadataContext.getTransHeadersKV(); MessageMetadataContainer calleeMessageMetadataContainer = metadataContext.getMetadataContainer(MetadataType.MESSAGE, false); Map calleeTransitiveHeaders = calleeMessageMetadataContainer.getTransitiveHeaders(); @@ -70,6 +72,7 @@ public class EncodeTransferMedataWebClientEnhancedPlugin implements EnhancedPlug 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()); diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/provider/FeignRequestTemplateMetadataProvider.java b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/provider/FeignRequestTemplateMetadataProvider.java new file mode 100644 index 000000000..1d62416a5 --- /dev/null +++ b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/provider/FeignRequestTemplateMetadataProvider.java @@ -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> 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; + } + } +} diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/provider/RestTemplateMetadataProvider.java b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/provider/RestTemplateMetadataProvider.java new file mode 100644 index 000000000..31eea10f8 --- /dev/null +++ b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/provider/RestTemplateMetadataProvider.java @@ -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; + } + } +} diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/PolarisServiceDiscovery.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/PolarisServiceDiscovery.java index 7cbc84f50..379c7dff3 100644 --- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/PolarisServiceDiscovery.java +++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/PolarisServiceDiscovery.java @@ -69,7 +69,7 @@ public class PolarisServiceDiscovery { 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; } diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisRegistration.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisRegistration.java index dd6390403..faac451ed 100644 --- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisRegistration.java +++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisRegistration.java @@ -48,8 +48,6 @@ import static com.tencent.cloud.polaris.extend.nacos.NacosContextProperties.DEFA */ public class PolarisRegistration implements Registration { - private static final String METADATA_KEY_IP = "internal-ip"; - private static final String METADATA_KEY_ADDRESS = "internal-address"; private static final String GROUP_SERVER_ID_FORMAT = "%s__%s"; private static final String NACOS_CLUSTER = "nacos.cluster"; @@ -116,10 +114,6 @@ public class PolarisRegistration implements Registration { if (CollectionUtils.isEmpty(metadata)) { Map instanceMetadata = new HashMap<>(); - // put internal metadata - instanceMetadata.put(METADATA_KEY_IP, host); - instanceMetadata.put(METADATA_KEY_ADDRESS, host + ":" + port); - // put internal-nacos-cluster if necessary if (Objects.nonNull(nacosContextProperties)) { String clusterName = nacosContextProperties.getClusterName(); diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistry.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistry.java index 12d444a64..7c3bf8889 100644 --- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistry.java +++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistry.java @@ -44,6 +44,9 @@ import com.tencent.polaris.api.rpc.InstanceRegisterResponse; import com.tencent.polaris.api.rpc.InstancesResponse; import com.tencent.polaris.client.util.NamedThreadFactory; import com.tencent.polaris.factory.config.provider.ServiceConfigImpl; +import com.tencent.polaris.metadata.core.TransitiveType; +import com.tencent.polaris.metadata.core.constant.MetadataConstants; +import com.tencent.polaris.metadata.core.manager.CalleeMetadataContainerGroup; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -121,6 +124,14 @@ public class PolarisServiceRegistry implements ServiceRegistry metadata = serverConnectorConfig.getMetadata(); String appName = RegistrationUtil.getAppName(tsfDiscoveryProperties, context.getEnvironment()); metadata.put(ConsulConstant.MetadataMapKey.SERVICE_NAME_KEY, RegistrationUtil.normalizeForDns(appName)); - metadata.put(ConsulConstant.MetadataMapKey.INSTANCE_ID_KEY, RegistrationUtil.getInstanceId(tsfDiscoveryProperties, context)); + metadata.put(ConsulConstant.MetadataMapKey.INSTANCE_ID_KEY, RegistrationUtil.getInstanceId(tsfCoreProperties, context)); if (StringUtils.isNotBlank(tsfConsulProperties.getAclToken())) { serverConnectorConfig.setToken(tsfConsulProperties.getAclToken()); } - metadata.put(ConsulConstant.MetadataMapKey.TAGS_KEY, JacksonUtils.serialize2Json(RegistrationUtil.createTags(tsfDiscoveryProperties))); + metadata.put(ConsulConstant.MetadataMapKey.TAGS_KEY, JacksonUtils.serialize2Json(TsfUtils.createTags(tsfCoreProperties))); if (StringUtils.isNotBlank(tsfDiscoveryProperties.getDefaultQueryTag())) { metadata.put(ConsulConstant.MetadataMapKey.QUERY_TAG_KEY, tsfDiscoveryProperties.getDefaultQueryTag()); } diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/tsf/TsfDiscoveryProperties.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/tsf/TsfDiscoveryProperties.java index 9b113ec51..dc308081c 100644 --- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/tsf/TsfDiscoveryProperties.java +++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/tsf/TsfDiscoveryProperties.java @@ -24,7 +24,6 @@ import java.util.Map; import com.tencent.cloud.common.util.inet.PolarisInetUtils; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.commons.util.InetUtils; @@ -43,11 +42,6 @@ public class TsfDiscoveryProperties { private InetUtils.HostInfo hostInfo; - /** - * Tags to use when registering service. - */ - private List tags = new ArrayList<>(); - /** * If service discovery enabled. */ @@ -132,33 +126,6 @@ public class TsfDiscoveryProperties { */ private String serviceName; - /** - * Unique service instance id. - */ - @Value("${tsf_instance_id:${spring.cloud.consul.discovery.instanceId:${SPRING_CLOUD_CONSUL_DISCOVERY_INSTANCEID:}}}") - private String instanceId; - - /** - * Service instance zone. - */ - private String instanceZone; - - /** - * Service instance group. - */ - private String instanceGroup; - - /** - * Service instance zone comes from metadata. - * This allows changing the metadata tag name. - */ - private String defaultZoneMetadataName = "zone"; - - /** - * Whether to register an http or https service. - */ - private String scheme = "http"; - /** * Suffix to use when registering management service. */ @@ -214,30 +181,6 @@ public class TsfDiscoveryProperties { */ private Boolean healthCheckTlsSkipVerify; - /** - * tsf service consul registration tags. - * - * progVersion 包版本 - */ - @Value("${tsf_prog_version:}") - private String tsfProgVersion; - - /** - * tsf service consul registration tags. - * - * 地域信息 - */ - @Value("${tsf_region:}") - private String tsfRegion; - - /** - * tsf service consul registration tags. - * - * 可用区信息 - */ - @Value("${tsf_zone:}") - private String tsfZone; - /** * 有状态服务回调的线程池. */ @@ -247,7 +190,6 @@ public class TsfDiscoveryProperties { private long callbackErrorDelay = 30 * 1000L; - /** * 是否开启零实例保护,默认开启。开启时如果 consul 返回在线实例为0,用上次的缓存(正常来说线上环境不应该有provider全下线的情况). * 定制化双发现时可能需要关闭,此时如果provider下线,则返回空列表。如果 consul 连接不上则用缓存. @@ -296,14 +238,6 @@ public class TsfDiscoveryProperties { this.hostInfo = hostInfo; } - public List getTags() { - return tags; - } - - public void setTags(List tags) { - this.tags = tags; - } - public boolean isEnabled() { return enabled; } @@ -433,46 +367,6 @@ public class TsfDiscoveryProperties { this.serviceName = serviceName; } - public String getInstanceId() { - return instanceId; - } - - public void setInstanceId(String instanceId) { - this.instanceId = instanceId; - } - - public String getInstanceZone() { - return instanceZone; - } - - public void setInstanceZone(String instanceZone) { - this.instanceZone = instanceZone; - } - - public String getInstanceGroup() { - return instanceGroup; - } - - public void setInstanceGroup(String instanceGroup) { - this.instanceGroup = instanceGroup; - } - - public String getDefaultZoneMetadataName() { - return defaultZoneMetadataName; - } - - public void setDefaultZoneMetadataName(String defaultZoneMetadataName) { - this.defaultZoneMetadataName = defaultZoneMetadataName; - } - - public String getScheme() { - return scheme; - } - - public void setScheme(String scheme) { - this.scheme = scheme; - } - public String getManagementSuffix() { return managementSuffix; } @@ -553,30 +447,6 @@ public class TsfDiscoveryProperties { this.healthCheckTlsSkipVerify = healthCheckTlsSkipVerify; } - public String getTsfProgVersion() { - return tsfProgVersion; - } - - public void setTsfProgVersion(final String tsfProgVersion) { - this.tsfProgVersion = tsfProgVersion; - } - - public String getTsfRegion() { - return tsfRegion; - } - - public void setTsfRegion(final String tsfRegion) { - this.tsfRegion = tsfRegion; - } - - public String getTsfZone() { - return tsfZone; - } - - public void setTsfZone(final String tsfZone) { - this.tsfZone = tsfZone; - } - public Map getServiceMeta() { return serviceMeta; } @@ -629,7 +499,6 @@ public class TsfDiscoveryProperties { public String toString() { return "ConsulDiscoveryProperties{" + "hostInfo=" + hostInfo + - ", tags=" + tags + ", enabled=" + enabled + ", managementTags=" + managementTags + ", healthCheckPath='" + healthCheckPath + '\'' + @@ -647,11 +516,6 @@ public class TsfDiscoveryProperties { ", catalogServicesWatchDelay=" + catalogServicesWatchDelay + ", catalogServicesWatchTimeout=" + catalogServicesWatchTimeout + ", serviceName='" + serviceName + '\'' + - ", instanceId='" + instanceId + '\'' + - ", instanceZone='" + instanceZone + '\'' + - ", instanceGroup='" + instanceGroup + '\'' + - ", defaultZoneMetadataName='" + defaultZoneMetadataName + '\'' + - ", scheme='" + scheme + '\'' + ", managementSuffix='" + managementSuffix + '\'' + ", serverListQueryTags=" + serverListQueryTags + ", datacenters=" + datacenters + diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/tsf/registry/TsfDiscoveryRegistryAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/tsf/registry/TsfDiscoveryRegistryAutoConfiguration.java index 8e9cc36cf..7732a3bfb 100644 --- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/tsf/registry/TsfDiscoveryRegistryAutoConfiguration.java +++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/tsf/registry/TsfDiscoveryRegistryAutoConfiguration.java @@ -44,21 +44,14 @@ import org.springframework.context.annotation.Configuration; @ConditionalOnTsfEnabled @AutoConfigureBefore(PolarisServiceRegistryAutoConfiguration.class) public class TsfDiscoveryRegistryAutoConfiguration { - @Bean - @ConditionalOnMissingBean - public TsfMetadataPolarisRegistrationCustomizer tsfMetadataPolarisRegistrationCustomizer( - TsfCoreProperties tsfCoreProperties, TsfDiscoveryProperties tsfDiscoveryProperties) { - return new TsfMetadataPolarisRegistrationCustomizer(tsfCoreProperties, tsfDiscoveryProperties); - } - @Bean @ConditionalOnMissingBean public TsfPortPolarisRegistrationCustomizer tsfPortPolarisRegistrationCustomizer( AutoServiceRegistrationProperties autoServiceRegistrationProperties, - ApplicationContext context, TsfDiscoveryProperties tsfDiscoveryProperties, + ApplicationContext context, TsfDiscoveryProperties tsfDiscoveryProperties, TsfCoreProperties tsfCoreProperties, TsfHeartbeatProperties tsfHeartbeatProperties, PolarisSDKContextManager polarisSDKContextManager) { return new TsfPortPolarisRegistrationCustomizer(autoServiceRegistrationProperties, context, - tsfDiscoveryProperties, tsfHeartbeatProperties, polarisSDKContextManager.getSDKContext()); + tsfDiscoveryProperties, tsfCoreProperties, tsfHeartbeatProperties, polarisSDKContextManager.getSDKContext()); } @Bean diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/tsf/registry/TsfMetadataPolarisRegistrationCustomizer.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/tsf/registry/TsfMetadataPolarisRegistrationCustomizer.java deleted file mode 100644 index b152afd54..000000000 --- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/tsf/registry/TsfMetadataPolarisRegistrationCustomizer.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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.polaris.tsf.registry; - -import java.util.Map; - -import com.tencent.cloud.common.constant.SdkVersion; -import com.tencent.cloud.common.util.JacksonUtils; -import com.tencent.cloud.polaris.context.tsf.config.TsfCoreProperties; -import com.tencent.cloud.polaris.registry.PolarisRegistration; -import com.tencent.cloud.polaris.registry.PolarisRegistrationCustomizer; -import com.tencent.cloud.polaris.tsf.TsfDiscoveryProperties; -import com.tencent.cloud.polaris.tsf.consts.WarmupCons; -import com.tencent.cloud.polaris.tsf.util.RegistrationUtil; - -import static com.tencent.cloud.common.tsf.TsfConstant.TSF_APPLICATION_ID; -import static com.tencent.cloud.common.tsf.TsfConstant.TSF_GROUP_ID; -import static com.tencent.cloud.common.tsf.TsfConstant.TSF_INSTNACE_ID; -import static com.tencent.cloud.common.tsf.TsfConstant.TSF_NAMESPACE_ID; -import static com.tencent.cloud.common.tsf.TsfConstant.TSF_PROG_VERSION; -import static com.tencent.cloud.common.tsf.TsfConstant.TSF_REGION; -import static com.tencent.cloud.common.tsf.TsfConstant.TSF_SDK_VERSION; -import static com.tencent.cloud.common.tsf.TsfConstant.TSF_TAGS; -import static com.tencent.cloud.common.tsf.TsfConstant.TSF_ZONE; - -/** - * - * - * @author Haotian Zhang - */ -public class TsfMetadataPolarisRegistrationCustomizer implements PolarisRegistrationCustomizer { - - private final TsfCoreProperties tsfCoreProperties; - - private final TsfDiscoveryProperties tsfDiscoveryProperties; - - public TsfMetadataPolarisRegistrationCustomizer(TsfCoreProperties tsfCoreProperties, TsfDiscoveryProperties tsfDiscoveryProperties) { - this.tsfCoreProperties = tsfCoreProperties; - this.tsfDiscoveryProperties = tsfDiscoveryProperties; - } - - @Override - public void customize(PolarisRegistration registration) { - Map metadata = registration.getMetadata(); - - metadata.put(TSF_APPLICATION_ID, tsfCoreProperties.getTsfApplicationId()); - metadata.put(TSF_PROG_VERSION, tsfDiscoveryProperties.getTsfProgVersion()); - metadata.put(TSF_GROUP_ID, tsfCoreProperties.getTsfGroupId()); - metadata.put(TSF_NAMESPACE_ID, tsfCoreProperties.getTsfNamespaceId()); - metadata.put(TSF_INSTNACE_ID, tsfDiscoveryProperties.getInstanceId()); - metadata.put(TSF_REGION, tsfDiscoveryProperties.getTsfRegion()); - metadata.put(TSF_ZONE, tsfDiscoveryProperties.getTsfZone()); - // 处理预热相关的参数 - metadata.put(WarmupCons.TSF_START_TIME, String.valueOf(System.currentTimeMillis())); - metadata.put(TSF_SDK_VERSION, SdkVersion.get()); - metadata.put(TSF_TAGS, JacksonUtils.serialize2Json(RegistrationUtil.createTags(tsfDiscoveryProperties))); - RegistrationUtil.appendMetaIpAddress(metadata); - } -} diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/tsf/registry/TsfPortPolarisRegistrationCustomizer.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/tsf/registry/TsfPortPolarisRegistrationCustomizer.java index 65372d5a1..8312c2f1b 100644 --- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/tsf/registry/TsfPortPolarisRegistrationCustomizer.java +++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/tsf/registry/TsfPortPolarisRegistrationCustomizer.java @@ -17,6 +17,7 @@ package com.tencent.cloud.polaris.tsf.registry; +import com.tencent.cloud.polaris.context.tsf.config.TsfCoreProperties; import com.tencent.cloud.polaris.registry.PolarisRegistration; import com.tencent.cloud.polaris.registry.PolarisRegistrationCustomizer; import com.tencent.cloud.polaris.tsf.TsfDiscoveryProperties; @@ -37,15 +38,17 @@ public class TsfPortPolarisRegistrationCustomizer implements PolarisRegistration private final AutoServiceRegistrationProperties autoServiceRegistrationProperties; private final ApplicationContext context; private final TsfDiscoveryProperties tsfDiscoveryProperties; + private final TsfCoreProperties tsfCoreProperties; private final TsfHeartbeatProperties tsfHeartbeatProperties; private final SDKContext sdkContext; public TsfPortPolarisRegistrationCustomizer(AutoServiceRegistrationProperties autoServiceRegistrationProperties, - ApplicationContext context, TsfDiscoveryProperties tsfDiscoveryProperties, + ApplicationContext context, TsfDiscoveryProperties tsfDiscoveryProperties, TsfCoreProperties tsfCoreProperties, TsfHeartbeatProperties tsfHeartbeatProperties, SDKContext sdkContext) { this.autoServiceRegistrationProperties = autoServiceRegistrationProperties; this.context = context; this.tsfDiscoveryProperties = tsfDiscoveryProperties; + this.tsfCoreProperties = tsfCoreProperties; this.tsfHeartbeatProperties = tsfHeartbeatProperties; this.sdkContext = sdkContext; } @@ -56,7 +59,7 @@ public class TsfPortPolarisRegistrationCustomizer implements PolarisRegistration registration.setPort(tsfDiscoveryProperties.getPort()); } // we know the port and can set the check - RegistrationUtil.setCheck(autoServiceRegistrationProperties, tsfDiscoveryProperties, context, + RegistrationUtil.setCheck(autoServiceRegistrationProperties, tsfDiscoveryProperties, tsfCoreProperties, context, tsfHeartbeatProperties, registration, sdkContext.getConfig()); } } diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/tsf/util/RegistrationUtil.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/tsf/util/RegistrationUtil.java index bb95c8d83..a9c55b7fb 100644 --- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/tsf/util/RegistrationUtil.java +++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/tsf/util/RegistrationUtil.java @@ -17,14 +17,12 @@ package com.tencent.cloud.polaris.tsf.util; -import java.util.LinkedList; -import java.util.List; import java.util.Map; import com.ecwid.consul.v1.agent.model.NewService; import com.tencent.cloud.common.util.AddressUtils; import com.tencent.cloud.common.util.JacksonUtils; -import com.tencent.cloud.common.util.inet.PolarisInetUtils; +import com.tencent.cloud.polaris.context.tsf.config.TsfCoreProperties; import com.tencent.cloud.polaris.tsf.TsfDiscoveryProperties; import com.tencent.cloud.polaris.tsf.TsfHeartbeatProperties; import com.tencent.polaris.api.config.Configuration; @@ -58,15 +56,6 @@ public final class RegistrationUtil { */ public static final String ID = "consul"; private static final Logger LOGGER = LoggerFactory.getLogger(RegistrationUtil.class); - /** - * IPV4. - */ - public static String TSF_ADDRESS_IPV4 = "TSF_ADDRESS_IPV4"; - - /** - * IPV6. - */ - public static String TSF_ADDRESS_IPV6 = "TSF_ADDRESS_IPV6"; private RegistrationUtil() { } @@ -79,7 +68,7 @@ public final class RegistrationUtil { return env.getProperty("spring.application.name", "application"); } - public static String getInstanceId(TsfDiscoveryProperties properties, ApplicationContext context) { + public static String getInstanceId(TsfCoreProperties properties, ApplicationContext context) { // tsf consul 不支持 dns,所以这里不需要 normalize,并且由于优雅下线,readiness probe 联动都是依赖 service id 的,normalize 后两边对不上,所以需要去掉 normalize if (!StringUtils.hasText(properties.getInstanceId())) { return IdUtils.getDefaultInstanceId(context.getEnvironment(), false); @@ -123,40 +112,8 @@ public final class RegistrationUtil { return normalized.toString(); } - public static List createTags(TsfDiscoveryProperties properties) { - List tags = new LinkedList<>(properties.getTags()); - - if (StringUtils.hasText(properties.getInstanceZone())) { - tags.add(properties.getDefaultZoneMetadataName() + "=" + properties.getInstanceZone()); - } - if (StringUtils.hasText(properties.getInstanceGroup())) { - tags.add("group=" + properties.getInstanceGroup()); - } - - //store the secure flag in the tags so that clients will be able to figure out whether to use http or https automatically - tags.add("secure=" + properties.getScheme().equalsIgnoreCase("https")); - - return tags; - } - - public static Map appendMetaIpAddress(Map meta) { - if (meta == null) { - return null; - } - String ipv4Address = PolarisInetUtils.getIpString(false); - if (ipv4Address != null) { - meta.put(TSF_ADDRESS_IPV4, ipv4Address); - } - - String ipv6Address = PolarisInetUtils.getIpString(true); - if (ipv6Address != null) { - meta.put(TSF_ADDRESS_IPV6, ipv6Address); - } - return meta; - } - public static void setCheck(AutoServiceRegistrationProperties autoServiceRegistrationProperties, - TsfDiscoveryProperties properties, ApplicationContext context, + TsfDiscoveryProperties properties, TsfCoreProperties tsfCoreProperties, ApplicationContext context, TsfHeartbeatProperties tsfHeartbeatProperties, Registration registration, Configuration configuration) { if (properties.isRegisterHealthCheck()) { Integer checkPort; @@ -171,7 +128,7 @@ public final class RegistrationUtil { for (ServerConnectorConfigImpl config : configuration.getGlobal().getServerConnectors()) { if (org.apache.commons.lang.StringUtils.equals(config.getId(), ID)) { Map metadata = config.getMetadata(); - NewService.Check check = createCheck(checkPort, tsfHeartbeatProperties, properties); + NewService.Check check = createCheck(checkPort, tsfHeartbeatProperties, properties, tsfCoreProperties); String checkJson = JacksonUtils.serialize2Json(check); LOGGER.debug("Check is : {}", checkJson); metadata.put(ConsulConstant.MetadataMapKey.CHECK_KEY, checkJson); @@ -182,7 +139,7 @@ public final class RegistrationUtil { } public static NewService.Check createCheck(Integer port, TsfHeartbeatProperties ttlConfig, - TsfDiscoveryProperties properties) { + TsfDiscoveryProperties properties, TsfCoreProperties tsfCoreProperties) { NewService.Check check = new NewService.Check(); if (ttlConfig.isEnabled()) { check.setTtl(ttlConfig.getTtl()); @@ -196,7 +153,7 @@ public final class RegistrationUtil { check.setHttp(properties.getHealthCheckUrl()); } else { - check.setHttp(String.format("%s://%s:%s%s", properties.getScheme(), + check.setHttp(String.format("%s://%s:%s%s", tsfCoreProperties.getScheme(), AddressUtils.getIpCompatible(properties.getHostname()), port, properties.getHealthCheckPath())); } diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/registry/PolarisRegistrationTest.java b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/registry/PolarisRegistrationTest.java index d6d7c1e99..73231a6a6 100644 --- a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/registry/PolarisRegistrationTest.java +++ b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/registry/PolarisRegistrationTest.java @@ -181,7 +181,7 @@ public class PolarisRegistrationTest { Map metadata = polarisRegistration1.getMetadata(); assertThat(metadata).isNotNull(); assertThat(metadata).isNotEmpty(); - assertThat(metadata.size()).isEqualTo(4); + assertThat(metadata.size()).isEqualTo(2); assertThat(metadata.get("key1")).isEqualTo("value1"); } @@ -211,7 +211,7 @@ public class PolarisRegistrationTest { Map metadata = polarisRegistration1.getMetadata(); assertThat(metadata).isNotNull(); assertThat(metadata).isNotEmpty(); - assertThat(metadata.size()).isEqualTo(4); + assertThat(metadata.size()).isEqualTo(2); assertThat(metadata.get("nacos.cluster")).isEqualTo(clusterName); } } diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisRouterContext.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisRouterContext.java index 0061758fd..f27c3deb2 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisRouterContext.java +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisRouterContext.java @@ -18,10 +18,8 @@ package com.tencent.cloud.polaris.router; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -79,25 +77,6 @@ public class PolarisRouterContext { return routerLabels.get(labelKey); } - public Set getLabelAsSet(String labelKey) { - Map routerLabels = labels.get(RouterConstant.ROUTER_LABELS); - if (CollectionUtils.isEmpty(routerLabels)) { - return Collections.emptySet(); - } - - for (Map.Entry entry : routerLabels.entrySet()) { - if (StringUtils.equalsIgnoreCase(labelKey, entry.getKey())) { - String keysStr = entry.getValue(); - if (StringUtils.isNotBlank(keysStr)) { - String[] keysArr = StringUtils.split(keysStr, ","); - return new HashSet<>(Arrays.asList(keysArr)); - } - } - } - - return Collections.emptySet(); - } - public void putLabels(String labelType, Map subLabels) { if (this.labels == null) { this.labels = new HashMap<>(); diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisRouterServiceInstanceListSupplier.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisRouterServiceInstanceListSupplier.java index daa911a70..62fd8f7f9 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisRouterServiceInstanceListSupplier.java +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisRouterServiceInstanceListSupplier.java @@ -32,7 +32,6 @@ import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.metadata.MetadataContextHolder; import com.tencent.cloud.common.pojo.PolarisServiceInstance; import com.tencent.cloud.common.util.JacksonUtils; -import com.tencent.cloud.polaris.router.resttemplate.PolarisLoadBalancerRequest; import com.tencent.cloud.polaris.router.spi.RouterRequestInterceptor; import com.tencent.cloud.polaris.router.spi.RouterResponseInterceptor; import com.tencent.cloud.rpc.enhancement.transformer.InstanceTransformer; @@ -100,14 +99,9 @@ public class PolarisRouterServiceInstanceListSupplier extends DelegatingServiceI PolarisRouterContext routerContext = null; DefaultRequestContext requestContext = (DefaultRequestContext) request.getContext(); - if (requestContext != null) { - if (requestContext instanceof RequestDataContext) { - routerContext = buildRouterContext(((RequestDataContext) requestContext).getClientRequest().getHeaders()); - } - else if (requestContext.getClientRequest() instanceof PolarisLoadBalancerRequest) { - routerContext = buildRouterContext(((PolarisLoadBalancerRequest) requestContext.getClientRequest()).getRequest() - .getHeaders()); - } + if (requestContext instanceof RequestDataContext) { + routerContext = buildRouterContext(((RequestDataContext) requestContext).getClientRequest() + .getHeaders()); } if (routerContext == null) { @@ -120,15 +114,11 @@ public class PolarisRouterServiceInstanceListSupplier extends DelegatingServiceI PolarisRouterContext buildRouterContext(HttpHeaders headers) { Collection labelHeaderValues = headers.get(RouterConstant.ROUTER_LABEL_HEADER); - if (CollectionUtils.isEmpty(labelHeaderValues)) { - return null; + labelHeaderValues = new ArrayList<>(); } - PolarisRouterContext routerContext = new PolarisRouterContext(); - routerContext.putLabels(RouterConstant.TRANSITIVE_LABELS, MetadataContextHolder.get().getTransitiveMetadata()); - Map labelHeaderValuesMap = new HashMap<>(); try { Optional labelHeaderValuesOptional = labelHeaderValues.stream().findFirst(); @@ -178,6 +168,7 @@ public class PolarisRouterServiceInstanceListSupplier extends DelegatingServiceI serviceInfo.setNamespace(MetadataContext.LOCAL_NAMESPACE); serviceInfo.setService(MetadataContext.LOCAL_SERVICE); processRoutersRequest.setSourceService(serviceInfo); + processRoutersRequest.setMetadataContainerGroup(MetadataContextHolder.get().getMetadataContainerGroup(false)); return processRoutersRequest; } diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/RouterRuleLabelResolver.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/RouterRuleLabelResolver.java deleted file mode 100644 index 0b277332d..000000000 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/RouterRuleLabelResolver.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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.polaris.router; - -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import com.tencent.cloud.common.util.expresstion.ExpressionLabelUtils; -import com.tencent.cloud.polaris.context.ServiceRuleManager; -import com.tencent.polaris.specification.api.v1.model.ModelProto; -import com.tencent.polaris.specification.api.v1.traffic.manage.RoutingProto; - -import org.springframework.util.CollectionUtils; - -/** - * Resolve label expressions from routing rules. - * - * @author lepdou 2022-05-19 - */ -public class RouterRuleLabelResolver { - - private final ServiceRuleManager serviceRuleManager; - - public RouterRuleLabelResolver(ServiceRuleManager serviceRuleManager) { - this.serviceRuleManager = serviceRuleManager; - } - - public Set getExpressionLabelKeys(String namespace, String sourceService, String dstService) { - List rules = serviceRuleManager.getServiceRouterRule(namespace, sourceService, dstService); - - if (CollectionUtils.isEmpty(rules)) { - return Collections.emptySet(); - } - - Set expressionLabels = new HashSet<>(); - - for (RoutingProto.Route rule : rules) { - List sources = rule.getSourcesList(); - if (CollectionUtils.isEmpty(sources)) { - continue; - } - for (RoutingProto.Source source : sources) { - Map labels = source.getMetadataMap(); - if (CollectionUtils.isEmpty(labels)) { - continue; - } - for (String labelKey : labels.keySet()) { - if (ExpressionLabelUtils.isExpressionLabel(labelKey)) { - expressionLabels.add(labelKey); - } - } - } - } - - return expressionLabels; - } -} diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/RouterUtils.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/RouterUtils.java index e79a1efd8..5ddcacfe3 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/RouterUtils.java +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/RouterUtils.java @@ -19,7 +19,9 @@ package com.tencent.cloud.polaris.router; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; @@ -64,12 +66,14 @@ public final class RouterUtils { .collect(Collectors.toList()))).subscribe(instance -> instanceList.add((Instance) instance)); String serviceName = ""; + Map serviceMetadata = new HashMap<>(); if (!CollectionUtils.isEmpty(instanceList)) { serviceName = instanceList.get(0).getService(); + serviceMetadata = instanceList.get(0).getServiceMetadata(); } ServiceKey serviceKey = new ServiceKey(MetadataContext.LOCAL_NAMESPACE, serviceName); - return new DefaultServiceInstances(serviceKey, instanceList); + return new DefaultServiceInstances(serviceKey, instanceList, serviceMetadata); } } diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/beanprocessor/LoadBalancerInterceptorBeanPostProcessor.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/beanprocessor/LoadBalancerInterceptorBeanPostProcessor.java deleted file mode 100644 index 29df08d7b..000000000 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/beanprocessor/LoadBalancerInterceptorBeanPostProcessor.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.polaris.router.beanprocessor; - -import com.tencent.cloud.polaris.router.resttemplate.PolarisLoadBalancerInterceptor; - -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryAware; -import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; -import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor; -import org.springframework.cloud.client.loadbalancer.LoadBalancerRequestFactory; - -/** - * Replace LoadBalancerInterceptor with PolarisLoadBalancerInterceptor. - * PolarisLoadBalancerInterceptor can pass routing context information. - * - *@author lepdou 2022-05-18 - */ -public class LoadBalancerInterceptorBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware { - - private BeanFactory factory; - - @Override - public void setBeanFactory(BeanFactory beanFactory) throws BeansException { - this.factory = beanFactory; - } - - @Override - public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { - if (bean instanceof LoadBalancerInterceptor) { - LoadBalancerRequestFactory requestFactory = this.factory.getBean(LoadBalancerRequestFactory.class); - LoadBalancerClient loadBalancerClient = this.factory.getBean(LoadBalancerClient.class); - - return new PolarisLoadBalancerInterceptor(loadBalancerClient, requestFactory); - } - return bean; - } -} diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/beanprocessor/ReactiveLoadBalancerClientFilterBeanPostProcessor.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/beanprocessor/ReactiveLoadBalancerClientFilterBeanPostProcessor.java deleted file mode 100644 index eb2b9d66f..000000000 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/beanprocessor/ReactiveLoadBalancerClientFilterBeanPostProcessor.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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.polaris.router.beanprocessor; - -import java.util.List; - -import com.tencent.cloud.common.metadata.StaticMetadataManager; -import com.tencent.cloud.common.util.BeanFactoryUtils; -import com.tencent.cloud.polaris.context.config.PolarisContextProperties; -import com.tencent.cloud.polaris.router.RouterRuleLabelResolver; -import com.tencent.cloud.polaris.router.scg.PolarisReactiveLoadBalancerClientFilter; -import com.tencent.cloud.polaris.router.spi.SpringWebRouterLabelResolver; - -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryAware; -import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.cloud.client.loadbalancer.LoadBalancerProperties; -import org.springframework.cloud.gateway.config.GatewayLoadBalancerProperties; -import org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter; -import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory; - -/** - * Replaced ReactiveLoadBalancerClientFilter with PolarisReactiveLoadBalancerClientFilter during creating bean phase. - * - * @author lepdou 2022-06-20 - */ -public class ReactiveLoadBalancerClientFilterBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware { - - private BeanFactory factory; - - @Override - public void setBeanFactory(BeanFactory beanFactory) throws BeansException { - this.factory = beanFactory; - } - - @Override - public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { - // Support spring cloud gateway router. - // Replaces the default ReactiveLoadBalancerClientFilter implementation - // and returns a custom PolarisReactiveLoadBalancerClientFilter - if (bean instanceof ReactiveLoadBalancerClientFilter) { - LoadBalancerClientFactory loadBalancerClientFactory = this.factory.getBean(LoadBalancerClientFactory.class); - GatewayLoadBalancerProperties gatewayLoadBalancerProperties = this.factory.getBean(GatewayLoadBalancerProperties.class); - LoadBalancerProperties loadBalancerProperties = this.factory.getBean(LoadBalancerProperties.class); - List routerLabelResolvers = BeanFactoryUtils.getBeans(factory, SpringWebRouterLabelResolver.class); - StaticMetadataManager staticMetadataManager = this.factory.getBean(StaticMetadataManager.class); - RouterRuleLabelResolver routerRuleLabelResolver = this.factory.getBean(RouterRuleLabelResolver.class); - PolarisContextProperties polarisContextProperties = this.factory.getBean(PolarisContextProperties.class); - - return new PolarisReactiveLoadBalancerClientFilter( - loadBalancerClientFactory, gatewayLoadBalancerProperties, loadBalancerProperties, - staticMetadataManager, routerRuleLabelResolver, routerLabelResolvers, polarisContextProperties); - } - return bean; - } -} diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/FeignAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/FeignAutoConfiguration.java index fef47e170..bd03625fd 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/FeignAutoConfiguration.java +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/FeignAutoConfiguration.java @@ -18,18 +18,11 @@ package com.tencent.cloud.polaris.router.config; -import java.util.List; - -import com.tencent.cloud.common.metadata.StaticMetadataManager; -import com.tencent.cloud.polaris.context.config.PolarisContextProperties; -import com.tencent.cloud.polaris.router.RouterRuleLabelResolver; import com.tencent.cloud.polaris.router.feign.RouterLabelFeignInterceptor; -import com.tencent.cloud.polaris.router.spi.FeignRouterLabelResolver; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.lang.Nullable; @Configuration(proxyBeanMethods = false) @ConditionalOnPolarisRouterEnabled @@ -37,10 +30,7 @@ import org.springframework.lang.Nullable; public class FeignAutoConfiguration { @Bean - public RouterLabelFeignInterceptor routerLabelInterceptor(@Nullable List routerLabelResolvers, - StaticMetadataManager staticMetadataManager, - RouterRuleLabelResolver routerRuleLabelResolver, - PolarisContextProperties polarisContextProperties) { - return new RouterLabelFeignInterceptor(routerLabelResolvers, staticMetadataManager, routerRuleLabelResolver, polarisContextProperties); + public RouterLabelFeignInterceptor routerLabelInterceptor() { + return new RouterLabelFeignInterceptor(); } } diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RouterAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RouterAutoConfiguration.java index 9cc2d14a1..b052aab22 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RouterAutoConfiguration.java +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RouterAutoConfiguration.java @@ -22,12 +22,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import com.tencent.cloud.common.metadata.StaticMetadataManager; -import com.tencent.cloud.polaris.context.ServiceRuleManager; -import com.tencent.cloud.polaris.context.config.PolarisContextProperties; -import com.tencent.cloud.polaris.router.RouterRuleLabelResolver; -import com.tencent.cloud.polaris.router.beanprocessor.LoadBalancerInterceptorBeanPostProcessor; -import com.tencent.cloud.polaris.router.beanprocessor.ReactiveLoadBalancerClientFilterBeanPostProcessor; import com.tencent.cloud.polaris.router.config.properties.PolarisMetadataRouterProperties; import com.tencent.cloud.polaris.router.config.properties.PolarisNearByRouterProperties; import com.tencent.cloud.polaris.router.config.properties.PolarisRuleBasedRouterProperties; @@ -35,7 +29,7 @@ import com.tencent.cloud.polaris.router.interceptor.MetadataRouterRequestInterce import com.tencent.cloud.polaris.router.interceptor.NearbyRouterRequestInterceptor; import com.tencent.cloud.polaris.router.interceptor.RuleBasedRouterRequestInterceptor; import com.tencent.cloud.polaris.router.resttemplate.RouterLabelRestTemplateInterceptor; -import com.tencent.cloud.polaris.router.spi.SpringWebRouterLabelResolver; +import com.tencent.cloud.polaris.router.scg.RouterLabelGlobalFilter; import com.tencent.cloud.rpc.enhancement.resttemplate.EnhancedRestTemplateInterceptor; import org.springframework.beans.factory.SmartInitializingSingleton; @@ -45,41 +39,19 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.core.annotation.Order; import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.web.client.RestTemplate; -import static org.springframework.core.Ordered.HIGHEST_PRECEDENCE; - /** * configuration for router module singleton beans. * - * @author lepdou 2022-05-11 + *@author lepdou 2022-05-11 */ @Configuration(proxyBeanMethods = false) @ConditionalOnPolarisRouterEnabled @LoadBalancerClients(defaultConfiguration = LoadBalancerConfiguration.class) public class RouterAutoConfiguration { - @Bean - @Order(HIGHEST_PRECEDENCE) - @ConditionalOnClass(name = "org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor") - public LoadBalancerInterceptorBeanPostProcessor loadBalancerInterceptorBeanPostProcessor() { - return new LoadBalancerInterceptorBeanPostProcessor(); - } - - @Bean - @Order(HIGHEST_PRECEDENCE) - @ConditionalOnClass(name = "org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter") - public ReactiveLoadBalancerClientFilterBeanPostProcessor loadBalancerClientFilterBeanPostProcessor() { - return new ReactiveLoadBalancerClientFilterBeanPostProcessor(); - } - - @Bean - public RouterRuleLabelResolver routerRuleLabelResolver(ServiceRuleManager serviceRuleManager) { - return new RouterRuleLabelResolver(serviceRuleManager); - } - @Bean @ConditionalOnProperty(value = "spring.cloud.polaris.router.metadata-router.enabled", matchIfMissing = true) public MetadataRouterRequestInterceptor metadataRouterRequestInterceptor(PolarisMetadataRouterProperties polarisMetadataRouterProperties) { @@ -98,6 +70,21 @@ public class RouterAutoConfiguration { return new RuleBasedRouterRequestInterceptor(polarisRuleBasedRouterProperties); } + + /** + * Create when gateway application is SCG. + */ + @Configuration(proxyBeanMethods = false) + @ConditionalOnClass(name = "org.springframework.cloud.gateway.filter.GlobalFilter") + protected static class RouterLabelScgFilterConfig { + + @Bean + public RouterLabelGlobalFilter routerLabelGlobalFilter() { + return new RouterLabelGlobalFilter(); + } + + } + /** * Create when RestTemplate exists. * @author liuye 2022-09-14 @@ -111,13 +98,8 @@ public class RouterAutoConfiguration { private List restTemplates = Collections.emptyList(); @Bean - public RouterLabelRestTemplateInterceptor routerLabelRestTemplateInterceptor( - List routerLabelResolvers, - StaticMetadataManager staticMetadataManager, - RouterRuleLabelResolver routerRuleLabelResolver, - PolarisContextProperties polarisContextProperties) { - return new RouterLabelRestTemplateInterceptor(routerLabelResolvers, staticMetadataManager, - routerRuleLabelResolver, polarisContextProperties); + public RouterLabelRestTemplateInterceptor routerLabelRestTemplateInterceptor() { + return new RouterLabelRestTemplateInterceptor(); } @Bean diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/properties/PolarisRuleBasedRouterProperties.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/properties/PolarisRuleBasedRouterProperties.java index 9ad4c8ef0..e9ecceabf 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/properties/PolarisRuleBasedRouterProperties.java +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/properties/PolarisRuleBasedRouterProperties.java @@ -17,6 +17,8 @@ package com.tencent.cloud.polaris.router.config.properties; +import com.tencent.polaris.api.rpc.RuleBasedRouterFailoverType; + import org.springframework.boot.context.properties.ConfigurationProperties; /** @@ -29,6 +31,8 @@ public class PolarisRuleBasedRouterProperties { private boolean enabled = true; + private RuleBasedRouterFailoverType failOver = RuleBasedRouterFailoverType.all; + public boolean isEnabled() { return enabled; } @@ -37,10 +41,19 @@ public class PolarisRuleBasedRouterProperties { this.enabled = enabled; } + public RuleBasedRouterFailoverType getFailOver() { + return failOver; + } + + public void setFailOver(RuleBasedRouterFailoverType failOver) { + this.failOver = failOver; + } + @Override public String toString() { - return "PolarisNearByRouterProperties{" + + return "PolarisRuleBasedRouterProperties{" + "enabled=" + enabled + + ", failOver=" + failOver + '}'; } } diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/FeignExpressionLabelUtils.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/FeignExpressionLabelUtils.java deleted file mode 100644 index 849d563c6..000000000 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/FeignExpressionLabelUtils.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * 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.polaris.router.feign; - -import java.net.URI; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -import com.tencent.cloud.common.util.expresstion.ExpressionLabelUtils; -import feign.RequestTemplate; -import org.apache.commons.lang.StringUtils; - -import org.springframework.util.CollectionUtils; - -/** - * Resolve rule expression label from feign request. - * - * @author lepdou 2022-05-20 - */ -public final class FeignExpressionLabelUtils { - - private FeignExpressionLabelUtils() { - } - - public static Map resolve(RequestTemplate request, Set labelKeys) { - if (CollectionUtils.isEmpty(labelKeys)) { - return Collections.emptyMap(); - } - - Map labels = new HashMap<>(); - - for (String labelKey : labelKeys) { - if (ExpressionLabelUtils.isHeaderLabel(labelKey)) { - String headerKey = ExpressionLabelUtils.parseHeaderKey(labelKey); - if (StringUtils.isBlank(headerKey)) { - continue; - } - labels.put(labelKey, getHeaderValue(request, headerKey)); - } - else if (ExpressionLabelUtils.isQueryLabel(labelKey)) { - String queryKey = ExpressionLabelUtils.parseQueryKey(labelKey); - if (StringUtils.isBlank(queryKey)) { - continue; - } - labels.put(labelKey, getQueryValue(request, queryKey)); - } - else if (ExpressionLabelUtils.isCookieLabel(labelKey)) { - String cookieKey = ExpressionLabelUtils.parseCookieKey(labelKey); - if (StringUtils.isBlank(cookieKey)) { - continue; - } - labels.put(labelKey, getCookieValue(request, cookieKey)); - } - else if (ExpressionLabelUtils.isMethodLabel(labelKey)) { - labels.put(labelKey, request.method()); - } - else if (ExpressionLabelUtils.isUriLabel(labelKey)) { - URI uri = URI.create(request.request().url()); - labels.put(labelKey, uri.getPath()); - } - } - - return labels; - } - - public static String getHeaderValue(RequestTemplate request, String key) { - Map> headers = request.headers(); - return ExpressionLabelUtils.getFirstValue(headers, key); - } - - public static String getQueryValue(RequestTemplate request, String key) { - return ExpressionLabelUtils.getFirstValue(request.queries(), key); - } - - public static String getCookieValue(RequestTemplate request, String key) { - Map> headers = request.headers(); - return ExpressionLabelUtils.getCookieFirstValue(headers, key); - } -} diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/RouterLabelFeignInterceptor.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/RouterLabelFeignInterceptor.java index 80e66892a..eda50162f 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/RouterLabelFeignInterceptor.java +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/RouterLabelFeignInterceptor.java @@ -18,63 +18,21 @@ package com.tencent.cloud.polaris.router.feign; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - import com.tencent.cloud.common.constant.OrderConstant; -import com.tencent.cloud.common.constant.RouterConstant; -import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.metadata.MetadataContextHolder; -import com.tencent.cloud.common.metadata.StaticMetadataManager; -import com.tencent.cloud.common.util.JacksonUtils; -import com.tencent.cloud.common.util.expresstion.ExpressionLabelUtils; -import com.tencent.cloud.polaris.context.config.PolarisContextProperties; -import com.tencent.cloud.polaris.router.RouterRuleLabelResolver; -import com.tencent.cloud.polaris.router.spi.FeignRouterLabelResolver; +import com.tencent.cloud.metadata.provider.FeignRequestTemplateMetadataProvider; +import com.tencent.polaris.metadata.core.MetadataType; import feign.RequestInterceptor; import feign.RequestTemplate; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.core.Ordered; -import org.springframework.util.CollectionUtils; - -import static com.tencent.cloud.common.constant.ContextConstant.UTF_8; /** - * Resolver labels from request. + * Interceptor used for setting Feign RequestTemplate metadata provider. * * @author lepdou, cheese8, Hoatian Zhang */ public class RouterLabelFeignInterceptor implements RequestInterceptor, Ordered { - private static final Logger LOGGER = LoggerFactory.getLogger(RouterLabelFeignInterceptor.class); - - private final List routerLabelResolvers; - private final StaticMetadataManager staticMetadataManager; - private final RouterRuleLabelResolver routerRuleLabelResolver; - private final PolarisContextProperties polarisContextProperties; - - public RouterLabelFeignInterceptor(List routerLabelResolvers, - StaticMetadataManager staticMetadataManager, - RouterRuleLabelResolver routerRuleLabelResolver, - PolarisContextProperties polarisContextProperties) { - if (!CollectionUtils.isEmpty(routerLabelResolvers)) { - routerLabelResolvers.sort(Comparator.comparingInt(Ordered::getOrder)); - this.routerLabelResolvers = routerLabelResolvers; - } - else { - this.routerLabelResolvers = null; - } - this.staticMetadataManager = staticMetadataManager; - this.routerRuleLabelResolver = routerRuleLabelResolver; - this.polarisContextProperties = polarisContextProperties; - } @Override public int getOrder() { @@ -83,62 +41,7 @@ public class RouterLabelFeignInterceptor implements RequestInterceptor, Ordered @Override public void apply(RequestTemplate requestTemplate) { - // local service labels - Map labels = new HashMap<>(staticMetadataManager.getMergedStaticMetadata()); - - // labels from rule expression - String peerServiceName = requestTemplate.feignTarget().name(); - Set expressionLabelKeys = routerRuleLabelResolver.getExpressionLabelKeys(MetadataContext.LOCAL_NAMESPACE, - MetadataContext.LOCAL_SERVICE, peerServiceName); - - Map ruleExpressionLabels = getRuleExpressionLabels(requestTemplate, expressionLabelKeys); - labels.putAll(ruleExpressionLabels); - - // labels from custom spi - if (!CollectionUtils.isEmpty(routerLabelResolvers)) { - routerLabelResolvers.forEach(resolver -> { - try { - Map customResolvedLabels = resolver.resolve(requestTemplate, expressionLabelKeys); - if (!CollectionUtils.isEmpty(customResolvedLabels)) { - labels.putAll(customResolvedLabels); - } - } - catch (Throwable t) { - LOGGER.error("[SCT][Router] revoke RouterLabelResolver occur some exception. ", t); - } - }); - } - - // labels from downstream - Map transitiveLabels = MetadataContextHolder.get().getTransitiveMetadata(); - labels.putAll(transitiveLabels); - - // pass label by header - String encodedLabelsContent; - try { - encodedLabelsContent = URLEncoder.encode(JacksonUtils.serialize2Json(labels), UTF_8); - } - catch (UnsupportedEncodingException e) { - throw new RuntimeException("unsupported charset exception " + UTF_8); - } - requestTemplate.header(RouterConstant.ROUTER_LABEL_HEADER, encodedLabelsContent); - } - - private Map getRuleExpressionLabels(RequestTemplate requestTemplate, Set labelKeys) { - if (CollectionUtils.isEmpty(labelKeys)) { - return Collections.emptyMap(); - } - - //enrich labels from request - Map labels = FeignExpressionLabelUtils.resolve(requestTemplate, labelKeys); - - //enrich caller ip label - for (String labelKey : labelKeys) { - if (ExpressionLabelUtils.isCallerIPLabel(labelKey)) { - labels.put(labelKey, polarisContextProperties.getLocalIpAddress()); - } - } - - return labels; + MetadataContextHolder.get().getMetadataContainer(MetadataType.MESSAGE, false) + .setMetadataProvider(new FeignRequestTemplateMetadataProvider(requestTemplate)); } } diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/interceptor/MetadataRouterRequestInterceptor.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/interceptor/MetadataRouterRequestInterceptor.java index e8de0fa29..3a97f7624 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/interceptor/MetadataRouterRequestInterceptor.java +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/interceptor/MetadataRouterRequestInterceptor.java @@ -18,20 +18,16 @@ package com.tencent.cloud.polaris.router.interceptor; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import com.tencent.cloud.common.constant.RouterConstant; +import com.tencent.cloud.common.metadata.MetadataContextHolder; import com.tencent.cloud.polaris.router.PolarisRouterContext; import com.tencent.cloud.polaris.router.config.properties.PolarisMetadataRouterProperties; import com.tencent.cloud.polaris.router.spi.RouterRequestInterceptor; -import com.tencent.polaris.api.pojo.RouteArgument; +import com.tencent.polaris.metadata.core.MetadataContainer; +import com.tencent.polaris.metadata.core.MetadataType; +import com.tencent.polaris.metadata.core.TransitiveType; import com.tencent.polaris.plugins.router.metadata.MetadataRouter; import com.tencent.polaris.router.api.rpc.ProcessRoutersRequest; -import org.springframework.util.CollectionUtils; - /** * Router request interceptor for metadata router. * @author lepdou, Hoatian Zhang @@ -51,18 +47,10 @@ public class MetadataRouterRequestInterceptor implements RouterRequestIntercepto return; } - // 1. get metadata router label keys - Set metadataRouterKeys = routerContext.getLabelAsSet(LABEL_KEY_METADATA_ROUTER_KEYS); - // 2. get metadata router labels - Map metadataRouterLabels = routerContext.getLabels(RouterConstant.ROUTER_LABELS, - metadataRouterKeys); - // 3. set metadata router labels to request - Set routeArguments = new HashSet<>(); - if (!CollectionUtils.isEmpty(metadataRouterKeys)) { - for (Map.Entry entry : metadataRouterLabels.entrySet()) { - routeArguments.add(RouteArgument.fromLabel(entry.getKey(), entry.getValue())); - } - } - request.putRouterArgument(MetadataRouter.ROUTER_TYPE_METADATA, routeArguments); + // set metadata router label keys + MetadataContainer metadataContainer = MetadataContextHolder.get() + .getMetadataContainer(MetadataType.CUSTOM, false); + String metadataRouteKeys = metadataContainer.getRawMetadataStringValue(LABEL_KEY_METADATA_ROUTER_KEYS); + metadataContainer.putMetadataMapValue(MetadataRouter.ROUTER_TYPE_METADATA, MetadataRouter.KEY_METADATA_KEYS, metadataRouteKeys, TransitiveType.NONE); } } diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/interceptor/NearbyRouterRequestInterceptor.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/interceptor/NearbyRouterRequestInterceptor.java index ca59f7788..6d40e0c55 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/interceptor/NearbyRouterRequestInterceptor.java +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/interceptor/NearbyRouterRequestInterceptor.java @@ -18,13 +18,13 @@ package com.tencent.cloud.polaris.router.interceptor; -import java.util.HashSet; -import java.util.Set; - +import com.tencent.cloud.common.metadata.MetadataContextHolder; import com.tencent.cloud.polaris.router.PolarisRouterContext; import com.tencent.cloud.polaris.router.config.properties.PolarisNearByRouterProperties; import com.tencent.cloud.polaris.router.spi.RouterRequestInterceptor; -import com.tencent.polaris.api.pojo.RouteArgument; +import com.tencent.polaris.metadata.core.MetadataContainer; +import com.tencent.polaris.metadata.core.MetadataType; +import com.tencent.polaris.metadata.core.TransitiveType; import com.tencent.polaris.plugins.router.nearby.NearbyRouter; import com.tencent.polaris.router.api.rpc.ProcessRoutersRequest; @@ -42,13 +42,10 @@ public class NearbyRouterRequestInterceptor implements RouterRequestInterceptor @Override public void apply(ProcessRoutersRequest request, PolarisRouterContext routerContext) { - if (!polarisNearByRouterProperties.isEnabled()) { - return; - } - - Set routeArguments = new HashSet<>(1); - routeArguments.add(RouteArgument.buildCustom(NearbyRouter.ROUTER_ENABLED, "true")); - - request.putRouterArgument(NearbyRouter.ROUTER_TYPE_NEAR_BY, routeArguments); + // set nearby router enable + boolean nearbyRouterEnabled = polarisNearByRouterProperties.isEnabled(); + MetadataContainer metadataContainer = MetadataContextHolder.get() + .getMetadataContainer(MetadataType.CUSTOM, false); + metadataContainer.putMetadataMapValue(NearbyRouter.ROUTER_TYPE_NEAR_BY, NearbyRouter.ROUTER_ENABLED, String.valueOf(nearbyRouterEnabled), TransitiveType.NONE); } } diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/interceptor/RuleBasedRouterRequestInterceptor.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/interceptor/RuleBasedRouterRequestInterceptor.java index ff8f2fb1b..39d9e37b8 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/interceptor/RuleBasedRouterRequestInterceptor.java +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/interceptor/RuleBasedRouterRequestInterceptor.java @@ -17,20 +17,16 @@ package com.tencent.cloud.polaris.router.interceptor; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import com.tencent.cloud.common.constant.RouterConstant; +import com.tencent.cloud.common.metadata.MetadataContextHolder; import com.tencent.cloud.polaris.router.PolarisRouterContext; import com.tencent.cloud.polaris.router.config.properties.PolarisRuleBasedRouterProperties; import com.tencent.cloud.polaris.router.spi.RouterRequestInterceptor; -import com.tencent.polaris.api.pojo.RouteArgument; +import com.tencent.polaris.metadata.core.MetadataContainer; +import com.tencent.polaris.metadata.core.MetadataType; +import com.tencent.polaris.metadata.core.TransitiveType; import com.tencent.polaris.plugins.router.rule.RuleBasedRouter; import com.tencent.polaris.router.api.rpc.ProcessRoutersRequest; -import org.springframework.util.CollectionUtils; - /** * Router request interceptor for rule based router. * @author lepdou, Hoatian Zhang @@ -45,24 +41,12 @@ public class RuleBasedRouterRequestInterceptor implements RouterRequestIntercept @Override public void apply(ProcessRoutersRequest request, PolarisRouterContext routerContext) { + // set rule based router enable boolean ruleBasedRouterEnabled = polarisRuleBasedRouterProperties.isEnabled(); - - // set dynamic switch for rule based router - Set routeArguments = new HashSet<>(); - routeArguments.add(RouteArgument.buildCustom(RuleBasedRouter.ROUTER_ENABLED, String.valueOf(ruleBasedRouterEnabled))); - - // The label information that the rule based routing depends on - // is placed in the metadata of the source service for transmission. - // Later, can consider putting it in routerMetadata like other routers. - if (ruleBasedRouterEnabled) { - Map ruleRouterLabels = routerContext.getLabels(RouterConstant.ROUTER_LABELS); - if (!CollectionUtils.isEmpty(ruleRouterLabels)) { - for (Map.Entry label : ruleRouterLabels.entrySet()) { - routeArguments.add(RouteArgument.fromLabel(label.getKey(), label.getValue())); - } - } - } - - request.putRouterArgument(RuleBasedRouter.ROUTER_TYPE_RULE_BASED, routeArguments); + MetadataContainer metadataContainer = MetadataContextHolder.get() + .getMetadataContainer(MetadataType.CUSTOM, false); + metadataContainer.putMetadataMapValue(RuleBasedRouter.ROUTER_TYPE_RULE_BASED, RuleBasedRouter.ROUTER_ENABLED, String.valueOf(ruleBasedRouterEnabled), TransitiveType.NONE); + // set rule based router fail over type. + request.setRuleBasedRouterFailoverType(polarisRuleBasedRouterProperties.getFailOver()); } } diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerInterceptor.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerInterceptor.java deleted file mode 100644 index e3fcad7be..000000000 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerInterceptor.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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.polaris.router.resttemplate; - -import java.io.IOException; -import java.net.URI; - -import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; -import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor; -import org.springframework.cloud.client.loadbalancer.LoadBalancerRequestFactory; -import org.springframework.http.HttpRequest; -import org.springframework.http.client.ClientHttpRequestExecution; -import org.springframework.http.client.ClientHttpResponse; -import org.springframework.util.Assert; - -/** - * PolarisLoadBalancerInterceptor extends LoadBalancerInterceptor capabilities. - * Parses the label from the request and puts it into the RouterContext for routing. - * - * @author lepdou, cheese8 - */ -public class PolarisLoadBalancerInterceptor extends LoadBalancerInterceptor { - - private final LoadBalancerClient loadBalancer; - private final LoadBalancerRequestFactory requestFactory; - - public PolarisLoadBalancerInterceptor(LoadBalancerClient loadBalancer, - LoadBalancerRequestFactory requestFactory) { - super(loadBalancer, requestFactory); - this.loadBalancer = loadBalancer; - this.requestFactory = requestFactory; - } - - @Override - public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { - final URI originalUri = request.getURI(); - String peerServiceName = originalUri.getHost(); - Assert.state(peerServiceName != null, - "Request URI does not contain a valid hostname: " + originalUri); - - return this.loadBalancer.execute(peerServiceName, - new PolarisLoadBalancerRequest<>(request, this.requestFactory.createRequest(request, body, execution))); - } -} diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerRequest.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerRequest.java deleted file mode 100644 index ad4d47295..000000000 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerRequest.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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.polaris.router.resttemplate; - -import org.springframework.cloud.client.ServiceInstance; -import org.springframework.cloud.client.loadbalancer.LoadBalancerRequest; -import org.springframework.http.HttpRequest; - -/** - * Wrapper of {@link LoadBalancerRequest}. - * - * @author Haotian Zhang - */ -public class PolarisLoadBalancerRequest implements LoadBalancerRequest { - - private HttpRequest request; - - private LoadBalancerRequest delegate; - - public PolarisLoadBalancerRequest(HttpRequest request, LoadBalancerRequest delegate) { - this.request = request; - this.delegate = delegate; - } - - @Override - public T apply(ServiceInstance instance) throws Exception { - return delegate.apply(instance); - } - - public HttpRequest getRequest() { - return request; - } - - public LoadBalancerRequest getDelegate() { - return delegate; - } -} diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/RouterLabelRestTemplateInterceptor.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/RouterLabelRestTemplateInterceptor.java index e862a33e8..d079f7b87 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/RouterLabelRestTemplateInterceptor.java +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/RouterLabelRestTemplateInterceptor.java @@ -18,73 +18,25 @@ package com.tencent.cloud.polaris.router.resttemplate; import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.net.URLEncoder; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; import com.tencent.cloud.common.constant.OrderConstant; -import com.tencent.cloud.common.constant.RouterConstant; -import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.metadata.MetadataContextHolder; -import com.tencent.cloud.common.metadata.StaticMetadataManager; -import com.tencent.cloud.common.util.JacksonUtils; -import com.tencent.cloud.common.util.expresstion.ExpressionLabelUtils; -import com.tencent.cloud.common.util.expresstion.SpringWebExpressionLabelUtils; -import com.tencent.cloud.polaris.context.config.PolarisContextProperties; -import com.tencent.cloud.polaris.router.RouterRuleLabelResolver; -import com.tencent.cloud.polaris.router.spi.SpringWebRouterLabelResolver; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.tencent.cloud.metadata.provider.RestTemplateMetadataProvider; +import com.tencent.polaris.metadata.core.MetadataType; import org.springframework.core.Ordered; -import org.springframework.http.HttpHeaders; 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.Assert; -import org.springframework.util.CollectionUtils; - -import static com.tencent.cloud.common.constant.ContextConstant.UTF_8; /** - * Interceptor used for adding the route label in http headers from context when web client - * is RestTemplate. + * Interceptor used for setting RestTemplate HttpRequest metadata provider. * * @author liuye, Hoatian Zhang */ public class RouterLabelRestTemplateInterceptor implements ClientHttpRequestInterceptor, Ordered { - private static final Logger LOGGER = LoggerFactory.getLogger(RouterLabelRestTemplateInterceptor.class); - - private final List routerLabelResolvers; - private final StaticMetadataManager staticMetadataManager; - private final RouterRuleLabelResolver routerRuleLabelResolver; - private final PolarisContextProperties polarisContextProperties; - - public RouterLabelRestTemplateInterceptor(List routerLabelResolvers, - StaticMetadataManager staticMetadataManager, - RouterRuleLabelResolver routerRuleLabelResolver, - PolarisContextProperties polarisContextProperties) { - this.staticMetadataManager = staticMetadataManager; - this.routerRuleLabelResolver = routerRuleLabelResolver; - this.polarisContextProperties = polarisContextProperties; - - if (!CollectionUtils.isEmpty(routerLabelResolvers)) { - routerLabelResolvers.sort(Comparator.comparingInt(Ordered::getOrder)); - this.routerLabelResolvers = routerLabelResolvers; - } - else { - this.routerLabelResolvers = null; - } - } @Override public int getOrder() { @@ -94,82 +46,8 @@ public class RouterLabelRestTemplateInterceptor implements ClientHttpRequestInte @Override public ClientHttpResponse intercept(@NonNull HttpRequest request, @NonNull byte[] body, @NonNull ClientHttpRequestExecution clientHttpRequestExecution) throws IOException { - final URI originalUri = request.getURI(); - String peerServiceName = originalUri.getHost(); - Assert.state(peerServiceName != null, - "Request URI does not contain a valid hostname: " + originalUri); - - setLabelsToHeaders(request, body, peerServiceName); - - ClientHttpResponse response = clientHttpRequestExecution.execute(request, body); - - if (!CollectionUtils.isEmpty(request.getHeaders().get(RouterConstant.ROUTER_LABEL_HEADER))) { - HttpHeaders responseHeaders = HttpHeaders.writableHttpHeaders(response.getHeaders()); - responseHeaders.addAll(RouterConstant.ROUTER_LABEL_HEADER, Objects.requireNonNull(request.getHeaders() - .get(RouterConstant.ROUTER_LABEL_HEADER))); - } - - return response; - } - - void setLabelsToHeaders(HttpRequest request, byte[] body, String peerServiceName) { - // local service labels - Map labels = new HashMap<>(staticMetadataManager.getMergedStaticMetadata()); - - // labels from rule expression - Set expressionLabelKeys = routerRuleLabelResolver.getExpressionLabelKeys(MetadataContext.LOCAL_NAMESPACE, - MetadataContext.LOCAL_SERVICE, peerServiceName); - - Map ruleExpressionLabels = getExpressionLabels(request, expressionLabelKeys); - if (!CollectionUtils.isEmpty(ruleExpressionLabels)) { - labels.putAll(ruleExpressionLabels); - } - - // labels from request - if (!CollectionUtils.isEmpty(routerLabelResolvers)) { - routerLabelResolvers.forEach(resolver -> { - try { - Map customResolvedLabels = resolver.resolve(request, body, expressionLabelKeys); - if (!CollectionUtils.isEmpty(customResolvedLabels)) { - labels.putAll(customResolvedLabels); - } - } - catch (Throwable t) { - LOGGER.error("[SCT][Router] revoke RouterLabelResolver occur some exception. ", t); - } - }); - } - - // labels from downstream - Map transitiveLabels = MetadataContextHolder.get().getTransitiveMetadata(); - labels.putAll(transitiveLabels); - - // pass label by header - String encodedLabelsContent; - try { - encodedLabelsContent = URLEncoder.encode(JacksonUtils.serialize2Json(labels), UTF_8); - } - catch (UnsupportedEncodingException e) { - throw new RuntimeException("unsupported charset exception " + UTF_8); - } - request.getHeaders().set(RouterConstant.ROUTER_LABEL_HEADER, encodedLabelsContent); - } - - private Map getExpressionLabels(HttpRequest request, Set labelKeys) { - if (CollectionUtils.isEmpty(labelKeys)) { - return Collections.emptyMap(); - } - - //enrich labels from request - Map labels = SpringWebExpressionLabelUtils.resolve(request, labelKeys); - - //enrich caller ip label - for (String labelKey : labelKeys) { - if (ExpressionLabelUtils.isCallerIPLabel(labelKey)) { - labels.put(labelKey, polarisContextProperties.getLocalIpAddress()); - } - } - - return labels; + MetadataContextHolder.get().getMetadataContainer(MetadataType.MESSAGE, false) + .setMetadataProvider(new RestTemplateMetadataProvider(request)); + return clientHttpRequestExecution.execute(request, body); } } diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/scg/PolarisReactiveLoadBalancerClientFilter.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/scg/PolarisReactiveLoadBalancerClientFilter.java deleted file mode 100644 index 0c0f30875..000000000 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/scg/PolarisReactiveLoadBalancerClientFilter.java +++ /dev/null @@ -1,282 +0,0 @@ -/* - * 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.polaris.router.scg; - -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.net.URLEncoder; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import com.tencent.cloud.common.constant.RouterConstant; -import com.tencent.cloud.common.metadata.MetadataContext; -import com.tencent.cloud.common.metadata.MetadataContextHolder; -import com.tencent.cloud.common.metadata.StaticMetadataManager; -import com.tencent.cloud.common.util.JacksonUtils; -import com.tencent.cloud.common.util.expresstion.ExpressionLabelUtils; -import com.tencent.cloud.common.util.expresstion.SpringWebExpressionLabelUtils; -import com.tencent.cloud.polaris.context.config.PolarisContextProperties; -import com.tencent.cloud.polaris.router.PolarisRouterServiceInstanceListSupplier; -import com.tencent.cloud.polaris.router.RouterRuleLabelResolver; -import com.tencent.cloud.polaris.router.spi.SpringWebRouterLabelResolver; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import reactor.core.publisher.Mono; - -import org.springframework.cloud.client.ServiceInstance; -import org.springframework.cloud.client.loadbalancer.CompletionContext; -import org.springframework.cloud.client.loadbalancer.DefaultRequest; -import org.springframework.cloud.client.loadbalancer.LoadBalancerLifecycle; -import org.springframework.cloud.client.loadbalancer.LoadBalancerLifecycleValidator; -import org.springframework.cloud.client.loadbalancer.LoadBalancerProperties; -import org.springframework.cloud.client.loadbalancer.LoadBalancerUriTools; -import org.springframework.cloud.client.loadbalancer.Request; -import org.springframework.cloud.client.loadbalancer.RequestData; -import org.springframework.cloud.client.loadbalancer.RequestDataContext; -import org.springframework.cloud.client.loadbalancer.Response; -import org.springframework.cloud.client.loadbalancer.ResponseData; -import org.springframework.cloud.gateway.config.GatewayLoadBalancerProperties; -import org.springframework.cloud.gateway.filter.GatewayFilterChain; -import org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter; -import org.springframework.cloud.gateway.support.DelegatingServiceInstance; -import org.springframework.cloud.gateway.support.NotFoundException; -import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer; -import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer; -import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory; -import org.springframework.http.HttpHeaders; -import org.springframework.http.server.reactive.ServerHttpRequest; -import org.springframework.util.CollectionUtils; -import org.springframework.web.server.ServerWebExchange; - -import static com.tencent.cloud.common.constant.ContextConstant.UTF_8; -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_LOADBALANCER_RESPONSE_ATTR; -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR; -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR; -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.addOriginalRequestUrl; - -/** - * ReactiveLoadBalancerClientFilter does not have the ability to pass route labels, so it is replaced - * with PolarisReactiveLoadBalancerClientFilter. The passed route labels are used in - * {@link PolarisRouterServiceInstanceListSupplier}. - * - * @author lepdou, Hoatian Zhang - */ -public class PolarisReactiveLoadBalancerClientFilter extends ReactiveLoadBalancerClientFilter { - private static final Logger log = LoggerFactory.getLogger(PolarisReactiveLoadBalancerClientFilter.class); - - private final LoadBalancerClientFactory clientFactory; - private final GatewayLoadBalancerProperties gatewayLoadBalancerProperties; - private final LoadBalancerProperties loadBalancerProperties; - private final StaticMetadataManager staticMetadataManager; - private final RouterRuleLabelResolver routerRuleLabelResolver; - private final List routerLabelResolvers; - private final PolarisContextProperties polarisContextProperties; - - public PolarisReactiveLoadBalancerClientFilter(LoadBalancerClientFactory clientFactory, - GatewayLoadBalancerProperties gatewayLoadBalancerProperties, - LoadBalancerProperties loadBalancerProperties, - StaticMetadataManager staticMetadataManager, - RouterRuleLabelResolver routerRuleLabelResolver, - List routerLabelResolvers, - PolarisContextProperties polarisContextProperties) { - super(clientFactory, gatewayLoadBalancerProperties, loadBalancerProperties); - - this.clientFactory = clientFactory; - this.gatewayLoadBalancerProperties = gatewayLoadBalancerProperties; - this.loadBalancerProperties = loadBalancerProperties; - this.staticMetadataManager = staticMetadataManager; - this.routerRuleLabelResolver = routerRuleLabelResolver; - this.routerLabelResolvers = routerLabelResolvers; - this.polarisContextProperties = polarisContextProperties; - } - - /** - * Copied from ReactiveLoadBalancerClientFilter, and create new RequestData for passing router labels. - */ - @Override - public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { - URI url = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR); - String schemePrefix = exchange.getAttribute(GATEWAY_SCHEME_PREFIX_ATTR); - if (url == null || (!"lb".equals(url.getScheme()) && !"lb".equals(schemePrefix))) { - return chain.filter(exchange); - } - // preserve the original url - addOriginalRequestUrl(exchange, url); - - if (log.isTraceEnabled()) { - log.trace(ReactiveLoadBalancerClientFilter.class.getSimpleName() + " url before: " + url); - } - - URI requestUri = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR); - String serviceId = requestUri.getHost(); - Set supportedLifecycleProcessors = LoadBalancerLifecycleValidator - .getSupportedLifecycleProcessors(clientFactory.getInstances(serviceId, LoadBalancerLifecycle.class), - RequestDataContext.class, ResponseData.class, ServiceInstance.class); - - // Pass route tags through http headers - HttpHeaders routerHttpHeaders = genRouterHttpHeaders(exchange, serviceId); - - ServerHttpRequest request = exchange.getRequest(); - RequestData requestData = new RequestData(request.getMethod(), request.getURI(), routerHttpHeaders, - new HttpHeaders(), new HashMap<>()); - DefaultRequest lbRequest = new DefaultRequest<>(new RequestDataContext( - requestData, getHint(serviceId, loadBalancerProperties.getHint()))); - - return choose(lbRequest, serviceId, supportedLifecycleProcessors).doOnNext(response -> { - - if (!response.hasServer()) { - supportedLifecycleProcessors.forEach(lifecycle -> lifecycle - .onComplete(new CompletionContext<>(CompletionContext.Status.DISCARD, lbRequest, response))); - throw NotFoundException.create(gatewayLoadBalancerProperties.isUse404(), - "Unable to find instance for " + url.getHost()); - } - - ServiceInstance retrievedInstance = response.getServer(); - - URI uri = exchange.getRequest().getURI(); - - // if the `lb:` mechanism was used, use `` as the default, - // if the loadbalancer doesn't provide one. - String overrideScheme = retrievedInstance.isSecure() ? "https" : "http"; - if (schemePrefix != null) { - overrideScheme = url.getScheme(); - } - - DelegatingServiceInstance serviceInstance = new DelegatingServiceInstance(retrievedInstance, - overrideScheme); - - URI requestUrl = reconstructURI(serviceInstance, uri); - - if (log.isTraceEnabled()) { - log.trace("LoadBalancerClientFilter url chosen: " + requestUrl); - } - exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl); - exchange.getAttributes().put(GATEWAY_LOADBALANCER_RESPONSE_ATTR, response); - supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onStartRequest(lbRequest, response)); - }).then(chain.filter(exchange)) - .doOnError(throwable -> supportedLifecycleProcessors.forEach(lifecycle -> lifecycle - .onComplete(new CompletionContext( - CompletionContext.Status.FAILED, throwable, lbRequest, - exchange.getAttribute(GATEWAY_LOADBALANCER_RESPONSE_ATTR))))) - .doOnSuccess(aVoid -> supportedLifecycleProcessors.forEach(lifecycle -> lifecycle - .onComplete(new CompletionContext( - CompletionContext.Status.SUCCESS, lbRequest, - exchange.getAttribute(GATEWAY_LOADBALANCER_RESPONSE_ATTR), - new ResponseData(exchange.getResponse(), new RequestData(exchange.getRequest())))))); - } - - @Override - protected URI reconstructURI(ServiceInstance serviceInstance, URI original) { - return LoadBalancerUriTools.reconstructURI(serviceInstance, original); - } - - private Mono> choose(Request lbRequest, String serviceId, - Set supportedLifecycleProcessors) { - ReactorLoadBalancer loadBalancer = this.clientFactory.getInstance(serviceId, - ReactorServiceInstanceLoadBalancer.class); - if (loadBalancer == null) { - throw new NotFoundException("No loadbalancer available for " + serviceId); - } - supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onStart(lbRequest)); - return loadBalancer.choose(lbRequest); - } - - // no actual used - private String getHint(String serviceId, Map hints) { - String defaultHint = hints.getOrDefault("default", "default"); - String hintPropertyValue = hints.get(serviceId); - return hintPropertyValue != null ? hintPropertyValue : defaultHint; - } - - // In order to be consistent with feign and restTemplate, - // the router label is passed through the http header uniformly instead of the original hint mechanism. - HttpHeaders genRouterHttpHeaders(ServerWebExchange exchange, String peerServiceName) { - HttpHeaders headers = new HttpHeaders(); - headers.add(RouterConstant.ROUTER_LABEL_HEADER, genRouterHint(exchange, peerServiceName)); - return headers; - } - - private String genRouterHint(ServerWebExchange exchange, String peerServiceName) { - Map routerLabels = genRouterLabels(exchange, peerServiceName); - String encodedLabelsContent; - try { - encodedLabelsContent = URLEncoder.encode(JacksonUtils.serialize2Json(routerLabels), UTF_8); - } - catch (UnsupportedEncodingException e) { - throw new RuntimeException("unsupported charset exception " + UTF_8); - } - return encodedLabelsContent; - } - - private Map genRouterLabels(ServerWebExchange exchange, String peerServiceName) { - // local service labels - Map labels = new HashMap<>(staticMetadataManager.getMergedStaticMetadata()); - - // labels from rule expression - Set expressionLabelKeys = routerRuleLabelResolver.getExpressionLabelKeys(MetadataContext.LOCAL_NAMESPACE, - MetadataContext.LOCAL_SERVICE, peerServiceName); - - Map ruleExpressionLabels = getExpressionLabels(exchange, expressionLabelKeys); - if (!CollectionUtils.isEmpty(ruleExpressionLabels)) { - labels.putAll(ruleExpressionLabels); - } - - // labels from request - if (!CollectionUtils.isEmpty(routerLabelResolvers)) { - routerLabelResolvers.forEach(resolver -> { - try { - Map customResolvedLabels = resolver.resolve(exchange, expressionLabelKeys); - if (!CollectionUtils.isEmpty(customResolvedLabels)) { - labels.putAll(customResolvedLabels); - } - } - catch (Throwable t) { - log.error("[SCT][Router] revoke RouterLabelResolver occur some exception. ", t); - } - }); - } - - // labels from downstream - Map transitiveLabels = MetadataContextHolder.get().getTransitiveMetadata(); - labels.putAll(transitiveLabels); - - return labels; - } - - private Map getExpressionLabels(ServerWebExchange exchange, Set labelKeys) { - if (CollectionUtils.isEmpty(labelKeys)) { - return Collections.emptyMap(); - } - - //enrich labels from request - Map labels = SpringWebExpressionLabelUtils.resolve(exchange, labelKeys); - - //enrich caller ip label - for (String labelKey : labelKeys) { - if (ExpressionLabelUtils.isCallerIPLabel(labelKey)) { - labels.put(labelKey, polarisContextProperties.getLocalIpAddress()); - } - } - - return labels; - } -} diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/scg/RouterLabelGlobalFilter.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/scg/RouterLabelGlobalFilter.java new file mode 100644 index 000000000..7f6cbadad --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/scg/RouterLabelGlobalFilter.java @@ -0,0 +1,57 @@ +/* + * 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.polaris.router.scg; + +import com.tencent.cloud.common.metadata.MetadataContextHolder; +import com.tencent.cloud.metadata.provider.ReactiveMetadataProvider; +import com.tencent.polaris.metadata.core.MetadataType; +import com.tencent.polaris.metadata.core.constant.MetadataConstants; +import com.tencent.polaris.metadata.core.manager.CalleeMetadataContainerGroup; +import reactor.core.publisher.Mono; + +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.cloud.gateway.filter.GlobalFilter; +import org.springframework.core.Ordered; +import org.springframework.web.server.ServerWebExchange; + +import static org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter.LOAD_BALANCER_CLIENT_FILTER_ORDER; + +/** + * Interceptor used for setting SCG ServerWebExchange metadata provider. + * + * @author Hoatian Zhang + */ +public class RouterLabelGlobalFilter implements GlobalFilter, Ordered { + @Override + public int getOrder() { + return LOAD_BALANCER_CLIENT_FILTER_ORDER - 1; + } + + /** + * Copied from ReactiveLoadBalancerClientFilter, and create new RequestData for passing router labels. + */ + @Override + public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { + MetadataContextHolder.get().getMetadataContainer(MetadataType.MESSAGE, false) + .setMetadataProvider(new ReactiveMetadataProvider(exchange.getRequest(), + CalleeMetadataContainerGroup.getStaticApplicationMetadataContainer() + .getRawMetadataStringValue(MetadataConstants.LOCAL_IP))); + return chain.filter(exchange); + } +} diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/spi/FeignRouterLabelResolver.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/spi/FeignRouterLabelResolver.java deleted file mode 100644 index 6ff5c9c56..000000000 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/spi/FeignRouterLabelResolver.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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.polaris.router.spi; - -import java.util.Map; -import java.util.Set; - -import feign.RequestTemplate; - -import org.springframework.core.Ordered; - -/** - * Router label resolver for feign request. - * @author lepdou 2022-07-20 - */ -public interface FeignRouterLabelResolver extends Ordered { - - /** - * Resolve labels from feign request. User can customize expression parser to extract labels. - * - * @param requestTemplate the feign request. - * @param expressionLabelKeys the expression labels which are configured in router rule. - * @return resolved labels - */ - Map resolve(RequestTemplate requestTemplate, Set expressionLabelKeys); -} diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/spi/SpringWebRouterLabelResolver.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/spi/SpringWebRouterLabelResolver.java deleted file mode 100644 index 55db8498b..000000000 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/spi/SpringWebRouterLabelResolver.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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.polaris.router.spi; - -import java.util.Collections; -import java.util.Map; -import java.util.Set; - -import org.springframework.core.Ordered; -import org.springframework.http.HttpRequest; -import org.springframework.web.server.ServerWebExchange; - -/** - * Router label resolver for spring web http request. - * @author lepdou 2022-07-20 - */ -public interface SpringWebRouterLabelResolver extends Ordered { - - /** - * resolve labels from rest template request. User can customize expression parser to extract labels. - * - * @param request the rest template request. - * @param body the rest template request body. - * @param expressionLabelKeys the expression labels which are configured in router rule. - * @return resolved labels - */ - default Map resolve(HttpRequest request, byte[] body, Set expressionLabelKeys) { - return Collections.emptyMap(); - } - - - /** - * resolve labels from server web exchange. User can customize expression parser to extract labels. - * - * @param exchange the server web exchange. - * @param expressionLabelKeys the expression labels which are configured in router rule. - * @return resolved labels - */ - default Map resolve(ServerWebExchange exchange, Set expressionLabelKeys) { - return Collections.emptyMap(); - } -} diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-starter-tencent-polaris-router/src/main/resources/META-INF/additional-spring-configuration-metadata.json index c5a47d1db..f628ed620 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-cloud-starter-tencent-polaris-router/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -24,6 +24,12 @@ "defaultValue": true, "description": "the switch for rule based router." }, + { + "name": "spring.cloud.polaris.router.rule-router.failOver", + "type": "java.lang.String", + "defaultValue": "all", + "description": "the fail over type for rule based router." + }, { "name": "spring.cloud.polaris.router.enabled", "type": "java.lang.Boolean", diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/PolarisRouterContextTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/PolarisRouterContextTest.java index b87602087..b14415f0c 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/PolarisRouterContextTest.java +++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/PolarisRouterContextTest.java @@ -20,7 +20,6 @@ package com.tencent.cloud.polaris.router; import java.util.HashMap; import java.util.Map; -import java.util.Set; import com.google.common.collect.Sets; import com.tencent.cloud.common.constant.RouterConstant; @@ -97,20 +96,4 @@ public class PolarisRouterContextTest { String resolvedLabel = routerContext.getLabel("k1"); assertThat(resolvedLabel).isEqualTo("v1"); } - - @Test - public void testGetLabelAsSet() { - Map labels = new HashMap<>(); - labels.put("k1", "v1,v2,v3"); - - PolarisRouterContext routerContext = new PolarisRouterContext(); - routerContext.putLabels(RouterConstant.ROUTER_LABELS, labels); - - Set resolvedLabels = routerContext.getLabelAsSet("k1"); - - assertThat(resolvedLabels.size()).isEqualTo(3); - assertThat(resolvedLabels).contains("v1"); - assertThat(resolvedLabels).contains("v2"); - assertThat(resolvedLabels).contains("v3"); - } } diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/PolarisRouterServiceInstanceListSupplierTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/PolarisRouterServiceInstanceListSupplierTest.java index 858ab7e9a..1380919fb 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/PolarisRouterServiceInstanceListSupplierTest.java +++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/PolarisRouterServiceInstanceListSupplierTest.java @@ -24,7 +24,6 @@ import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import com.tencent.cloud.common.constant.RouterConstant; @@ -38,7 +37,6 @@ import com.tencent.cloud.polaris.router.config.properties.PolarisRuleBasedRouter import com.tencent.cloud.polaris.router.interceptor.MetadataRouterRequestInterceptor; import com.tencent.cloud.polaris.router.interceptor.NearbyRouterRequestInterceptor; import com.tencent.cloud.polaris.router.interceptor.RuleBasedRouterRequestInterceptor; -import com.tencent.cloud.polaris.router.resttemplate.PolarisLoadBalancerRequest; import com.tencent.cloud.polaris.router.spi.RouterRequestInterceptor; import com.tencent.cloud.polaris.router.spi.RouterResponseInterceptor; import com.tencent.cloud.rpc.enhancement.transformer.PolarisInstanceTransformer; @@ -46,9 +44,11 @@ import com.tencent.polaris.api.exception.PolarisException; import com.tencent.polaris.api.pojo.DefaultInstance; import com.tencent.polaris.api.pojo.DefaultServiceInstances; import com.tencent.polaris.api.pojo.Instance; -import com.tencent.polaris.api.pojo.RouteArgument; import com.tencent.polaris.api.pojo.ServiceInstances; import com.tencent.polaris.api.pojo.ServiceKey; +import com.tencent.polaris.metadata.core.MetadataContainer; +import com.tencent.polaris.metadata.core.MetadataType; +import com.tencent.polaris.metadata.core.TransitiveType; import com.tencent.polaris.plugins.router.metadata.MetadataRouter; import com.tencent.polaris.plugins.router.nearby.NearbyRouter; import com.tencent.polaris.plugins.router.rule.RuleBasedRouter; @@ -66,7 +66,6 @@ import reactor.core.publisher.Flux; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.loadbalancer.DefaultRequest; -import org.springframework.cloud.client.loadbalancer.DefaultRequestContext; import org.springframework.cloud.client.loadbalancer.RequestData; import org.springframework.cloud.client.loadbalancer.RequestDataContext; import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier; @@ -123,27 +122,18 @@ public class PolarisRouterServiceInstanceListSupplierTest { PolarisRouterServiceInstanceListSupplier polarisSupplier = new PolarisRouterServiceInstanceListSupplier( delegate, routerAPI, requestInterceptors, null, new PolarisInstanceTransformer()); + MetadataContainer metadataContainer = MetadataContextHolder.get() + .getMetadataContainer(MetadataType.CUSTOM, false); + metadataContainer.putMetadataStringValue("system-metadata-router-keys", "k2", TransitiveType.NONE); + ServiceInstances serviceInstances = assembleServiceInstances(); PolarisRouterContext routerContext = assembleRouterContext(); - Map oldRouterLabels = routerContext.getLabels(RouterConstant.ROUTER_LABELS); - Map newRouterLabels = new HashMap<>(oldRouterLabels); - newRouterLabels.put("system-metadata-router-keys", "k2"); - routerContext.putLabels(RouterConstant.ROUTER_LABELS, newRouterLabels); - ProcessRoutersRequest request = polarisSupplier.buildProcessRoutersRequest(serviceInstances, routerContext); polarisSupplier.processRouterRequestInterceptors(request, routerContext); - Set routerMetadata = request.getRouterArguments(MetadataRouter.ROUTER_TYPE_METADATA); - - assertThat(routerMetadata.size()).isEqualTo(1); - assertThat(request.getRouterArguments(NearbyRouter.ROUTER_TYPE_NEAR_BY).size()).isEqualTo(0); - assertThat(request.getRouterArguments(RuleBasedRouter.ROUTER_TYPE_RULE_BASED).size()).isEqualTo(1); - - for (RouteArgument routeArgument : request.getRouterArguments(RuleBasedRouter.ROUTER_TYPE_RULE_BASED)) { - assertThat(routeArgument.getKey()).isEqualTo(RuleBasedRouter.ROUTER_ENABLED); - assertThat(routeArgument.getValue()).isEqualTo("false"); - } + String result = metadataContainer.getRawMetadataMapValue(MetadataRouter.ROUTER_TYPE_METADATA, MetadataRouter.KEY_METADATA_KEYS); + assertThat(result).isEqualTo("k2"); } } @@ -166,22 +156,10 @@ public class PolarisRouterServiceInstanceListSupplierTest { ProcessRoutersRequest request = polarisSupplier.buildProcessRoutersRequest(serviceInstances, routerContext); polarisSupplier.processRouterRequestInterceptors(request, routerContext); - Set routerMetadata = request.getRouterArguments(NearbyRouter.ROUTER_TYPE_NEAR_BY); - - assertThat(request.getRouterArguments(MetadataRouter.ROUTER_TYPE_METADATA).size()).isEqualTo(0); - assertThat(routerMetadata.size()).isEqualTo(1); - - for (RouteArgument routeArgument : routerMetadata) { - assertThat(routeArgument.getKey()).isEqualTo(RuleBasedRouter.ROUTER_ENABLED); - assertThat(routeArgument.getValue()).isEqualTo("true"); - } - - assertThat(request.getRouterArguments(RuleBasedRouter.ROUTER_TYPE_RULE_BASED).size()).isEqualTo(1); - - for (RouteArgument routeArgument : request.getRouterArguments(RuleBasedRouter.ROUTER_TYPE_RULE_BASED)) { - assertThat(routeArgument.getKey()).isEqualTo(RuleBasedRouter.ROUTER_ENABLED); - assertThat(routeArgument.getValue()).isEqualTo("false"); - } + MetadataContainer metadataContainer = MetadataContextHolder.get() + .getMetadataContainer(MetadataType.CUSTOM, false); + String result = metadataContainer.getRawMetadataMapValue(NearbyRouter.ROUTER_TYPE_NEAR_BY, NearbyRouter.ROUTER_ENABLED); + assertThat(result).isEqualTo("true"); } } @@ -204,11 +182,10 @@ public class PolarisRouterServiceInstanceListSupplierTest { ProcessRoutersRequest request = polarisSupplier.buildProcessRoutersRequest(serviceInstances, routerContext); polarisSupplier.processRouterRequestInterceptors(request, routerContext); - Set routerMetadata = request.getRouterArguments(RuleBasedRouter.ROUTER_TYPE_RULE_BASED); - - assertThat(routerMetadata.size()).isEqualTo(3); - assertThat(request.getRouterArguments(MetadataRouter.ROUTER_TYPE_METADATA).size()).isEqualTo(0); - assertThat(request.getRouterArguments(NearbyRouter.ROUTER_TYPE_NEAR_BY).size()).isEqualTo(0); + MetadataContainer metadataContainer = MetadataContextHolder.get() + .getMetadataContainer(MetadataType.CUSTOM, false); + String result = metadataContainer.getRawMetadataMapValue(RuleBasedRouter.ROUTER_TYPE_RULE_BASED, RuleBasedRouter.ROUTER_ENABLED); + assertThat(result).isEqualTo("true"); } } @@ -242,7 +219,7 @@ public class PolarisRouterServiceInstanceListSupplierTest { HttpHeaders headers = new HttpHeaders(); PolarisRouterContext context = polarisSupplier.buildRouterContext(headers); - assertThat(context).isNull(); + assertThat(context).isNotNull(); // mock try (MockedStatic mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class)) { @@ -266,25 +243,6 @@ public class PolarisRouterServiceInstanceListSupplierTest { @Test public void testGet02() { - try (MockedStatic mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class)) { - mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString())) - .thenReturn(testCallerService); - - PolarisRouterServiceInstanceListSupplier polarisSupplier = new PolarisRouterServiceInstanceListSupplier( - delegate, routerAPI, requestInterceptors, null, new PolarisInstanceTransformer()); - - MockServerHttpRequest httpRequest = MockServerHttpRequest.get("/" + testCalleeService + "/users") - .header("k1", "v1") - .queryParam("userid", "zhangsan") - .build(); - RequestDataContext requestDataContext = new RequestDataContext(new RequestData(httpRequest), "blue"); - DefaultRequest request = new DefaultRequest(requestDataContext); - assertThat(polarisSupplier.get(request)).isNull(); - } - } - - @Test - public void testGet03() { try (MockedStatic mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class)) { mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString())) .thenReturn(testCallerService); @@ -299,14 +257,14 @@ public class PolarisRouterServiceInstanceListSupplierTest { MockServerHttpRequest httpRequest = MockServerHttpRequest.get("/" + testCalleeService + "/users") .header("k1", "v1") - .header(RouterConstant.ROUTER_LABEL_HEADER, "{\"k1\":\"v1\"}") .queryParam("userid", "zhangsan") .build(); - DefaultRequestContext requestDataContext = new DefaultRequestContext(new PolarisLoadBalancerRequest(httpRequest, null), "blue"); + RequestDataContext requestDataContext = new RequestDataContext(new RequestData(httpRequest), "blue"); DefaultRequest request = new DefaultRequest(requestDataContext); - assertThat(polarisSupplier.get(request).blockFirst().size()).isEqualTo(0); + assertThat(polarisSupplier.get(request)).isNotNull(); } } + private void setTransitiveMetadata() { if (initTransitiveMetadata.compareAndSet(false, true)) { // mock transitive metadata diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/RouterRuleLabelResolverTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/RouterRuleLabelResolverTest.java deleted file mode 100644 index 16b7b2219..000000000 --- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/RouterRuleLabelResolverTest.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * 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.polaris.router; - -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import com.tencent.cloud.polaris.context.ServiceRuleManager; -import com.tencent.polaris.specification.api.v1.model.ModelProto; -import com.tencent.polaris.specification.api.v1.traffic.manage.RoutingProto; -import org.assertj.core.util.Lists; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.when; - -/** - * test for {@link RouterRuleLabelResolver}. - * - * @author lepdou 2022-05-26 - */ -@ExtendWith(MockitoExtension.class) -public class RouterRuleLabelResolverTest { - - private final String testNamespace = "testNamespace"; - private final String testSourceService = "sourceService"; - private final String testDstService = "dstService"; - @Mock - private ServiceRuleManager serviceRuleManager; - - @Test - public void test() { - Map labels = new HashMap<>(); - ModelProto.MatchString matchString = ModelProto.MatchString.getDefaultInstance(); - String validKey1 = "${http.header.uid}"; - String validKey2 = "${http.query.name}"; - String validKey3 = "${http.method}"; - String validKey4 = "${http.uri}"; - String validKey5 = "${http.body.customkey}"; - String invalidKey = "$http.expression.wrong}"; - labels.put(validKey1, matchString); - labels.put(validKey2, matchString); - labels.put(validKey3, matchString); - labels.put(validKey4, matchString); - labels.put(validKey5, matchString); - labels.put(invalidKey, matchString); - - RoutingProto.Source source1 = RoutingProto.Source.newBuilder().putAllMetadata(labels).build(); - RoutingProto.Source source2 = RoutingProto.Source.newBuilder().putAllMetadata(labels).build(); - RoutingProto.Source source3 = RoutingProto.Source.newBuilder().putAllMetadata(new HashMap<>()).build(); - - List routes = new LinkedList<>(); - RoutingProto.Route route = RoutingProto.Route.newBuilder() - .addAllSources(Lists.list(source1, source2, source3)) - .build(); - routes.add(route); - - when(serviceRuleManager.getServiceRouterRule(testNamespace, testSourceService, testDstService)).thenReturn(routes); - - RouterRuleLabelResolver resolver = new RouterRuleLabelResolver(serviceRuleManager); - - Set resolvedExpressionLabelKeys = resolver.getExpressionLabelKeys(testNamespace, testSourceService, testDstService); - - assertThat(resolvedExpressionLabelKeys).isNotNull(); - assertThat(resolvedExpressionLabelKeys.size()).isEqualTo(6); - assertThat(resolvedExpressionLabelKeys).contains(validKey1); - assertThat(resolvedExpressionLabelKeys).contains(validKey2); - assertThat(resolvedExpressionLabelKeys).contains(validKey3); - assertThat(resolvedExpressionLabelKeys).contains(validKey4); - assertThat(resolvedExpressionLabelKeys).contains(validKey5); - assertThat(resolvedExpressionLabelKeys).contains(invalidKey); - } -} diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/RouterUtilsTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/RouterUtilsTest.java index a89e9c6af..e91c7e1af 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/RouterUtilsTest.java +++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/RouterUtilsTest.java @@ -28,6 +28,7 @@ import com.tencent.cloud.rpc.enhancement.transformer.PolarisInstanceTransformer; import com.tencent.polaris.api.pojo.DefaultInstance; import com.tencent.polaris.api.pojo.Instance; import com.tencent.polaris.api.pojo.ServiceInstances; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.MockedStatic; @@ -51,6 +52,11 @@ public class RouterUtilsTest { private static final String testNamespaceAndService = "testNamespaceAndService"; + @BeforeAll + static void beforeAll() { + MetadataContext.LOCAL_NAMESPACE = testNamespaceAndService; + } + @Test public void testTransferEmptyInstances() { ServiceInstances serviceInstances = RouterUtils.transferServersToServiceInstances(Flux.empty(), new PolarisInstanceTransformer()); diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/beanprocessor/LoadBalancerInterceptorBeanPostProcessorTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/beanprocessor/LoadBalancerInterceptorBeanPostProcessorTest.java deleted file mode 100644 index 128d3523d..000000000 --- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/beanprocessor/LoadBalancerInterceptorBeanPostProcessorTest.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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.polaris.router.beanprocessor; - -import com.tencent.cloud.common.util.BeanFactoryUtils; -import com.tencent.cloud.polaris.router.resttemplate.PolarisLoadBalancerInterceptor; -import com.tencent.cloud.polaris.router.spi.SpringWebRouterLabelResolver; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.MockedStatic; -import org.mockito.Mockito; -import org.mockito.junit.jupiter.MockitoExtension; - -import org.springframework.beans.factory.BeanFactory; -import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; -import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor; -import org.springframework.cloud.client.loadbalancer.LoadBalancerRequestFactory; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.when; - -/** - * Test for ${@link LoadBalancerInterceptorBeanPostProcessor}. - * - * @author lepdou 2022-05-26 - */ -@ExtendWith(MockitoExtension.class) -public class LoadBalancerInterceptorBeanPostProcessorTest { - - @Mock - private LoadBalancerClient loadBalancerClient; - @Mock - private LoadBalancerRequestFactory loadBalancerRequestFactory; - @Mock - private BeanFactory beanFactory; - - @Test - public void testWrapperLoadBalancerInterceptor() { - when(beanFactory.getBean(LoadBalancerRequestFactory.class)).thenReturn(loadBalancerRequestFactory); - when(beanFactory.getBean(LoadBalancerClient.class)).thenReturn(loadBalancerClient); - - try (MockedStatic mockedBeanFactoryUtils = Mockito.mockStatic(BeanFactoryUtils.class)) { - mockedBeanFactoryUtils.when(() -> BeanFactoryUtils.getBeans(beanFactory, SpringWebRouterLabelResolver.class)) - .thenReturn(null); - LoadBalancerInterceptor loadBalancerInterceptor = new LoadBalancerInterceptor(loadBalancerClient, loadBalancerRequestFactory); - - LoadBalancerInterceptorBeanPostProcessor processor = new LoadBalancerInterceptorBeanPostProcessor(); - processor.setBeanFactory(beanFactory); - - Object bean = processor.postProcessBeforeInitialization(loadBalancerInterceptor, ""); - - assertThat(bean).isInstanceOf(PolarisLoadBalancerInterceptor.class); - } - } - - @Test - public void testNotWrapperLoadBalancerInterceptor() { - LoadBalancerInterceptorBeanPostProcessor processor = new LoadBalancerInterceptorBeanPostProcessor(); - processor.setBeanFactory(beanFactory); - - OtherBean otherBean = new OtherBean(); - Object bean = processor.postProcessBeforeInitialization(otherBean, ""); - assertThat(bean).isNotInstanceOf(PolarisLoadBalancerInterceptor.class); - assertThat(bean).isInstanceOf(OtherBean.class); - } - - static class OtherBean { - - } -} diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/beanprocessor/ReactiveLoadBalancerClientFilterBeanPostProcessorTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/beanprocessor/ReactiveLoadBalancerClientFilterBeanPostProcessorTest.java deleted file mode 100644 index 56730dcc8..000000000 --- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/beanprocessor/ReactiveLoadBalancerClientFilterBeanPostProcessorTest.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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.polaris.router.beanprocessor; - -import com.tencent.cloud.common.metadata.StaticMetadataManager; -import com.tencent.cloud.common.util.BeanFactoryUtils; -import com.tencent.cloud.polaris.router.RouterRuleLabelResolver; -import com.tencent.cloud.polaris.router.scg.PolarisReactiveLoadBalancerClientFilter; -import com.tencent.cloud.polaris.router.spi.SpringWebRouterLabelResolver; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.MockedStatic; -import org.mockito.Mockito; -import org.mockito.junit.jupiter.MockitoExtension; - -import org.springframework.beans.factory.BeanFactory; -import org.springframework.cloud.client.loadbalancer.LoadBalancerProperties; -import org.springframework.cloud.gateway.config.GatewayLoadBalancerProperties; -import org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter; -import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.when; - - -/** - * Test for ${@link ReactiveLoadBalancerClientFilterBeanPostProcessor}. - * - * @author lepdou 2022-07-04 - */ -@ExtendWith(MockitoExtension.class) -public class ReactiveLoadBalancerClientFilterBeanPostProcessorTest { - - @Mock - private BeanFactory beanFactory; - @Mock - private LoadBalancerClientFactory loadBalancerClientFactory; - @Mock - private GatewayLoadBalancerProperties gatewayLoadBalancerProperties; - @Mock - private LoadBalancerProperties loadBalancerProperties; - @Mock - private StaticMetadataManager staticMetadataManager; - @Mock - private RouterRuleLabelResolver routerRuleLabelResolver; - - @Test - public void testWrapReactiveLoadBalancerClientFilter() { - when(beanFactory.getBean(LoadBalancerClientFactory.class)).thenReturn(loadBalancerClientFactory); - when(beanFactory.getBean(GatewayLoadBalancerProperties.class)).thenReturn(gatewayLoadBalancerProperties); - when(beanFactory.getBean(LoadBalancerProperties.class)).thenReturn(loadBalancerProperties); - when(beanFactory.getBean(StaticMetadataManager.class)).thenReturn(staticMetadataManager); - when(beanFactory.getBean(RouterRuleLabelResolver.class)).thenReturn(routerRuleLabelResolver); - - try (MockedStatic mockedBeanFactoryUtils = Mockito.mockStatic(BeanFactoryUtils.class)) { - mockedBeanFactoryUtils.when(() -> BeanFactoryUtils.getBeans(beanFactory, SpringWebRouterLabelResolver.class)) - .thenReturn(null); - - ReactiveLoadBalancerClientFilter reactiveLoadBalancerClientFilter = new ReactiveLoadBalancerClientFilter( - loadBalancerClientFactory, gatewayLoadBalancerProperties, loadBalancerProperties); - - ReactiveLoadBalancerClientFilterBeanPostProcessor processor = new ReactiveLoadBalancerClientFilterBeanPostProcessor(); - processor.setBeanFactory(beanFactory); - - Object bean = processor.postProcessBeforeInitialization(reactiveLoadBalancerClientFilter, ""); - assertThat(bean).isInstanceOf(PolarisReactiveLoadBalancerClientFilter.class); - } - } - - @Test - public void testNotWrapLoadBalancerInterceptor() { - ReactiveLoadBalancerClientFilterBeanPostProcessor processor = new ReactiveLoadBalancerClientFilterBeanPostProcessor(); - processor.setBeanFactory(beanFactory); - - OtherBean otherBean = new OtherBean(); - Object bean = processor.postProcessBeforeInitialization(otherBean, ""); - assertThat(bean).isNotInstanceOf(PolarisReactiveLoadBalancerClientFilter.class); - assertThat(bean).isInstanceOf(OtherBean.class); - } - - static class OtherBean { - - } -} diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/config/properties/PolarisRuleBasedRouterPropertiesTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/config/properties/PolarisRuleBasedRouterPropertiesTest.java index 9a8fc5697..1cc5e43ad 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/config/properties/PolarisRuleBasedRouterPropertiesTest.java +++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/config/properties/PolarisRuleBasedRouterPropertiesTest.java @@ -49,7 +49,7 @@ public class PolarisRuleBasedRouterPropertiesTest { @Test public void testToString() { assertThat(properties.toString()) - .isEqualTo("PolarisNearByRouterProperties{enabled=true}"); + .isEqualTo("PolarisRuleBasedRouterProperties{enabled=true, failOver=all}"); } } diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/FeignExpressionLabelUtilsTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/FeignExpressionLabelUtilsTest.java deleted file mode 100644 index 8d117ee2a..000000000 --- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/FeignExpressionLabelUtilsTest.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * 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.polaris.router.feign; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Stream; - -import feign.Request; -import feign.RequestTemplate; -import org.junit.jupiter.api.Test; - -import static java.util.stream.Collectors.toSet; -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Test for {@link FeignExpressionLabelUtils}. - * - * @author lepdou 2022-05-26 - */ -public class FeignExpressionLabelUtilsTest { - - @Test - public void testGetHeaderLabel() { - String headerKey = "uid"; - String headerValue = "1000"; - String headerKey2 = "teacher.age"; - String headerValue2 = "1000"; - - RequestTemplate requestTemplate = new RequestTemplate(); - requestTemplate.header(headerKey, headerValue); - requestTemplate.header(headerKey2, headerValue2); - - String labelKey1 = "${http.header.uid}"; - String labelKey2 = "${http.header.name}"; - String labelKey3 = "${http.headername}"; - String labelKey4 = "${http.header.}"; - String labelKey5 = "${http.header.teacher.age}"; - Map result = FeignExpressionLabelUtils.resolve(requestTemplate, - Stream.of(labelKey1, labelKey2, labelKey3, labelKey4, labelKey5).collect(toSet())); - - assertThat(result).isNotEmpty(); - assertThat(result.get(labelKey1)).isEqualTo(headerValue); - assertThat(result.get(labelKey5)).isEqualTo(headerValue2); - assertThat(result.get(labelKey2)).isBlank(); - assertThat(result.get(labelKey3)).isBlank(); - assertThat(result.get(labelKey4)).isBlank(); - } - - @Test - public void testGetQueryLabel() { - String headerKey = "uid"; - String headerValue = "1000"; - String headerKey2 = "teacher.age"; - String headerValue2 = "1000"; - - RequestTemplate requestTemplate = new RequestTemplate(); - requestTemplate.query(headerKey, headerValue); - requestTemplate.query(headerKey2, headerValue2); - - String labelKey1 = "${http.query.uid}"; - String labelKey2 = "${http.query.name}"; - String labelKey3 = "${http.queryname}"; - String labelKey4 = "${http.query.}"; - String labelKey5 = "${http.query.teacher.age}"; - Map result = FeignExpressionLabelUtils.resolve(requestTemplate, - Stream.of(labelKey1, labelKey2, labelKey3, labelKey4, labelKey5).collect(toSet())); - - assertThat(result).isNotEmpty(); - assertThat(result.get(labelKey1)).isEqualTo(headerValue); - assertThat(result.get(labelKey5)).isEqualTo(headerValue2); - assertThat(result.get(labelKey2)).isBlank(); - assertThat(result.get(labelKey3)).isBlank(); - assertThat(result.get(labelKey4)).isBlank(); - } - - @Test - public void testGetMethod() { - RequestTemplate requestTemplate = new RequestTemplate(); - requestTemplate.method(Request.HttpMethod.GET); - - String labelKey1 = "${http.method}"; - Map result = FeignExpressionLabelUtils.resolve(requestTemplate, Stream.of(labelKey1) - .collect(toSet())); - - assertThat(result).isNotEmpty(); - assertThat(result.get(labelKey1)).isEqualTo("GET"); - } - - @Test - public void testGetUri() { - String uri = "/user/get"; - - RequestTemplate requestTemplate = new RequestTemplate(); - requestTemplate.uri(uri); - requestTemplate.method(Request.HttpMethod.GET); - requestTemplate.target("http://localhost"); - requestTemplate = requestTemplate.resolve(new HashMap<>()); - - String labelKey1 = "${http.uri}"; - Map result = FeignExpressionLabelUtils.resolve(requestTemplate, Stream.of(labelKey1) - .collect(toSet())); - - assertThat(result).isNotEmpty(); - assertThat(result.get(labelKey1)).isEqualTo(uri); - } - - @Test - public void testGetUri2() { - String uri = "/"; - - RequestTemplate requestTemplate = new RequestTemplate(); - requestTemplate.uri(uri); - requestTemplate.method(Request.HttpMethod.GET); - requestTemplate.target("http://localhost"); - requestTemplate = requestTemplate.resolve(new HashMap<>()); - - String labelKey1 = "${http.uri}"; - Map result = FeignExpressionLabelUtils.resolve(requestTemplate, Stream.of(labelKey1) - .collect(toSet())); - - assertThat(result).isNotEmpty(); - assertThat(result.get(labelKey1)).isEqualTo(uri); - } - - @Test - public void testGetCookie() { - String uri = "/"; - String cookieValue = "zhangsan"; - - RequestTemplate requestTemplate = new RequestTemplate(); - requestTemplate.uri(uri); - requestTemplate.method(Request.HttpMethod.GET); - requestTemplate.target("http://localhost"); - requestTemplate = requestTemplate.resolve(new HashMap<>()); - requestTemplate.header("cookie", Collections.singleton("uid=zhangsan; auth-token=dfhuwshfy77")); - - String labelKey1 = "${http.cookie.uid}"; - Map result = FeignExpressionLabelUtils.resolve(requestTemplate, Stream.of(labelKey1) - .collect(toSet())); - - assertThat(result).isNotEmpty(); - assertThat(result.get(labelKey1)).isEqualTo(cookieValue); - } -} diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/RouterLabelFeignInterceptorTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/RouterLabelFeignInterceptorTest.java index 0e381c96e..257a9498a 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/RouterLabelFeignInterceptorTest.java +++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/RouterLabelFeignInterceptorTest.java @@ -18,124 +18,81 @@ package com.tencent.cloud.polaris.router.feign; -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; -import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; +import java.util.List; import java.util.Map; -import java.util.Set; import com.tencent.cloud.common.constant.OrderConstant; -import com.tencent.cloud.common.constant.RouterConstant; -import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.metadata.MetadataContextHolder; -import com.tencent.cloud.common.metadata.StaticMetadataManager; -import com.tencent.cloud.common.util.ApplicationContextAwareUtils; -import com.tencent.cloud.common.util.JacksonUtils; -import com.tencent.cloud.polaris.context.config.PolarisContextProperties; -import com.tencent.cloud.polaris.router.RouterRuleLabelResolver; -import com.tencent.cloud.polaris.router.spi.FeignRouterLabelResolver; +import com.tencent.polaris.metadata.core.MessageMetadataContainer; +import com.tencent.polaris.metadata.core.MetadataContainer; +import com.tencent.polaris.metadata.core.MetadataType; +import feign.Request; import feign.RequestTemplate; -import feign.Target; +import io.netty.handler.codec.http.HttpHeaderNames; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.MockedStatic; -import org.mockito.Mockito; -import org.mockito.junit.jupiter.MockitoExtension; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; /** * test for {@link RouterLabelFeignInterceptor}. * - * @author lepdou, cheese8 + * @author lepdou 2022-05-26 */ -@ExtendWith(MockitoExtension.class) +@ExtendWith(SpringExtension.class) +@SpringBootTest(classes = RouterLabelFeignInterceptorTest.TestApplication.class, + properties = {"spring.cloud.polaris.namespace=test", "spring.application.name=test", "spring.cloud.gateway.enabled=false"}) public class RouterLabelFeignInterceptorTest { - @Mock - private StaticMetadataManager staticMetadataManager; - @Mock - private RouterRuleLabelResolver routerRuleLabelResolver; - @Mock - private FeignRouterLabelResolver routerLabelResolver; - @Mock - private PolarisContextProperties polarisContextProperties; - @Test - public void testResolveRouterLabel() throws UnsupportedEncodingException { - RouterLabelFeignInterceptor routerLabelFeignInterceptor = new RouterLabelFeignInterceptor( - Collections.singletonList(routerLabelResolver), - staticMetadataManager, routerRuleLabelResolver, polarisContextProperties); + public void testRouterLabel() { + RouterLabelFeignInterceptor routerLabelFeignInterceptor = new RouterLabelFeignInterceptor(); assertThat(routerLabelFeignInterceptor.getOrder()).isEqualTo(OrderConstant.Client.Feign.ROUTER_LABEL_INTERCEPTOR_ORDER); // mock request template - RequestTemplate requestTemplate = new RequestTemplate(); + RequestTemplate requestTemplate = mock(RequestTemplate.class); String headerUidKey = "uid"; String headerUidValue = "1000"; - requestTemplate.header(headerUidKey, headerUidValue); - String peerService = "peerService"; - Target.EmptyTarget target = Target.EmptyTarget.create(Object.class, peerService); - requestTemplate.feignTarget(target); - - // mock ApplicationContextAwareUtils#getProperties - try (MockedStatic mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class)) { - String testService = "callerService"; - mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString())) - .thenReturn(testService); - - MetadataContext metadataContext = Mockito.mock(MetadataContext.class); - - // mock transitive metadata - Map transitiveLabels = new HashMap<>(); - transitiveLabels.put("k1", "v1"); - transitiveLabels.put("k2", "v22"); - when(metadataContext.getTransitiveMetadata()).thenReturn(transitiveLabels); - - // mock MetadataContextHolder#get - try (MockedStatic mockedMetadataContextHolder = Mockito.mockStatic(MetadataContextHolder.class)) { - mockedMetadataContextHolder.when(MetadataContextHolder::get).thenReturn(metadataContext); - - // mock expression rule labels - Set expressionKeys = new HashSet<>(); - expressionKeys.add("${http.header.uid}"); - expressionKeys.add("${http.header.name}"); - when(routerRuleLabelResolver.getExpressionLabelKeys(MetadataContext.LOCAL_NAMESPACE, - MetadataContext.LOCAL_SERVICE, peerService)).thenReturn(expressionKeys); - - // mock custom resolved labels from request - Map customResolvedLabels = new HashMap<>(); - customResolvedLabels.put("k2", "v2"); - customResolvedLabels.put("k3", "v3"); - when(routerLabelResolver.resolve(requestTemplate, expressionKeys)).thenReturn(customResolvedLabels); - - Map localMetadata = new HashMap<>(); - localMetadata.put("k3", "v31"); - localMetadata.put("k4", "v4"); - when(staticMetadataManager.getMergedStaticMetadata()).thenReturn(localMetadata); - - routerLabelFeignInterceptor.apply(requestTemplate); - - Collection routerLabels = requestTemplate.headers().get(RouterConstant.ROUTER_LABEL_HEADER); + Map> headerMap = new HashMap<>(); + headerMap.put(headerUidKey, Collections.singletonList(headerUidValue)); + headerMap.put(HttpHeaderNames.COOKIE.toString(), Collections.singletonList("k1=v1")); + doReturn(headerMap).when(requestTemplate).headers(); + doReturn(Request.HttpMethod.POST.toString()).when(requestTemplate).method(); + Request request = mock(Request.class); + doReturn(request).when(requestTemplate).request(); + doReturn("http://callee/test/path").when(request).url(); + Map> queryMap = new HashMap<>(); + queryMap.put("q1", Collections.singletonList("a1")); + doReturn(queryMap).when(requestTemplate).queries(); + + routerLabelFeignInterceptor.apply(requestTemplate); + + // get message metadata container + MetadataContainer metadataContainer = MetadataContextHolder.get() + .getMetadataContainer(MetadataType.MESSAGE, false); + // method + assertThat(metadataContainer.getRawMetadataStringValue(MessageMetadataContainer.LABEL_KEY_METHOD)).isEqualTo(Request.HttpMethod.POST.toString()); + // path + assertThat(metadataContainer.getRawMetadataStringValue(MessageMetadataContainer.LABEL_KEY_PATH)).isEqualTo("/test/path"); + // header + assertThat(metadataContainer.getRawMetadataMapValue(MessageMetadataContainer.LABEL_MAP_KEY_HEADER, headerUidKey)).isEqualTo(headerUidValue); + // cookie + assertThat(metadataContainer.getRawMetadataMapValue(MessageMetadataContainer.LABEL_MAP_KEY_COOKIE, "k1")).isEqualTo("v1"); + // query + assertThat(metadataContainer.getRawMetadataMapValue(MessageMetadataContainer.LABEL_MAP_KEY_QUERY, "q1")).isEqualTo("a1"); + } - assertThat(routerLabels).isNotNull(); - for (String value : routerLabels) { - Map labels = JacksonUtils.deserialize2Map(URLDecoder.decode(value, "UTF-8")); + @SpringBootApplication + protected static class TestApplication { - assertThat(labels.get("k1")).isEqualTo("v1"); - assertThat(labels.get("k2")).isEqualTo("v22"); - assertThat(labels.get("k3")).isEqualTo("v3"); - assertThat(labels.get("k4")).isEqualTo("v4"); - assertThat(labels.get("${http.header.uid}")).isEqualTo(headerUidValue); - assertThat(labels.get("${http.header.name}")).isEqualTo(""); - } - } - } } } diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerRequestTests.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerRequestTests.java deleted file mode 100644 index dfe6684a6..000000000 --- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerRequestTests.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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.polaris.router.resttemplate; - -import org.junit.jupiter.api.Test; - -import org.springframework.cloud.client.DefaultServiceInstance; -import org.springframework.cloud.client.ServiceInstance; -import org.springframework.cloud.client.loadbalancer.LoadBalancerRequest; -import org.springframework.http.HttpRequest; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; - -/** - * test for {@link PolarisLoadBalancerRequest}. - * @author dongyinuo - */ -public class PolarisLoadBalancerRequestTests { - - @Test - public void test() throws Exception { - String calleeService = "calleeService"; - HttpRequest request = new RouterLabelRestTemplateInterceptorTest.MockedHttpRequest("http://" + calleeService + "/user/get"); - MockLoadBalancerRequest mockLoadBalancerRequest = new MockLoadBalancerRequest(); - PolarisLoadBalancerRequest polarisLoadBalancerRequest = new PolarisLoadBalancerRequest<>(request, mockLoadBalancerRequest); - - DefaultServiceInstance serviceInstance = new DefaultServiceInstance(); - serviceInstance.setServiceId(calleeService); - ServiceInstance apply = polarisLoadBalancerRequest.apply(serviceInstance); - assertThat(apply.getServiceId()).isEqualTo(calleeService); - assertThat(polarisLoadBalancerRequest.getRequest()).isEqualTo(request); - assertThat(polarisLoadBalancerRequest.getDelegate()).isEqualTo(mockLoadBalancerRequest); - } - - static class MockLoadBalancerRequest implements LoadBalancerRequest { - - @Override - public Object apply(ServiceInstance instance) throws Exception { - return instance; - } - } - -} diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/resttemplate/RouterLabelRestTemplateInterceptorTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/resttemplate/RouterLabelRestTemplateInterceptorTest.java index e3a5b4723..9c88cab66 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/resttemplate/RouterLabelRestTemplateInterceptorTest.java +++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/resttemplate/RouterLabelRestTemplateInterceptorTest.java @@ -13,39 +13,26 @@ * 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.polaris.router.resttemplate; -import java.io.UnsupportedEncodingException; import java.net.URI; -import java.net.URLDecoder; -import java.net.URLEncoder; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Objects; -import java.util.Set; - -import com.tencent.cloud.common.constant.RouterConstant; -import com.tencent.cloud.common.metadata.MetadataContext; + +import com.tencent.cloud.common.constant.OrderConstant; import com.tencent.cloud.common.metadata.MetadataContextHolder; -import com.tencent.cloud.common.metadata.StaticMetadataManager; -import com.tencent.cloud.common.util.ApplicationContextAwareUtils; -import com.tencent.cloud.common.util.JacksonUtils; -import com.tencent.cloud.common.util.expresstion.SpringWebExpressionLabelUtils; -import com.tencent.cloud.polaris.context.config.PolarisContextProperties; -import com.tencent.cloud.polaris.router.RouterRuleLabelResolver; -import com.tencent.cloud.polaris.router.spi.SpringWebRouterLabelResolver; +import com.tencent.polaris.metadata.core.MessageMetadataContainer; +import com.tencent.polaris.metadata.core.MetadataContainer; +import com.tencent.polaris.metadata.core.MetadataType; +import feign.Request; +import io.netty.handler.codec.http.HttpHeaderNames; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.MockedStatic; -import org.mockito.Mockito; -import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.core.Ordered; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpRequest; @@ -53,14 +40,11 @@ import org.springframework.http.HttpStatus; import org.springframework.http.client.ClientHttpRequestExecution; import org.springframework.http.client.ClientHttpResponse; import org.springframework.mock.http.client.MockClientHttpResponse; +import org.springframework.test.context.junit.jupiter.SpringExtension; -import static com.tencent.cloud.common.constant.ContextConstant.UTF_8; -import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mockStatic; -import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; /** @@ -68,117 +52,63 @@ import static org.mockito.Mockito.when; * * @author liuye, Haotian Zhang */ -@ExtendWith(MockitoExtension.class) +@ExtendWith(SpringExtension.class) +@SpringBootTest(classes = RouterLabelRestTemplateInterceptorTest.TestApplication.class, + properties = {"spring.cloud.polaris.namespace=test", "spring.application.name=test", "spring.cloud.gateway.enabled=false"}) public class RouterLabelRestTemplateInterceptorTest { - private static final String testNamespaceAndService = "testNamespaceAndService"; - @Mock - - private SpringWebRouterLabelResolver routerLabelResolver; - @Mock - private StaticMetadataManager staticMetadataManager; - @Mock - private RouterRuleLabelResolver routerRuleLabelResolver; - @Mock - private PolarisContextProperties polarisContextProperties; - @Mock private ClientHttpRequestExecution clientHttpRequestExecution; - @Test - public void testRouterContext() throws Exception { - try ( - MockedStatic mockedApplicationContextAwareUtils = mockStatic(ApplicationContextAwareUtils.class); - MockedStatic mockedMetadataContextHolder = mockStatic(MetadataContextHolder.class) - ) { - mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString())) - .thenReturn(testNamespaceAndService); - - String calleeService = "calleeService"; - HttpRequest request = new MockedHttpRequest("http://" + calleeService + "/user/get"); - - // mock local metadata - Map localMetadata = new HashMap<>(); - localMetadata.put("k1", "v1"); - localMetadata.put("k2", "v2"); - when(staticMetadataManager.getMergedStaticMetadata()).thenReturn(localMetadata); - Map routerLabels = new HashMap<>(localMetadata); - - // mock expression rule labels - Set expressionKeys = new HashSet<>(); - expressionKeys.add("${http.method}"); - expressionKeys.add("${http.uri}"); - when(routerRuleLabelResolver.getExpressionLabelKeys(testNamespaceAndService, testNamespaceAndService, calleeService)).thenReturn(expressionKeys); - routerLabels.putAll(SpringWebExpressionLabelUtils.resolve(request, expressionKeys)); - - // mock custom resolved from request - Map customResolvedLabels = new HashMap<>(); - customResolvedLabels.put("k2", "v22"); - customResolvedLabels.put("k4", "v4"); - when(routerLabelResolver.resolve(request, null, expressionKeys)).thenReturn(customResolvedLabels); - routerLabels.putAll(customResolvedLabels); - - MetadataContext metadataContext = Mockito.mock(MetadataContext.class); - - // mock transitive metadata - Map transitiveLabels = new HashMap<>(); - transitiveLabels.put("k1", "v1"); - transitiveLabels.put("k2", "v22"); - when(metadataContext.getTransitiveMetadata()).thenReturn(transitiveLabels); - routerLabels.putAll(transitiveLabels); - - mockedMetadataContextHolder.when(MetadataContextHolder::get).thenReturn(metadataContext); - - RouterLabelRestTemplateInterceptor routerLabelRestTemplateInterceptor = new RouterLabelRestTemplateInterceptor( - Collections.singletonList(routerLabelResolver), staticMetadataManager, routerRuleLabelResolver, polarisContextProperties); - - ClientHttpResponse mockedResponse = new MockClientHttpResponse(new byte[] {}, HttpStatus.OK); - when(clientHttpRequestExecution.execute(eq(request), any())).thenReturn(mockedResponse); - - assertThat(routerLabelRestTemplateInterceptor.getOrder()).isEqualTo(Ordered.LOWEST_PRECEDENCE); - - routerLabelRestTemplateInterceptor.intercept(request, null, clientHttpRequestExecution); - - verify(staticMetadataManager).getMergedStaticMetadata(); - verify(routerRuleLabelResolver).getExpressionLabelKeys(testNamespaceAndService, testNamespaceAndService, calleeService); - verify(routerLabelResolver).resolve(request, null, expressionKeys); - - - Map headers = JacksonUtils.deserialize2Map(URLDecoder.decode(Objects.requireNonNull(request.getHeaders() - .get(RouterConstant.ROUTER_LABEL_HEADER)).get(0), "UTF-8")); - assertThat("v1").isEqualTo(headers.get("k1")); - assertThat("v22").isEqualTo(headers.get("k2")); - assertThat("v4").isEqualTo(headers.get("k4")); - assertThat("GET").isEqualTo(headers.get("${http.method}")); - assertThat("/user/get").isEqualTo(headers.get("${http.uri}")); - String encodedLabelsContent; - try { - encodedLabelsContent = URLEncoder.encode(JacksonUtils.serialize2Json(routerLabels), UTF_8); - } - catch (UnsupportedEncodingException e) { - throw new RuntimeException("unsupported charset exception " + UTF_8); - } - assertThat(mockedResponse.getHeaders().get(RouterConstant.ROUTER_LABEL_HEADER).get(0)) - .isEqualTo(encodedLabelsContent); - } + public void testRouterLabel() throws Exception { + RouterLabelRestTemplateInterceptor routerLabelRestTemplateInterceptor = new RouterLabelRestTemplateInterceptor(); + + assertThat(routerLabelRestTemplateInterceptor.getOrder()).isEqualTo(OrderConstant.Client.RestTemplate.ROUTER_LABEL_INTERCEPTOR_ORDER); + + String calleeService = "calleeService"; + HttpRequest request = new MockedHttpRequest("http://" + calleeService + "/test/path?q1=a1"); + + ClientHttpResponse mockedResponse = new MockClientHttpResponse(new byte[] {}, HttpStatus.OK); + when(clientHttpRequestExecution.execute(eq(request), any())).thenReturn(mockedResponse); + + routerLabelRestTemplateInterceptor.intercept(request, null, clientHttpRequestExecution); + + // get message metadata container + MetadataContainer metadataContainer = MetadataContextHolder.get() + .getMetadataContainer(MetadataType.MESSAGE, false); + // method + assertThat(metadataContainer.getRawMetadataStringValue(MessageMetadataContainer.LABEL_KEY_METHOD)).isEqualTo(Request.HttpMethod.POST.toString()); + // path + assertThat(metadataContainer.getRawMetadataStringValue(MessageMetadataContainer.LABEL_KEY_PATH)).isEqualTo("/test/path"); + // header + assertThat(metadataContainer.getRawMetadataMapValue(MessageMetadataContainer.LABEL_MAP_KEY_HEADER, "uid")).isEqualTo("1000"); + // cookie + assertThat(metadataContainer.getRawMetadataMapValue(MessageMetadataContainer.LABEL_MAP_KEY_COOKIE, "k1")).isEqualTo("v1"); + // query + assertThat(metadataContainer.getRawMetadataMapValue(MessageMetadataContainer.LABEL_MAP_KEY_QUERY, "q1")).isEqualTo("a1"); } static class MockedHttpRequest implements HttpRequest { - private URI uri; + private final URI uri; - private HttpHeaders httpHeaders = new HttpHeaders(); + private final HttpHeaders httpHeaders = new HttpHeaders(); MockedHttpRequest(String url) { this.uri = URI.create(url); + this.httpHeaders.add("uid", "1000"); + this.httpHeaders.add(HttpHeaderNames.COOKIE.toString(), "k1=v1"); } + @Override + public HttpMethod getMethod() { + return HttpMethod.POST; + } @Override public String getMethodValue() { - return HttpMethod.GET.name(); + return HttpMethod.POST.toString(); } - @Override public URI getURI() { return uri; @@ -189,4 +119,9 @@ public class RouterLabelRestTemplateInterceptorTest { return httpHeaders; } } + + @SpringBootApplication + protected static class TestApplication { + + } } diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/scg/PolarisReactiveLoadBalancerClientFilterTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/scg/PolarisReactiveLoadBalancerClientFilterTest.java deleted file mode 100644 index e62454e00..000000000 --- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/scg/PolarisReactiveLoadBalancerClientFilterTest.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * 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.polaris.router.scg; - -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.net.URLDecoder; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import com.tencent.cloud.common.constant.RouterConstant; -import com.tencent.cloud.common.metadata.MetadataContext; -import com.tencent.cloud.common.metadata.MetadataContextHolder; -import com.tencent.cloud.common.metadata.StaticMetadataManager; -import com.tencent.cloud.common.util.ApplicationContextAwareUtils; -import com.tencent.cloud.common.util.JacksonUtils; -import com.tencent.cloud.polaris.context.config.PolarisContextProperties; -import com.tencent.cloud.polaris.router.RouterRuleLabelResolver; -import com.tencent.cloud.polaris.router.spi.SpringWebRouterLabelResolver; -import org.assertj.core.util.Lists; -import org.assertj.core.util.Sets; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.MockedStatic; -import org.mockito.junit.jupiter.MockitoExtension; -import reactor.core.publisher.Mono; - -import org.springframework.cloud.client.loadbalancer.LoadBalancerProperties; -import org.springframework.cloud.gateway.config.GatewayLoadBalancerProperties; -import org.springframework.cloud.gateway.filter.GatewayFilterChain; -import org.springframework.cloud.loadbalancer.core.NoopServiceInstanceListSupplier; -import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer; -import org.springframework.cloud.loadbalancer.core.RoundRobinLoadBalancer; -import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory; -import org.springframework.cloud.loadbalancer.support.SimpleObjectProvider; -import org.springframework.http.HttpHeaders; -import org.springframework.mock.http.server.reactive.MockServerHttpRequest; -import org.springframework.mock.web.server.MockServerWebExchange; -import org.springframework.web.server.ServerWebExchange; - -import static com.tencent.cloud.common.constant.ContextConstant.UTF_8; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.mockStatic; -import static org.mockito.Mockito.when; -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR; -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR; - -/** - * Test for ${@link PolarisReactiveLoadBalancerClientFilter}. - * - * @author lepdou 2022-07-04 - */ -@ExtendWith(MockitoExtension.class) -public class PolarisReactiveLoadBalancerClientFilterTest { - - private static final String testNamespaceAndService = "testNamespaceAndService"; - private static final String calleeService = "calleeService"; - - @Mock - private StaticMetadataManager staticMetadataManager; - @Mock - private SpringWebRouterLabelResolver routerLabelResolver; - @Mock - private RouterRuleLabelResolver routerRuleLabelResolver; - @Mock - private LoadBalancerClientFactory loadBalancerClientFactory; - @Mock - private GatewayLoadBalancerProperties gatewayLoadBalancerProperties; - @Mock - private LoadBalancerProperties loadBalancerProperties; - @Mock - private PolarisContextProperties polarisContextProperties; - - @Test - public void testGenRouterHttpHeaders() throws UnsupportedEncodingException { - try ( - MockedStatic mockedApplicationContextAwareUtils = mockStatic(ApplicationContextAwareUtils.class); - MockedStatic mockedMetadataContextHolder = mockStatic(MetadataContextHolder.class) - ) { - mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString())) - .thenReturn(testNamespaceAndService); - - MetadataContext metadataContext = mock(MetadataContext.class); - - // mock transitive metadata - Map transitiveLabels = new HashMap<>(); - transitiveLabels.put("t1", "v1"); - transitiveLabels.put("t2", "v2"); - when(metadataContext.getTransitiveMetadata()).thenReturn(transitiveLabels); - mockedMetadataContextHolder.when(MetadataContextHolder::get).thenReturn(metadataContext); - - PolarisReactiveLoadBalancerClientFilter filter = new PolarisReactiveLoadBalancerClientFilter(loadBalancerClientFactory, - gatewayLoadBalancerProperties, loadBalancerProperties, staticMetadataManager, routerRuleLabelResolver, - Collections.singletonList(routerLabelResolver), polarisContextProperties); - - Map localMetadata = new HashMap<>(); - localMetadata.put("env", "blue"); - when(staticMetadataManager.getMergedStaticMetadata()).thenReturn(localMetadata); - - Set expressionLabelKeys = Sets.newLinkedHashSet("${http.header.k1}", "${http.query.userid}"); - when(routerRuleLabelResolver.getExpressionLabelKeys(anyString(), anyString(), anyString())).thenReturn(expressionLabelKeys); - - MockServerHttpRequest request = MockServerHttpRequest.get("/" + calleeService + "/users") - .header("k1", "v1") - .queryParam("userid", "zhangsan") - .build(); - MockServerWebExchange webExchange = new MockServerWebExchange.Builder(request).build(); - - Map customMetadata = new HashMap<>(); - customMetadata.put("k2", "v2"); - when(routerLabelResolver.resolve(webExchange, expressionLabelKeys)).thenReturn(customMetadata); - - HttpHeaders headers = filter.genRouterHttpHeaders(webExchange, calleeService); - - assertThat(headers).isNotNull(); - List routerHeaders = headers.get(RouterConstant.ROUTER_LABEL_HEADER); - assertThat(routerHeaders).isNotNull(); - - - Map routerLabels = JacksonUtils.deserialize2Map(URLDecoder.decode(routerHeaders.get(0), UTF_8)); - assertThat(routerLabels.get("${http.header.k1}")).isEqualTo("v1"); - assertThat(routerLabels.get("${http.query.userid}")).isEqualTo("zhangsan"); - assertThat(routerLabels.get("env")).isEqualTo("blue"); - assertThat(routerLabels.get("t1")).isEqualTo("v1"); - assertThat(routerLabels.get("t2")).isEqualTo("v2"); - } - } - - @Test - public void testFilter01() throws Exception { - try ( - MockedStatic mockedApplicationContextAwareUtils = mockStatic(ApplicationContextAwareUtils.class); - MockedStatic mockedMetadataContextHolder = mockStatic(MetadataContextHolder.class) - ) { - mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString())) - .thenReturn(testNamespaceAndService); - - MetadataContext metadataContext = mock(MetadataContext.class); - - // mock transitive metadata - Map transitiveLabels = new HashMap<>(); - transitiveLabels.put("t1", "v1"); - transitiveLabels.put("t2", "v2"); - when(metadataContext.getTransitiveMetadata()).thenReturn(transitiveLabels); - mockedMetadataContextHolder.when(MetadataContextHolder::get).thenReturn(metadataContext); - - PolarisReactiveLoadBalancerClientFilter filter = new PolarisReactiveLoadBalancerClientFilter(loadBalancerClientFactory, - gatewayLoadBalancerProperties, loadBalancerProperties, staticMetadataManager, routerRuleLabelResolver, - Lists.list(routerLabelResolver), polarisContextProperties); - - MockServerHttpRequest request = MockServerHttpRequest.get("/" + calleeService + "/users").build(); - MockServerWebExchange exchange = new MockServerWebExchange.Builder(request).build(); - - // mock no lb - EmptyGatewayFilterChain chain = new EmptyGatewayFilterChain(); - Mono ret = filter.filter(exchange, chain); - assertThat(ret).isEqualTo(Mono.empty()); - - // mock with lb - exchange = new MockServerWebExchange.Builder(request).build(); - exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, new URI("https://" + calleeService + ":8091")); - exchange.getAttributes().put(GATEWAY_SCHEME_PREFIX_ATTR, "lb"); - - NoopServiceInstanceListSupplier serviceInstanceListSupplier = new NoopServiceInstanceListSupplier(); - RoundRobinLoadBalancer roundRobinLoadBalancer = new RoundRobinLoadBalancer(new SimpleObjectProvider<>(serviceInstanceListSupplier), calleeService); - - when(loadBalancerClientFactory.getInstance(calleeService, ReactorServiceInstanceLoadBalancer.class)).thenReturn(roundRobinLoadBalancer); - filter.filter(exchange, chain); - } - } - - static class EmptyGatewayFilterChain implements GatewayFilterChain { - - @Override - public Mono filter(ServerWebExchange exchange) { - return Mono.empty(); - } - } -} diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/scg/RouterLabelGlobalFilterTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/scg/RouterLabelGlobalFilterTest.java new file mode 100644 index 000000000..65a5a249a --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/scg/RouterLabelGlobalFilterTest.java @@ -0,0 +1,95 @@ +/* + * 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.polaris.router.scg; + +import com.tencent.cloud.common.metadata.MetadataContextHolder; +import com.tencent.polaris.metadata.core.MessageMetadataContainer; +import com.tencent.polaris.metadata.core.MetadataContainer; +import com.tencent.polaris.metadata.core.MetadataType; +import feign.Request; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import reactor.core.publisher.Mono; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.http.HttpCookie; +import org.springframework.mock.http.server.reactive.MockServerHttpRequest; +import org.springframework.mock.web.server.MockServerWebExchange; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.web.server.ServerWebExchange; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter.LOAD_BALANCER_CLIENT_FILTER_ORDER; + +/** + * Test for ${@link RouterLabelGlobalFilter}. + * + * @author Haotian Zhang + */ +@ExtendWith(SpringExtension.class) +@SpringBootTest(classes = RouterLabelGlobalFilterTest.TestApplication.class, + properties = {"spring.cloud.polaris.namespace=test", "spring.application.name=test", "spring.main.web-application-type=reactive"}) +public class RouterLabelGlobalFilterTest { + + @Test + public void testRouterLabel() { + RouterLabelGlobalFilter routerLabelGlobalFilter = new RouterLabelGlobalFilter(); + + assertThat(routerLabelGlobalFilter.getOrder()) + .isEqualTo(LOAD_BALANCER_CLIENT_FILTER_ORDER - 1); + + MockServerHttpRequest request = MockServerHttpRequest.post("/test/path") + .header("uid", "1000") + .cookie(new HttpCookie("k1", "v1")) + .queryParam("q1", "a1") + .build(); + MockServerWebExchange mockWebExchange = new MockServerWebExchange.Builder(request).build(); + + routerLabelGlobalFilter.filter(mockWebExchange, new EmptyGatewayFilterChain()); + + // get message metadata container + MetadataContainer metadataContainer = MetadataContextHolder.get() + .getMetadataContainer(MetadataType.MESSAGE, false); + // method + assertThat(metadataContainer.getRawMetadataStringValue(MessageMetadataContainer.LABEL_KEY_METHOD)).isEqualTo(Request.HttpMethod.POST.toString()); + // path + assertThat(metadataContainer.getRawMetadataStringValue(MessageMetadataContainer.LABEL_KEY_PATH)).isEqualTo("/test/path"); + // header + assertThat(metadataContainer.getRawMetadataMapValue(MessageMetadataContainer.LABEL_MAP_KEY_HEADER, "uid")).isEqualTo("1000"); + // cookie + assertThat(metadataContainer.getRawMetadataMapValue(MessageMetadataContainer.LABEL_MAP_KEY_COOKIE, "k1")).isEqualTo("v1"); + // query + assertThat(metadataContainer.getRawMetadataMapValue(MessageMetadataContainer.LABEL_MAP_KEY_QUERY, "q1")).isEqualTo("a1"); + } + + static class EmptyGatewayFilterChain implements GatewayFilterChain { + + @Override + public Mono filter(ServerWebExchange exchange) { + return Mono.empty(); + } + } + + @SpringBootApplication + protected static class TestApplication { + + } +} diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/transformer/PolarisInstanceTransformerTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/transformer/PolarisInstanceTransformerTest.java index 9a2f77bf8..0836cf1ea 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/transformer/PolarisInstanceTransformerTest.java +++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/transformer/PolarisInstanceTransformerTest.java @@ -23,7 +23,6 @@ import com.tencent.cloud.common.util.ApplicationContextAwareUtils; import com.tencent.cloud.rpc.enhancement.transformer.PolarisInstanceTransformer; import com.tencent.polaris.api.pojo.DefaultInstance; import com.tencent.polaris.api.pojo.Instance; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.mockito.MockedStatic; import org.mockito.Mockito; @@ -37,25 +36,20 @@ import static org.assertj.core.api.Assertions.assertThat; */ public class PolarisInstanceTransformerTest { - private static MockedStatic mockedApplicationContextAwareUtils; - - @BeforeAll - public static void beforeAll() { - mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class); - mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties("spring.cloud.polaris.namespace")) - .thenReturn("default"); - mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties("spring.cloud.polaris.service")) - .thenReturn("test"); - } - - @Test public void test() { - PolarisInstanceTransformer polarisInstanceTransformer = new PolarisInstanceTransformer(); - DefaultInstance instance = new DefaultInstance(); - instance.setZone("zone"); - PolarisServiceInstance polarisServiceInstance = new PolarisServiceInstance(instance); - Instance instance1 = polarisInstanceTransformer.transform(polarisServiceInstance); - assertThat(instance1.getZone()).isEqualTo("zone"); + try ( + MockedStatic mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class)) { + mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties("spring.cloud.polaris.namespace")) + .thenReturn("default"); + mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties("spring.cloud.polaris.service")) + .thenReturn("test"); + PolarisInstanceTransformer polarisInstanceTransformer = new PolarisInstanceTransformer(); + DefaultInstance instance = new DefaultInstance(); + instance.setZone("zone"); + PolarisServiceInstance polarisServiceInstance = new PolarisServiceInstance(instance); + Instance instance1 = polarisInstanceTransformer.transform(polarisServiceInstance); + assertThat(instance1.getZone()).isEqualTo("zone"); + } } } diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/constant/MetadataConstant.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/constant/MetadataConstant.java index 3f8bb2555..f132920eb 100644 --- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/constant/MetadataConstant.java +++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/constant/MetadataConstant.java @@ -62,9 +62,9 @@ public final class MetadataConstant { public static final String CUSTOM_DISPOSABLE_METADATA = "SCT-CUSTOM-DISPOSABLE-METADATA"; /** - * System Metadata. + * Application Metadata. */ - public static final String SYSTEM_METADATA = "SCT-SYSTEM-METADATA"; + public static final String APPLICATION_METADATA = "SCT-APPLICATION-METADATA"; /** * Metadata context. diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/tsf/consts/WarmupCons.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/constant/WarmupCons.java similarity index 95% rename from spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/tsf/consts/WarmupCons.java rename to spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/constant/WarmupCons.java index 53bce11c8..d590e22c8 100644 --- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/tsf/consts/WarmupCons.java +++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/constant/WarmupCons.java @@ -15,7 +15,7 @@ * specific language governing permissions and limitations under the License. */ -package com.tencent.cloud.polaris.tsf.consts; +package com.tencent.cloud.common.constant; /** * 预热所需枚举. diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContext.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContext.java index e43a60f86..321cfa945 100644 --- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContext.java +++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContext.java @@ -56,6 +56,16 @@ public class MetadataContext extends com.tencent.polaris.metadata.core.manager.M */ public static final String FRAGMENT_UPSTREAM_DISPOSABLE = "upstream-disposable"; + /** + * disposable Context. + */ + public static final String FRAGMENT_APPLICATION = "application"; + + /** + * upstream disposable Context. + */ + public static final String FRAGMENT_UPSTREAM_APPLICATION = "upstream-application"; + /** * the key of the header(key) list needed to be transmitted from upstream to downstream. */ @@ -93,8 +103,6 @@ public class MetadataContext extends com.tencent.polaris.metadata.core.manager.M if (!StringUtils.hasText(namespace)) { LOG.error("namespace should not be blank. please configure spring.cloud.polaris.namespace or " + "spring.cloud.polaris.discovery.namespace"); - throw new RuntimeException("namespace should not be blank. please configure spring.cloud.polaris.namespace or " - + "spring.cloud.polaris.discovery.namespace"); } namespace = DiscoveryUtil.rewriteNamespace(namespace); LOCAL_NAMESPACE = namespace; @@ -109,8 +117,6 @@ public class MetadataContext extends com.tencent.polaris.metadata.core.manager.M if (!StringUtils.hasText(serviceName)) { LOG.error("service name should not be blank. please configure spring.cloud.polaris.service or " + "spring.cloud.polaris.discovery.service or spring.application.name"); - throw new RuntimeException("service name should not be blank. please configure spring.cloud.polaris.service or " - + "spring.cloud.polaris.discovery.service or spring.application.name"); } serviceName = DiscoveryUtil.rewriteServiceId(serviceName); LOCAL_SERVICE = serviceName; @@ -120,8 +126,8 @@ public class MetadataContext extends com.tencent.polaris.metadata.core.manager.M super(MetadataConstant.POLARIS_TRANSITIVE_HEADER_PREFIX); } - private Map getMetadataAsMap(MetadataType metadataType, TransitiveType transitiveType, boolean downstream) { - MetadataContainer metadataContainer = getMetadataContainer(metadataType, downstream); + private Map getMetadataAsMap(MetadataType metadataType, TransitiveType transitiveType, boolean caller) { + MetadataContainer metadataContainer = getMetadataContainer(metadataType, caller); Map values = new HashMap<>(); metadataContainer.iterateMetadataValues(new BiConsumer() { @Override @@ -144,8 +150,8 @@ public class MetadataContext extends com.tencent.polaris.metadata.core.manager.M } } - private Map getMapMetadataAsMap(MetadataType metadataType, String mapKey, TransitiveType transitiveType, boolean downstream) { - MetadataContainer metadataContainer = getMetadataContainer(metadataType, downstream); + private Map getMapMetadataAsMap(MetadataType metadataType, String mapKey, TransitiveType transitiveType, boolean caller) { + MetadataContainer metadataContainer = getMetadataContainer(metadataType, caller); Map values = new HashMap<>(); MetadataValue metadataValue = metadataContainer.getMetadataValue(mapKey); if (!(metadataValue instanceof MetadataMapValue)) { @@ -167,8 +173,8 @@ public class MetadataContext extends com.tencent.polaris.metadata.core.manager.M } private void putMapMetadataAsMap(MetadataType metadataType, String mapKey, - TransitiveType transitiveType, boolean downstream, Map values) { - MetadataContainer metadataContainer = getMetadataContainer(metadataType, downstream); + TransitiveType transitiveType, boolean caller, Map values) { + MetadataContainer metadataContainer = getMetadataContainer(metadataType, caller); for (Map.Entry entry : values.entrySet()) { metadataContainer.putMetadataMapValue(mapKey, entry.getKey(), entry.getValue(), transitiveType); } @@ -178,10 +184,22 @@ public class MetadataContext extends com.tencent.polaris.metadata.core.manager.M return getFragmentContext(FRAGMENT_DISPOSABLE); } + public void setDisposableMetadata(Map disposableMetadata) { + putFragmentContext(FRAGMENT_DISPOSABLE, Collections.unmodifiableMap(disposableMetadata)); + } + public Map getTransitiveMetadata() { return getFragmentContext(FRAGMENT_TRANSITIVE); } + public void setTransitiveMetadata(Map transitiveMetadata) { + putFragmentContext(FRAGMENT_TRANSITIVE, Collections.unmodifiableMap(transitiveMetadata)); + } + + public Map getApplicationMetadata() { + return getFragmentContext(FRAGMENT_APPLICATION); + } + public Map getCustomMetadata() { Map transitiveMetadata = this.getTransitiveMetadata(); Map disposableMetadata = this.getDisposableMetadata(); @@ -227,14 +245,6 @@ public class MetadataContext extends com.tencent.polaris.metadata.core.manager.M metadataContainer.putMetadataMapObjectValue(FRAGMENT_LB_METADATA, key, value); } - public void setTransitiveMetadata(Map transitiveMetadata) { - putFragmentContext(FRAGMENT_TRANSITIVE, Collections.unmodifiableMap(transitiveMetadata)); - } - - public void setDisposableMetadata(Map disposableMetadata) { - putFragmentContext(FRAGMENT_DISPOSABLE, Collections.unmodifiableMap(disposableMetadata)); - } - public void setUpstreamDisposableMetadata(Map upstreamDisposableMetadata) { putFragmentContext(FRAGMENT_UPSTREAM_DISPOSABLE, Collections.unmodifiableMap(upstreamDisposableMetadata)); } @@ -255,6 +265,10 @@ public class MetadataContext extends com.tencent.polaris.metadata.core.manager.M return getMetadataAsMap(MetadataType.CUSTOM, TransitiveType.DISPOSABLE, false); case FRAGMENT_UPSTREAM_DISPOSABLE: return getMetadataAsMap(MetadataType.CUSTOM, TransitiveType.DISPOSABLE, true); + case FRAGMENT_APPLICATION: + return getMetadataAsMap(MetadataType.APPLICATION, TransitiveType.DISPOSABLE, false); + case FRAGMENT_UPSTREAM_APPLICATION: + return getMetadataAsMap(MetadataType.APPLICATION, TransitiveType.DISPOSABLE, true); case FRAGMENT_RAW_TRANSHEADERS: return getMapMetadataAsMap(MetadataType.CUSTOM, FRAGMENT_RAW_TRANSHEADERS, TransitiveType.NONE, false); case FRAGMENT_RAW_TRANSHEADERS_KV: @@ -289,6 +303,12 @@ public class MetadataContext extends com.tencent.polaris.metadata.core.manager.M case FRAGMENT_UPSTREAM_DISPOSABLE: putMetadataAsMap(MetadataType.CUSTOM, TransitiveType.DISPOSABLE, true, context); break; + case FRAGMENT_APPLICATION: + putMetadataAsMap(MetadataType.APPLICATION, TransitiveType.DISPOSABLE, false, context); + break; + case FRAGMENT_UPSTREAM_APPLICATION: + putMetadataAsMap(MetadataType.APPLICATION, TransitiveType.DISPOSABLE, true, context); + break; case FRAGMENT_RAW_TRANSHEADERS: putMapMetadataAsMap(MetadataType.CUSTOM, FRAGMENT_RAW_TRANSHEADERS, TransitiveType.NONE, false, context); break; diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContextHolder.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContextHolder.java index 71e1b7754..2a1ec1e3e 100644 --- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContextHolder.java +++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContextHolder.java @@ -22,7 +22,6 @@ import java.util.HashMap; import java.util.Map; import java.util.Optional; -import com.tencent.cloud.common.metadata.config.MetadataLocalProperties; import com.tencent.cloud.common.util.ApplicationContextAwareUtils; import com.tencent.polaris.metadata.core.MessageMetadataContainer; import com.tencent.polaris.metadata.core.MetadataContainer; @@ -43,8 +42,6 @@ import static com.tencent.cloud.common.metadata.MetadataContext.FRAGMENT_UPSTREA */ public final class MetadataContextHolder { - private static MetadataLocalProperties metadataLocalProperties; - private static StaticMetadataManager staticMetadataManager; static { @@ -60,28 +57,38 @@ public final class MetadataContextHolder { private static MetadataContext createMetadataManager() { MetadataContext metadataManager = new MetadataContext(); - if (metadataLocalProperties == null) { - metadataLocalProperties = ApplicationContextAwareUtils.getApplicationContext() - .getBean(MetadataLocalProperties.class); - } if (staticMetadataManager == null) { staticMetadataManager = ApplicationContextAwareUtils.getApplicationContext() .getBean(StaticMetadataManager.class); } + // local custom metadata MetadataContainer metadataContainer = metadataManager.getMetadataContainer(MetadataType.CUSTOM, false); + Map mergedStaticMetadata = staticMetadataManager.getMergedStaticMetadata(); + for (Map.Entry entry : mergedStaticMetadata.entrySet()) { + metadataContainer.putMetadataStringValue(entry.getKey(), entry.getValue(), TransitiveType.NONE); + } + // local custom transitive metadata Map mergedStaticTransitiveMetadata = staticMetadataManager.getMergedStaticTransitiveMetadata(); for (Map.Entry entry : mergedStaticTransitiveMetadata.entrySet()) { metadataContainer.putMetadataStringValue(entry.getKey(), entry.getValue(), TransitiveType.PASS_THROUGH); } + // local custom disposable metadata Map mergedStaticDisposableMetadata = staticMetadataManager.getMergedStaticDisposableMetadata(); for (Map.Entry entry : mergedStaticDisposableMetadata.entrySet()) { metadataContainer.putMetadataStringValue(entry.getKey(), entry.getValue(), TransitiveType.DISPOSABLE); } - + // local trans header if (StringUtils.hasText(staticMetadataManager.getTransHeader())) { String transHeader = staticMetadataManager.getTransHeader(); metadataContainer.putMetadataMapValue(MetadataContext.FRAGMENT_RAW_TRANSHEADERS, transHeader, "", TransitiveType.NONE); } + + // local application disposable metadata + MetadataContainer applicationMetadataContainer = metadataManager.getMetadataContainer(MetadataType.APPLICATION, false); + Map mergedApplicationMetadata = staticMetadataManager.getMergedStaticMetadata(); + for (Map.Entry entry : mergedApplicationMetadata.entrySet()) { + applicationMetadataContainer.putMetadataStringValue(entry.getKey(), entry.getValue(), TransitiveType.DISPOSABLE); + } return metadataManager; } @@ -133,24 +140,36 @@ public final class MetadataContextHolder { * Save metadata map to thread local. * * @param dynamicTransitiveMetadata custom metadata collection - * @param dynamicDisposableMetadata custom disposable metadata connection + * @param dynamicDisposableMetadata custom disposable metadata collection + * @param dynamicApplicationMetadata application metadata collection * @param callerMetadataProvider caller metadata provider */ public static void init(Map dynamicTransitiveMetadata, Map dynamicDisposableMetadata, - MetadataProvider callerMetadataProvider) { + Map dynamicApplicationMetadata, MetadataProvider callerMetadataProvider) { com.tencent.polaris.metadata.core.manager.MetadataContextHolder.refresh(metadataManager -> { + // caller transitive metadata to local custom transitive metadata MetadataContainer metadataContainerUpstream = metadataManager.getMetadataContainer(MetadataType.CUSTOM, false); if (!CollectionUtils.isEmpty(dynamicTransitiveMetadata)) { for (Map.Entry entry : dynamicTransitiveMetadata.entrySet()) { metadataContainerUpstream.putMetadataStringValue(entry.getKey(), entry.getValue(), TransitiveType.PASS_THROUGH); } } + // caller disposable metadata to caller custom disposable metadata MetadataContainer metadataContainerDownstream = metadataManager.getMetadataContainer(MetadataType.CUSTOM, true); if (!CollectionUtils.isEmpty(dynamicDisposableMetadata)) { for (Map.Entry entry : dynamicDisposableMetadata.entrySet()) { metadataContainerDownstream.putMetadataStringValue(entry.getKey(), entry.getValue(), TransitiveType.DISPOSABLE); } } + // caller application metadata to caller application disposable metadata + MetadataContainer applicationMetadataContainerDownstream = metadataManager.getMetadataContainer(MetadataType.APPLICATION, true); + if (!CollectionUtils.isEmpty(dynamicApplicationMetadata)) { + for (Map.Entry entry : dynamicApplicationMetadata.entrySet()) { + applicationMetadataContainerDownstream.putMetadataStringValue(entry.getKey(), entry.getValue(), TransitiveType.DISPOSABLE); + } + } + + // caller message metadata if (callerMetadataProvider != null) { MessageMetadataContainer callerMessageContainer = metadataManager.getMetadataContainer(MetadataType.MESSAGE, true); callerMessageContainer.setMetadataProvider(callerMetadataProvider); diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/StaticMetadataManager.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/StaticMetadataManager.java index f0171cebb..2a70e9f66 100644 --- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/StaticMetadataManager.java +++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/StaticMetadataManager.java @@ -261,7 +261,8 @@ public class StaticMetadataManager { List instanceMetadataProviders) { // resolve region info if (!CollectionUtils.isEmpty(instanceMetadataProviders)) { - Set providerRegions = instanceMetadataProviders.stream().map(InstanceMetadataProvider::getRegion).filter(region -> !StringUtils.isBlank(region)).collect(Collectors.toSet()); + Set providerRegions = instanceMetadataProviders.stream().map(InstanceMetadataProvider::getRegion) + .filter(region -> !StringUtils.isBlank(region)).collect(Collectors.toSet()); if (!CollectionUtils.isEmpty(providerRegions)) { if (providerRegions.size() > 1) { throw new IllegalArgumentException("Multiple Regions Provided in InstanceMetadataProviders"); @@ -278,7 +279,8 @@ public class StaticMetadataManager { // resolve zone info if (!CollectionUtils.isEmpty(instanceMetadataProviders)) { - Set providerZones = instanceMetadataProviders.stream().map(InstanceMetadataProvider::getZone).filter(zone -> !StringUtils.isBlank(zone)).collect(Collectors.toSet()); + Set providerZones = instanceMetadataProviders.stream().map(InstanceMetadataProvider::getZone) + .filter(zone -> !StringUtils.isBlank(zone)).collect(Collectors.toSet()); if (!CollectionUtils.isEmpty(providerZones)) { if (providerZones.size() > 1) { throw new IllegalArgumentException("Multiple Zones Provided in InstanceMetadataProviders"); @@ -295,7 +297,8 @@ public class StaticMetadataManager { // resolve campus info if (!CollectionUtils.isEmpty(instanceMetadataProviders)) { - Set providerCampus = instanceMetadataProviders.stream().map(InstanceMetadataProvider::getCampus).filter(campus -> !StringUtils.isBlank(campus)).collect(Collectors.toSet()); + Set providerCampus = instanceMetadataProviders.stream().map(InstanceMetadataProvider::getCampus) + .filter(campus -> !StringUtils.isBlank(campus)).collect(Collectors.toSet()); if (!CollectionUtils.isEmpty(providerCampus)) { if (providerCampus.size() > 1) { throw new IllegalArgumentException("Multiple Campus Provided in InstanceMetadataProviders"); diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/endpoint/PolarisMetadataEndpoint.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/endpoint/PolarisMetadataEndpoint.java index ea7954c37..bf22ce327 100644 --- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/endpoint/PolarisMetadataEndpoint.java +++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/endpoint/PolarisMetadataEndpoint.java @@ -41,7 +41,7 @@ public class PolarisMetadataEndpoint { @ReadOperation public Map metadata() { - Map result = new HashMap<>(); + Map result = new HashMap<>(); result.put("Env", staticMetadataManager.getAllEnvMetadata()); result.put("EnvTransitive", staticMetadataManager.getEnvTransitiveMetadata()); result.put("ConfigTransitive", staticMetadataManager.getConfigTransitiveMetadata()); diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/pojo/PolarisServiceInstance.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/pojo/PolarisServiceInstance.java index d5f28e597..8af64d5e5 100644 --- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/pojo/PolarisServiceInstance.java +++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/pojo/PolarisServiceInstance.java @@ -18,10 +18,12 @@ package com.tencent.cloud.common.pojo; import java.net.URI; +import java.util.HashMap; import java.util.Map; import java.util.Objects; import com.tencent.polaris.api.pojo.Instance; +import com.tencent.polaris.api.utils.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.springframework.cloud.client.DefaultServiceInstance; @@ -40,7 +42,13 @@ public class PolarisServiceInstance implements ServiceInstance { private final String scheme; + private final Map serviceMetadata; + public PolarisServiceInstance(Instance instance) { + this(instance, null); + } + + public PolarisServiceInstance(Instance instance, Map metadata) { this.instance = instance; this.isSecure = StringUtils.equalsIgnoreCase(instance.getProtocol(), "https"); if (isSecure) { @@ -49,6 +57,10 @@ public class PolarisServiceInstance implements ServiceInstance { else { scheme = "http"; } + this.serviceMetadata = new HashMap<>(); + if (CollectionUtils.isNotEmpty(metadata)) { + this.serviceMetadata.putAll(metadata); + } } public Instance getPolarisInstance() { @@ -95,6 +107,10 @@ public class PolarisServiceInstance implements ServiceInstance { return this.scheme; } + public Map getServiceMetadata() { + return serviceMetadata; + } + /** * To fix loadbalancer not working bug when importing spring-retry. * @param o object @@ -116,4 +132,14 @@ public class PolarisServiceInstance implements ServiceInstance { public int hashCode() { return Objects.hash(instance, scheme); } + + @Override + public String toString() { + return "PolarisServiceInstance{" + + "instance=" + instance + + ", isSecure=" + isSecure + + ", scheme='" + scheme + '\'' + + ", serviceMetadata=" + serviceMetadata + + '}'; + } } diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/tsf/TsfConstant.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/tsf/TsfConstant.java deleted file mode 100644 index dfc8949fe..000000000 --- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/tsf/TsfConstant.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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.common.tsf; - -/** - * Constant for TSF. - * - * @author Haotian Zhang - */ -public final class TsfConstant { - /** - * tsf application id. - */ - public static String TSF_APPLICATION_ID = "TSF_APPLICATION_ID"; - - /** - * tsf program version. - */ - public static String TSF_PROG_VERSION = "TSF_PROG_VERSION"; - - /** - * tsf group id. - */ - public static String TSF_GROUP_ID = "TSF_GROUP_ID"; - - /** - * tsf namespace id. - */ - public static String TSF_NAMESPACE_ID = "TSF_NAMESPACE_ID"; - - /** - * tsf instance id. - */ - public static String TSF_INSTNACE_ID = "TSF_INSTNACE_ID"; - - /** - * tsf region. - */ - public static String TSF_REGION = "TSF_REGION"; - - /** - * tsf zone. - */ - public static String TSF_ZONE = "TSF_ZONE"; - - /** - * tsf SDK version. - */ - public static String TSF_SDK_VERSION = "TSF_SDK_VERSION"; - - /** - * tsf tags. - */ - public static String TSF_TAGS = "TSF_TAGS"; - - private TsfConstant() { - } -} diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/ExpressionLabelUtils.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/ExpressionLabelUtils.java index eea811de7..203fa4727 100644 --- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/ExpressionLabelUtils.java +++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/ExpressionLabelUtils.java @@ -137,7 +137,7 @@ public final class ExpressionLabelUtils { } public static String getQueryValue(String queryString, String queryKey) { - return getQueryValue(queryString, queryKey, StringUtils.EMPTY); + return getQueryValue(queryString, queryKey, null); } public static String getQueryValue(String queryString, String queryKey, String defaultValue) { @@ -159,31 +159,31 @@ public final class ExpressionLabelUtils { public static String getFirstValue(Map> valueMaps, String key) { if (CollectionUtils.isEmpty(valueMaps)) { - return StringUtils.EMPTY; + return null; } Collection values = valueMaps.get(key); if (CollectionUtils.isEmpty(values)) { - return StringUtils.EMPTY; + return null; } for (String value : values) { return value; } - return StringUtils.EMPTY; + return null; } public static String getCookieFirstValue(Map> valueMaps, String key) { if (CollectionUtils.isEmpty(valueMaps)) { - return StringUtils.EMPTY; + return null; } Collection values = valueMaps.get(HttpHeaderNames.COOKIE.toString()); if (CollectionUtils.isEmpty(values)) { - return StringUtils.EMPTY; + return null; } for (String value : values) { @@ -195,6 +195,6 @@ public final class ExpressionLabelUtils { } } } - return StringUtils.EMPTY; + return null; } } diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/SpringWebExpressionLabelUtils.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/SpringWebExpressionLabelUtils.java index 476aeeecf..7e4276d57 100644 --- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/SpringWebExpressionLabelUtils.java +++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/SpringWebExpressionLabelUtils.java @@ -75,7 +75,7 @@ public final class SpringWebExpressionLabelUtils { labels.put(labelKey, getCookieValue(exchange.getRequest(), cookieKey)); } else if (ExpressionLabelUtils.isMethodLabel(labelKey)) { - labels.put(labelKey, exchange.getRequest().getMethodValue()); + labels.put(labelKey, exchange.getRequest().getMethod().toString()); } else if (ExpressionLabelUtils.isUriLabel(labelKey)) { labels.put(labelKey, exchange.getRequest().getURI().getPath()); @@ -118,7 +118,7 @@ public final class SpringWebExpressionLabelUtils { labels.put(labelKey, getCookieValue(request, cookieKey)); } else if (ExpressionLabelUtils.isMethodLabel(labelKey)) { - labels.put(labelKey, request.getMethodValue()); + labels.put(labelKey, request.getMethod().toString()); } else if (ExpressionLabelUtils.isUriLabel(labelKey)) { labels.put(labelKey, request.getURI().getPath()); @@ -129,7 +129,7 @@ public final class SpringWebExpressionLabelUtils { } public static String getHeaderValue(ServerHttpRequest request, String key) { - return getHeaderValue(request, key, StringUtils.EMPTY); + return getHeaderValue(request, key, null); } public static String getHeaderValue(ServerHttpRequest request, String key, String defaultValue) { @@ -141,7 +141,7 @@ public final class SpringWebExpressionLabelUtils { } public static String getQueryValue(ServerHttpRequest request, String key) { - return getQueryValue(request, key, StringUtils.EMPTY); + return getQueryValue(request, key, null); } public static String getQueryValue(ServerHttpRequest request, String key, String defaultValue) { @@ -157,7 +157,7 @@ public final class SpringWebExpressionLabelUtils { } public static String getCookieValue(ServerHttpRequest request, String key) { - return getCookieValue(request, key, StringUtils.EMPTY); + return getCookieValue(request, key, null); } public static String getCookieValue(ServerHttpRequest request, String key, String defaultValue) { @@ -181,7 +181,7 @@ public final class SpringWebExpressionLabelUtils { public static String getCookieValue(HttpRequest request, String key) { String first = request.getHeaders().getFirst(HttpHeaders.COOKIE); if (StringUtils.isEmpty(first)) { - return StringUtils.EMPTY; + return null; } String[] cookieArray = StringUtils.split(first, ";"); for (String cookieItem : cookieArray) { @@ -190,6 +190,6 @@ public final class SpringWebExpressionLabelUtils { return cookieKv[1]; } } - return StringUtils.EMPTY; + return null; } } diff --git a/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/metadata/MetadataContextHolderTest.java b/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/metadata/MetadataContextHolderTest.java index b21344fa4..6f54ff7ba 100644 --- a/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/metadata/MetadataContextHolderTest.java +++ b/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/metadata/MetadataContextHolderTest.java @@ -63,7 +63,7 @@ public class MetadataContextHolderTest { customMetadata.put("a", "1"); customMetadata.put("b", "22"); customMetadata.put("c", "3"); - MetadataContextHolder.init(customMetadata, new HashMap<>(), null); + MetadataContextHolder.init(customMetadata, new HashMap<>(), new HashMap<>(), null); metadataContext = MetadataContextHolder.get(); customMetadata = metadataContext.getTransitiveMetadata(); Assertions.assertThat(customMetadata.get("a")).isEqualTo("1"); diff --git a/spring-cloud-tencent-examples/quickstart-example/quickstart-callee-service-a/src/main/java/com/tencent/cloud/quickstart/callee/QuickstartCalleeController.java b/spring-cloud-tencent-examples/quickstart-example/quickstart-callee-service-a/src/main/java/com/tencent/cloud/quickstart/callee/QuickstartCalleeController.java index 2370d4c17..88919d5ae 100644 --- a/spring-cloud-tencent-examples/quickstart-example/quickstart-callee-service-a/src/main/java/com/tencent/cloud/quickstart/callee/QuickstartCalleeController.java +++ b/spring-cloud-tencent-examples/quickstart-example/quickstart-callee-service-a/src/main/java/com/tencent/cloud/quickstart/callee/QuickstartCalleeController.java @@ -123,4 +123,10 @@ public class QuickstartCalleeController { LOG.info("Quickstart Callee Service [{}:{}] is detected right.", ip, port); return String.format("Quickstart Callee Service [%s:%s] is detected right.", ip, port); } + + @GetMapping("/test/{num}/echo") + public String test(@PathVariable int num) { + LOG.info("Quickstart Callee Service [%s] is detected right.", num); + return String.format("Quickstart Callee Service [%s] is detected right.", num); + } } diff --git a/spring-cloud-tencent-examples/quickstart-example/quickstart-caller-service/src/main/java/com/tencent/cloud/quickstart/caller/QuickstartCallerController.java b/spring-cloud-tencent-examples/quickstart-example/quickstart-caller-service/src/main/java/com/tencent/cloud/quickstart/caller/QuickstartCallerController.java index d5f55a97d..25764d052 100644 --- a/spring-cloud-tencent-examples/quickstart-example/quickstart-caller-service/src/main/java/com/tencent/cloud/quickstart/caller/QuickstartCallerController.java +++ b/spring-cloud-tencent-examples/quickstart-example/quickstart-caller-service/src/main/java/com/tencent/cloud/quickstart/caller/QuickstartCallerController.java @@ -18,18 +18,24 @@ package com.tencent.cloud.quickstart.caller; import java.util.Collections; +import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.metadata.MetadataContextHolder; +import com.tencent.polaris.api.utils.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import reactor.core.publisher.Mono; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @@ -76,8 +82,25 @@ public class QuickstartCallerController { * @return information of callee */ @GetMapping("/rest") - public String rest() { - return restTemplate.getForObject("http://QuickstartCalleeService/quickstart/callee/info", String.class); + public ResponseEntity rest(@RequestHeader Map headerMap) { + String url = "http://QuickstartCalleeService/quickstart/callee/info"; + + HttpHeaders headers = new HttpHeaders(); + for (Map.Entry entry : headerMap.entrySet()) { + if (StringUtils.isNotBlank(entry.getKey()) && StringUtils.isNotBlank(entry.getValue()) + && !entry.getKey().contains("sct-") + && !entry.getKey().contains("SCT-") + && !entry.getKey().contains("polaris-") + && !entry.getKey().contains("POLARIS-")) { + headers.add(entry.getKey(), entry.getValue()); + } + } + + // 创建 HttpEntity 实例并传入 HttpHeaders + HttpEntity entity = new HttpEntity<>(headers); + + // 使用 exchange 方法发送 GET 请求,并获取响应 + return restTemplate.exchange(url, HttpMethod.GET, entity, String.class); } /** diff --git a/spring-cloud-tencent-examples/quickstart-example/quickstart-caller-service/src/main/java/com/tencent/cloud/quickstart/caller/router/CustomRouterLabelResolver.java b/spring-cloud-tencent-examples/quickstart-example/quickstart-caller-service/src/main/java/com/tencent/cloud/quickstart/caller/router/CustomRouterLabelResolver.java deleted file mode 100644 index 18f3d0cac..000000000 --- a/spring-cloud-tencent-examples/quickstart-example/quickstart-caller-service/src/main/java/com/tencent/cloud/quickstart/caller/router/CustomRouterLabelResolver.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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.quickstart.caller.router; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -import com.google.gson.Gson; -import com.tencent.cloud.polaris.router.spi.FeignRouterLabelResolver; -import feign.RequestTemplate; - -import org.springframework.stereotype.Component; - -/** - * - * Customize the business tag information obtained from the request - * - *@author lepdou 2022-05-12 - */ -@Component -public class CustomRouterLabelResolver implements FeignRouterLabelResolver { - private final Gson gson = new Gson(); - - @Override - public Map resolve(RequestTemplate requestTemplate, Set expressionLabelKeys) { - Map labels = new HashMap<>(); - - labels.put("label1", "value1"); - - return labels; - } - - @Override - public int getOrder() { - return 0; - } -} diff --git a/spring-cloud-tencent-examples/tsf-example/consumer-demo/pom.xml b/spring-cloud-tencent-examples/tsf-example/consumer-demo/pom.xml index 9c9494728..968784284 100644 --- a/spring-cloud-tencent-examples/tsf-example/consumer-demo/pom.xml +++ b/spring-cloud-tencent-examples/tsf-example/consumer-demo/pom.xml @@ -27,6 +27,11 @@ spring-cloud-starter-tencent-polaris-contract + + com.tencent.cloud + spring-cloud-starter-tencent-polaris-router + + org.springframework.boot spring-boot-starter-web diff --git a/spring-cloud-tencent-examples/tsf-example/consumer-demo/src/main/java/com/tencent/cloud/tsf/demo/consumer/controller/ConsumerController.java b/spring-cloud-tencent-examples/tsf-example/consumer-demo/src/main/java/com/tencent/cloud/tsf/demo/consumer/controller/ConsumerController.java index cb98fa80f..11693c71f 100644 --- a/spring-cloud-tencent-examples/tsf-example/consumer-demo/src/main/java/com/tencent/cloud/tsf/demo/consumer/controller/ConsumerController.java +++ b/spring-cloud-tencent-examples/tsf-example/consumer-demo/src/main/java/com/tencent/cloud/tsf/demo/consumer/controller/ConsumerController.java @@ -22,6 +22,7 @@ import java.util.Map; import com.tencent.cloud.tsf.demo.consumer.proxy.ProviderDemoService; import com.tencent.cloud.tsf.demo.consumer.proxy.ProviderService; +import com.tencent.polaris.api.utils.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.tsf.core.context.TsfContext; @@ -29,6 +30,7 @@ import org.springframework.tsf.core.entity.Tag; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @@ -42,7 +44,12 @@ public class ConsumerController { private ProviderDemoService providerDemoService; @RequestMapping(value = "/echo-rest/{str}", method = RequestMethod.GET) - public String restProvider(@PathVariable String str) { + public String restProvider(@PathVariable String str, + @RequestParam(required = false) String tagName, + @RequestParam(required = false) String tagValue) { + if (StringUtils.isNotBlank(tagName)) { + TsfContext.putTag(tagName, tagValue); + } TsfContext.putTag("operation", "rest"); Map mTags = new HashMap<>(); mTags.put("rest-trace-key1", "value1"); @@ -52,7 +59,12 @@ public class ConsumerController { } @RequestMapping(value = "/echo-feign/{str}", method = RequestMethod.GET) - public String feignProvider(@PathVariable String str) { + public String feignProvider(@PathVariable String str, + @RequestParam(required = false) String tagName, + @RequestParam(required = false) String tagValue) { + if (StringUtils.isNotBlank(tagName)) { + TsfContext.putTag(tagName, tagValue); + } TsfContext.putTag("operation", "feign"); Map mTags = new HashMap<>(); mTags.put("feign-trace-key1", "value1"); @@ -62,7 +74,12 @@ public class ConsumerController { } @RequestMapping(value = "/echo-feign-url/{str}", method = RequestMethod.GET) - public String feignUrlProvider(@PathVariable String str) { + public String feignUrlProvider(@PathVariable String str, + @RequestParam(required = false) String tagName, + @RequestParam(required = false) String tagValue) { + if (StringUtils.isNotBlank(tagName)) { + TsfContext.putTag(tagName, tagValue); + } TsfContext.putTag("operation", "feignUrl"); Map mTags = new HashMap<>(); mTags.put("feignUrl-trace-key1", "value1"); diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/tsf/TsfSpanAttributesProvider.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/tsf/TsfSpanAttributesProvider.java index d4bc6882d..3fe48314c 100644 --- a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/tsf/TsfSpanAttributesProvider.java +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/tsf/TsfSpanAttributesProvider.java @@ -21,11 +21,11 @@ package com.tencent.cloud.plugin.trace.tsf; import java.util.HashMap; import java.util.Map; -import com.tencent.cloud.common.tsf.TsfConstant; import com.tencent.cloud.plugin.trace.SpanAttributesProvider; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; 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; @@ -39,11 +39,11 @@ public class TsfSpanAttributesProvider implements SpanAttributesProvider { } ServiceInstance targetServiceInstance = context.getTargetServiceInstance(); if (null != targetServiceInstance && CollectionUtils.isNotEmpty(targetServiceInstance.getMetadata())) { - String nsId = targetServiceInstance.getMetadata().get(TsfConstant.TSF_NAMESPACE_ID); + String nsId = targetServiceInstance.getMetadata().get(TsfMetadataConstants.TSF_NAMESPACE_ID); attributes.put("remote.namespace-id", StringUtils.defaultString(nsId)); - String groupId = targetServiceInstance.getMetadata().get(TsfConstant.TSF_GROUP_ID); + String groupId = targetServiceInstance.getMetadata().get(TsfMetadataConstants.TSF_GROUP_ID); attributes.put("remote.group-id", StringUtils.defaultString(groupId)); - String applicationId = targetServiceInstance.getMetadata().get(TsfConstant.TSF_APPLICATION_ID); + String applicationId = targetServiceInstance.getMetadata().get(TsfMetadataConstants.TSF_APPLICATION_ID); attributes.put("remote.application-id", StringUtils.defaultString(applicationId)); } return attributes; diff --git a/spring-cloud-tencent-polaris-context/pom.xml b/spring-cloud-tencent-polaris-context/pom.xml index b24d40d89..bf6279b5c 100644 --- a/spring-cloud-tencent-polaris-context/pom.xml +++ b/spring-cloud-tencent-polaris-context/pom.xml @@ -173,6 +173,16 @@ polaris-router-factory + + com.tencent.polaris + polaris-circuitbreaker-factory + + + + com.tencent.polaris + polaris-ratelimit-factory + + com.tencent.polaris loadbalancer-random diff --git a/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/tsf/TsfUtils.java b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/tsf/TsfUtils.java new file mode 100644 index 000000000..e393d7551 --- /dev/null +++ b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/tsf/TsfUtils.java @@ -0,0 +1,80 @@ +/* + * 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.polaris.context.tsf; + +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import com.tencent.cloud.common.util.inet.PolarisInetUtils; +import com.tencent.cloud.polaris.context.tsf.config.TsfCoreProperties; + +import org.springframework.util.StringUtils; + +/** + * + * + * @author Haotian Zhang + */ +public final class TsfUtils { + + /** + * IPV4. + */ + public static String TSF_ADDRESS_IPV4 = "TSF_ADDRESS_IPV4"; + + /** + * IPV6. + */ + public static String TSF_ADDRESS_IPV6 = "TSF_ADDRESS_IPV6"; + + private TsfUtils() { + } + + public static List createTags(TsfCoreProperties properties) { + List tags = new LinkedList<>(properties.getTags()); + + if (StringUtils.hasText(properties.getInstanceZone())) { + tags.add(properties.getDefaultZoneMetadataName() + "=" + properties.getInstanceZone()); + } + if (StringUtils.hasText(properties.getInstanceGroup())) { + tags.add("group=" + properties.getInstanceGroup()); + } + + //store the secure flag in the tags so that clients will be able to figure out whether to use http or https automatically + tags.add("secure=" + properties.getScheme().equalsIgnoreCase("https")); + + return tags; + } + + public static Map appendMetaIpAddress(Map meta) { + if (meta == null) { + return null; + } + String ipv4Address = PolarisInetUtils.getIpString(false); + if (ipv4Address != null) { + meta.put(TSF_ADDRESS_IPV4, ipv4Address); + } + + String ipv6Address = PolarisInetUtils.getIpString(true); + if (ipv6Address != null) { + meta.put(TSF_ADDRESS_IPV6, ipv6Address); + } + return meta; + } +} diff --git a/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/tsf/config/TsfCoreProperties.java b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/tsf/config/TsfCoreProperties.java index 6a617639f..fefb528d9 100644 --- a/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/tsf/config/TsfCoreProperties.java +++ b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/tsf/config/TsfCoreProperties.java @@ -17,6 +17,9 @@ package com.tencent.cloud.polaris.context.tsf.config; +import java.util.ArrayList; +import java.util.List; + import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; @@ -37,6 +40,12 @@ public class TsfCoreProperties { @Value("${tse_polaris_enable:false}") private boolean tsePolarisEnable = false; + /** + * Unique service instance id. + */ + @Value("${tsf_instance_id:${spring.cloud.consul.discovery.instanceId:${SPRING_CLOUD_CONSUL_DISCOVERY_INSTANCEID:}}}") + private String instanceId; + /** * tsf service consul registration tags. *

@@ -53,12 +62,67 @@ public class TsfCoreProperties { @Value("${tsf_group_id:}") private String tsfGroupId; + /** + * tsf service consul registration tags. + * + * progVersion 包版本 + */ + @Value("${tsf_prog_version:}") + private String tsfProgVersion; + /** * 仅本地测试时使用. */ @Value("${tsf_namespace_id:}") private String tsfNamespaceId; + /** + * tsf service consul registration tags. + * + * 地域信息 + */ + @Value("${tsf_region:}") + private String tsfRegion; + + /** + * tsf service consul registration tags. + * + * 可用区信息 + */ + @Value("${tsf_zone:}") + private String tsfZone; + + /** + * Tags to use when registering service. + */ + @Value("${tsf.discovery.tags:}") + private List tags = new ArrayList<>(); + + /** + * Service instance zone. + */ + @Value("${tsf.discovery.instanceZone:}") + private String instanceZone; + + /** + * Service instance group. + */ + @Value("${tsf.discovery.instanceGroup:}") + private String instanceGroup; + + /** + * Service instance zone comes from metadata. + * This allows changing the metadata tag name. + */ + @Value("${tsf.discovery.defaultZoneMetadataName:zone}") + private String defaultZoneMetadataName = "zone"; + + /** + * Whether to register an http or https service. + */ + @Value("${tsf.discovery.scheme:http}") + private String scheme = "http"; + public String getTsePolarisIp() { return tsePolarisIp; } @@ -83,6 +147,14 @@ public class TsfCoreProperties { this.tsePolarisEnable = tsePolarisEnable; } + public String getInstanceId() { + return instanceId; + } + + public void setInstanceId(String instanceId) { + this.instanceId = instanceId; + } + public String getTsfApplicationId() { return tsfApplicationId; } @@ -99,6 +171,14 @@ public class TsfCoreProperties { this.tsfGroupId = tsfGroupId; } + public String getTsfProgVersion() { + return tsfProgVersion; + } + + public void setTsfProgVersion(final String tsfProgVersion) { + this.tsfProgVersion = tsfProgVersion; + } + public String getTsfNamespaceId() { return tsfNamespaceId; } @@ -107,15 +187,80 @@ public class TsfCoreProperties { this.tsfNamespaceId = tsfNamespaceId; } + public String getTsfRegion() { + return tsfRegion; + } + + public void setTsfRegion(final String tsfRegion) { + this.tsfRegion = tsfRegion; + } + + public String getTsfZone() { + return tsfZone; + } + + public void setTsfZone(final String tsfZone) { + this.tsfZone = tsfZone; + } + + public List getTags() { + return tags; + } + + public void setTags(List tags) { + this.tags = tags; + } + + public String getInstanceZone() { + return instanceZone; + } + + public void setInstanceZone(String instanceZone) { + this.instanceZone = instanceZone; + } + + public String getInstanceGroup() { + return instanceGroup; + } + + public void setInstanceGroup(String instanceGroup) { + this.instanceGroup = instanceGroup; + } + + public String getDefaultZoneMetadataName() { + return defaultZoneMetadataName; + } + + public void setDefaultZoneMetadataName(String defaultZoneMetadataName) { + this.defaultZoneMetadataName = defaultZoneMetadataName; + } + + public String getScheme() { + return scheme; + } + + public void setScheme(String scheme) { + this.scheme = scheme; + } + @Override public String toString() { return "TsfCoreProperties{" + "tsePolarisIp='" + tsePolarisIp + '\'' + ", tsfConsulEnable=" + tsfConsulEnable + ", tsePolarisEnable=" + tsePolarisEnable + + ", instanceId='" + instanceId + '\'' + ", tsfApplicationId='" + tsfApplicationId + '\'' + ", tsfGroupId='" + tsfGroupId + '\'' + + ", tsfProgVersion='" + tsfProgVersion + '\'' + ", tsfNamespaceId='" + tsfNamespaceId + '\'' + + ", tsfRegion='" + tsfRegion + '\'' + + ", tsfZone='" + tsfZone + '\'' + + ", tags=" + tags + + ", instanceZone='" + instanceZone + '\'' + + ", instanceGroup='" + instanceGroup + '\'' + + ", defaultZoneMetadataName='" + defaultZoneMetadataName + '\'' + + ", scheme='" + scheme + '\'' + '}'; } } diff --git a/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/tsf/env/TsfCoreEnvironmentPostProcessor.java b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/tsf/env/TsfCoreEnvironmentPostProcessor.java index 56d71668d..9316fa90e 100644 --- a/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/tsf/env/TsfCoreEnvironmentPostProcessor.java +++ b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/tsf/env/TsfCoreEnvironmentPostProcessor.java @@ -122,7 +122,7 @@ public final class TsfCoreEnvironmentPostProcessor implements EnvironmentPostPro // tse_polaris_ip defaultProperties.put("spring.cloud.polaris.address", "grpc://" + environment.getProperty("tse_polaris_ip", "") + ":8091"); - // tsf_sctt_extensions_port + // tse_polaris_ip defaultProperties.put("spring.cloud.polaris.stat.port", environment.getProperty("tsf_sctt_extensions_port", "11134")); // rule based router fail over type diff --git a/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/tsf/metadata/TsfInstanceMetadataAutoConfiguration.java b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/tsf/metadata/TsfInstanceMetadataAutoConfiguration.java new file mode 100644 index 000000000..5c05baa41 --- /dev/null +++ b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/tsf/metadata/TsfInstanceMetadataAutoConfiguration.java @@ -0,0 +1,43 @@ +/* + * 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.polaris.context.tsf.metadata; + +import com.tencent.cloud.common.spi.InstanceMetadataProvider; +import com.tencent.cloud.common.tsf.ConditionalOnTsfEnabled; +import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration; +import com.tencent.cloud.polaris.context.tsf.config.TsfCoreProperties; + +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * Auto configuration for instanceMetadataProvider for TSF. + * + * @author Hoatian Zhang + */ +@Configuration(proxyBeanMethods = false) +@AutoConfigureAfter(PolarisContextAutoConfiguration.class) +@ConditionalOnTsfEnabled +public class TsfInstanceMetadataAutoConfiguration { + + @Bean + public InstanceMetadataProvider tsfInstanceMetadataProvider(TsfCoreProperties tsfCoreProperties) { + return new TsfInstanceMetadataProvider(tsfCoreProperties); + } +} diff --git a/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/tsf/metadata/TsfInstanceMetadataProvider.java b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/tsf/metadata/TsfInstanceMetadataProvider.java new file mode 100644 index 000000000..f11877c7a --- /dev/null +++ b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/tsf/metadata/TsfInstanceMetadataProvider.java @@ -0,0 +1,77 @@ +/* + * 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.polaris.context.tsf.metadata; + +import java.util.HashMap; +import java.util.Map; + +import com.tencent.cloud.common.constant.SdkVersion; +import com.tencent.cloud.common.constant.WarmupCons; +import com.tencent.cloud.common.spi.InstanceMetadataProvider; +import com.tencent.cloud.common.util.JacksonUtils; +import com.tencent.cloud.common.util.inet.PolarisInetUtils; +import com.tencent.cloud.polaris.context.tsf.TsfUtils; +import com.tencent.cloud.polaris.context.tsf.config.TsfCoreProperties; +import com.tencent.polaris.api.utils.StringUtils; +import com.tencent.polaris.metadata.core.constant.TsfMetadataConstants; + +import static com.tencent.cloud.polaris.context.tsf.TsfUtils.TSF_ADDRESS_IPV4; +import static com.tencent.cloud.polaris.context.tsf.TsfUtils.TSF_ADDRESS_IPV6; + + +/** + * InstanceMetadataProvider for TSF. + * + * @author Hoatian Zhang + */ +public class TsfInstanceMetadataProvider implements InstanceMetadataProvider { + + private final TsfCoreProperties tsfCoreProperties; + + public TsfInstanceMetadataProvider(TsfCoreProperties tsfCoreProperties) { + this.tsfCoreProperties = tsfCoreProperties; + } + + @Override + public Map getMetadata() { + return new HashMap() {{ + put(TsfMetadataConstants.TSF_PROG_VERSION, tsfCoreProperties.getTsfProgVersion()); + put(TsfMetadataConstants.TSF_APPLICATION_ID, tsfCoreProperties.getTsfApplicationId()); + put(TsfMetadataConstants.TSF_GROUP_ID, tsfCoreProperties.getTsfGroupId()); + put(TsfMetadataConstants.TSF_APPLICATION_ID, tsfCoreProperties.getTsfApplicationId()); + put(TsfMetadataConstants.TSF_PROG_VERSION, tsfCoreProperties.getTsfProgVersion()); + put(TsfMetadataConstants.TSF_GROUP_ID, tsfCoreProperties.getTsfGroupId()); + put(TsfMetadataConstants.TSF_NAMESPACE_ID, tsfCoreProperties.getTsfNamespaceId()); + put(TsfMetadataConstants.TSF_INSTNACE_ID, tsfCoreProperties.getInstanceId()); + put(TsfMetadataConstants.TSF_REGION, tsfCoreProperties.getTsfRegion()); + put(TsfMetadataConstants.TSF_ZONE, tsfCoreProperties.getTsfZone()); + // 处理预热相关的参数 + put(WarmupCons.TSF_START_TIME, String.valueOf(System.currentTimeMillis())); + put(TsfMetadataConstants.TSF_SDK_VERSION, SdkVersion.get()); + put(TsfMetadataConstants.TSF_TAGS, JacksonUtils.serialize2Json(TsfUtils.createTags(tsfCoreProperties))); + String ipv4Address = PolarisInetUtils.getIpString(false); + if (StringUtils.isNotBlank(ipv4Address)) { + put(TSF_ADDRESS_IPV4, ipv4Address); + } + String ipv6Address = PolarisInetUtils.getIpString(true); + if (StringUtils.isNotBlank(ipv6Address)) { + put(TSF_ADDRESS_IPV6, ipv6Address); + } + }}; + } +} diff --git a/spring-cloud-tencent-polaris-context/src/main/resources/META-INF/spring.factories b/spring-cloud-tencent-polaris-context/src/main/resources/META-INF/spring.factories index 185201262..98536998a 100644 --- a/spring-cloud-tencent-polaris-context/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-tencent-polaris-context/src/main/resources/META-INF/spring.factories @@ -2,7 +2,8 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration,\ com.tencent.cloud.polaris.context.config.PolarisContextPostConfiguration,\ com.tencent.cloud.polaris.context.tsf.consul.TsfConsulAutoConfiguration,\ - com.tencent.cloud.polaris.context.tsf.config.TsfCorePropertiesAutoConfiguration + com.tencent.cloud.polaris.context.tsf.config.TsfCorePropertiesAutoConfiguration,\ + com.tencent.cloud.polaris.context.tsf.metadata.TsfInstanceMetadataAutoConfiguration org.springframework.cloud.bootstrap.BootstrapConfiguration=\ com.tencent.cloud.polaris.context.config.PolarisContextBootstrapAutoConfiguration,\ com.tencent.cloud.polaris.context.tsf.config.TsfCorePropertiesBootstrapConfiguration,\ diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/transformer/PolarisInstanceTransformer.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/transformer/PolarisInstanceTransformer.java index a44ef3a56..73f6db5cc 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/transformer/PolarisInstanceTransformer.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/transformer/PolarisInstanceTransformer.java @@ -20,6 +20,7 @@ package com.tencent.cloud.rpc.enhancement.transformer; import com.tencent.cloud.common.pojo.PolarisServiceInstance; import com.tencent.polaris.api.pojo.DefaultInstance; +import com.tencent.polaris.api.utils.CollectionUtils; import org.springframework.cloud.client.ServiceInstance; @@ -38,6 +39,9 @@ public class PolarisInstanceTransformer implements InstanceTransformer { instance.setZone(polarisServiceInstance.getPolarisInstance().getZone()); instance.setCampus(polarisServiceInstance.getPolarisInstance().getCampus()); instance.setWeight(polarisServiceInstance.getPolarisInstance().getWeight()); + if (CollectionUtils.isNotEmpty(polarisServiceInstance.getServiceMetadata())) { + instance.getServiceMetadata().putAll(polarisServiceInstance.getServiceMetadata()); + } } }