Skip to content

Commit

Permalink
feat: support lane router (#1378)
Browse files Browse the repository at this point in the history
Co-authored-by: Haotian Zhang <skyebefreeman@qq.com>
Co-authored-by: andrew shan <45474304+andrewshan@users.noreply.github.com>
  • Loading branch information
3 people committed Aug 13, 2024
1 parent f5bb38c commit 3606712
Show file tree
Hide file tree
Showing 40 changed files with 1,288 additions and 486 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
- [feat:upgrade jacoco version.](https://github.com/Tencent/spring-cloud-tencent/pull/1307)
- [fix: fix RouterLabelRestTemplateInterceptor add response headers exception with httpclient5.](https://github.com/Tencent/spring-cloud-tencent/pull/1376)
- [feat: support lossless online and offline](https://github.com/Tencent/spring-cloud-tencent/pull/1377)
- [feat: support lane router](https://github.com/Tencent/spring-cloud-tencent/pull/1378)
24 changes: 24 additions & 0 deletions spring-cloud-starter-tencent-metadata-transfer/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-commons</artifactId>
</dependency>

<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-rpc-enhancement</artifactId>
</dependency>

<!-- Spring Cloud Tencent dependencies end -->

<dependency>
Expand Down Expand Up @@ -50,6 +56,24 @@
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>com.tencent.polaris</groupId>
<artifactId>polaris-test-mock-discovery</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>com.tencent.polaris</groupId>
<artifactId>polaris-test-common</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -18,29 +18,21 @@

package com.tencent.cloud.metadata.config;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.tencent.cloud.common.constant.OrderConstant;
import com.tencent.cloud.metadata.core.DecodeTransferMetadataReactiveFilter;
import com.tencent.cloud.metadata.core.DecodeTransferMetadataServletFilter;
import com.tencent.cloud.metadata.core.EncodeTransferMedataFeignInterceptor;
import com.tencent.cloud.metadata.core.EncodeTransferMedataRestTemplateInterceptor;
import com.tencent.cloud.metadata.core.EncodeTransferMedataScgFilter;
import com.tencent.cloud.metadata.core.EncodeTransferMedataWebClientFilter;
import com.tencent.cloud.metadata.core.EncodeTransferMedataFeignEnhancedPlugin;
import com.tencent.cloud.metadata.core.EncodeTransferMedataRestTemplateEnhancedPlugin;
import com.tencent.cloud.metadata.core.EncodeTransferMedataScgEnhancedPlugin;
import com.tencent.cloud.metadata.core.EncodeTransferMedataWebClientEnhancedPlugin;
import com.tencent.cloud.polaris.context.config.PolarisContextProperties;

import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.reactive.function.client.WebClient;

import static javax.servlet.DispatcherType.ASYNC;
import static javax.servlet.DispatcherType.ERROR;
Expand Down Expand Up @@ -74,8 +66,8 @@ public FilterRegistrationBean<DecodeTransferMetadataServletFilter> metadataServl
}

@Bean
public DecodeTransferMetadataServletFilter metadataServletFilter() {
return new DecodeTransferMetadataServletFilter();
public DecodeTransferMetadataServletFilter metadataServletFilter(PolarisContextProperties polarisContextProperties) {
return new DecodeTransferMetadataServletFilter(polarisContextProperties);
}
}

Expand All @@ -87,8 +79,8 @@ public DecodeTransferMetadataServletFilter metadataServletFilter() {
protected static class MetadataReactiveFilterConfig {

@Bean
public DecodeTransferMetadataReactiveFilter metadataReactiveFilter() {
return new DecodeTransferMetadataReactiveFilter();
public DecodeTransferMetadataReactiveFilter metadataReactiveFilter(PolarisContextProperties polarisContextProperties) {
return new DecodeTransferMetadataReactiveFilter(polarisContextProperties);
}
}

Expand All @@ -97,11 +89,12 @@ public DecodeTransferMetadataReactiveFilter metadataReactiveFilter() {
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(name = "org.springframework.cloud.gateway.filter.GlobalFilter")
@ConditionalOnProperty(value = "spring.cloud.tencent.rpc-enhancement.enabled", havingValue = "true", matchIfMissing = true)
protected static class MetadataTransferScgFilterConfig {

@Bean
public GlobalFilter encodeTransferMedataScgFilter() {
return new EncodeTransferMedataScgFilter();
public EncodeTransferMedataScgEnhancedPlugin encodeTransferMedataScgEnhancedPlugin() {
return new EncodeTransferMedataScgEnhancedPlugin();
}
}

Expand All @@ -110,11 +103,12 @@ public GlobalFilter encodeTransferMedataScgFilter() {
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(name = "feign.Feign")
@ConditionalOnProperty(value = "spring.cloud.tencent.rpc-enhancement.enabled", havingValue = "true", matchIfMissing = true)
protected static class MetadataTransferFeignInterceptorConfig {

@Bean
public EncodeTransferMedataFeignInterceptor encodeTransferMedataFeignInterceptor() {
return new EncodeTransferMedataFeignInterceptor();
public EncodeTransferMedataFeignEnhancedPlugin encodeTransferMedataFeignEnhancedPlugin() {
return new EncodeTransferMedataFeignEnhancedPlugin();
}
}

Expand All @@ -123,23 +117,12 @@ public EncodeTransferMedataFeignInterceptor encodeTransferMedataFeignInterceptor
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(name = "org.springframework.web.client.RestTemplate")
@ConditionalOnProperty(value = "spring.cloud.tencent.rpc-enhancement.enabled", havingValue = "true", matchIfMissing = true)
protected static class MetadataTransferRestTemplateConfig {

@Autowired(required = false)
private List<RestTemplate> restTemplates = Collections.emptyList();

@Bean
public EncodeTransferMedataRestTemplateInterceptor encodeTransferMedataRestTemplateInterceptor() {
return new EncodeTransferMedataRestTemplateInterceptor();
}

@Bean
public SmartInitializingSingleton addEncodeTransferMetadataInterceptorForRestTemplate(EncodeTransferMedataRestTemplateInterceptor interceptor) {
return () -> restTemplates.forEach(restTemplate -> {
List<ClientHttpRequestInterceptor> list = new ArrayList<>(restTemplate.getInterceptors());
list.add(interceptor);
restTemplate.setInterceptors(list);
});
public EncodeTransferMedataRestTemplateEnhancedPlugin encodeTransferMedataRestTemplateEnhancedPlugin() {
return new EncodeTransferMedataRestTemplateEnhancedPlugin();
}
}

Expand All @@ -148,20 +131,12 @@ public SmartInitializingSingleton addEncodeTransferMetadataInterceptorForRestTem
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(name = "org.springframework.web.reactive.function.client.WebClient")
@ConditionalOnProperty(value = "spring.cloud.tencent.rpc-enhancement.enabled", havingValue = "true", matchIfMissing = true)
protected static class MetadataTransferWebClientConfig {
@Autowired(required = false)
private List<WebClient.Builder> webClientBuilder = Collections.emptyList();

@Bean
public EncodeTransferMedataWebClientFilter encodeTransferMedataWebClientFilter() {
return new EncodeTransferMedataWebClientFilter();
}

@Bean
public SmartInitializingSingleton addEncodeTransferMetadataFilterForWebClient(EncodeTransferMedataWebClientFilter filter) {
return () -> webClientBuilder.forEach(webClient -> {
webClient.filter(filter);
});
public EncodeTransferMedataWebClientEnhancedPlugin encodeTransferMedataWebClientEnhancedPlugin() {
return new EncodeTransferMedataWebClientEnhancedPlugin();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,28 +18,27 @@

package com.tencent.cloud.metadata.core;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;

import com.tencent.cloud.common.constant.MetadataConstant;
import com.tencent.cloud.common.constant.OrderConstant;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Mono;

import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.util.StringUtils;
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.ContextConstant.UTF_8;
import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_DISPOSABLE_METADATA;
import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_METADATA;

Expand All @@ -51,8 +50,14 @@
*/
public class DecodeTransferMetadataReactiveFilter implements WebFilter, Ordered {

private PolarisContextProperties polarisContextProperties;

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

public DecodeTransferMetadataReactiveFilter(PolarisContextProperties polarisContextProperties) {
this.polarisContextProperties = polarisContextProperties;
}

@Override
public int getOrder() {
return OrderConstant.Server.Reactive.DECODE_TRANSFER_METADATA_FILTER_ORDER;
Expand All @@ -62,19 +67,16 @@ public int getOrder() {
public Mono<Void> filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) {
// Get metadata string from http header.
ServerHttpRequest serverHttpRequest = serverWebExchange.getRequest();

Map<String, String> internalTransitiveMetadata = getIntervalMetadata(serverHttpRequest, CUSTOM_METADATA);
Map<String, String> customTransitiveMetadata = CustomTransitiveMetadataResolver.resolve(serverWebExchange);

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

Map<String, String> internalDisposableMetadata = getIntervalMetadata(serverHttpRequest, CUSTOM_DISPOSABLE_METADATA);
Map<String, String> mergedDisposableMetadata = new HashMap<>(internalDisposableMetadata);

MetadataContextHolder.init(mergedTransitiveMetadata, mergedDisposableMetadata);

ReactiveMetadataProvider metadataProvider = new ReactiveMetadataProvider(serverHttpRequest, polarisContextProperties.getLocalIpAddress());
MetadataContextHolder.init(mergedTransitiveMetadata, mergedDisposableMetadata, metadataProvider);
// Save to ServerWebExchange.
serverWebExchange.getAttributes().put(
MetadataConstant.HeaderName.METADATA_CONTEXT,
Expand All @@ -83,20 +85,14 @@ public Mono<Void> filter(ServerWebExchange serverWebExchange, WebFilterChain web
TransHeadersTransfer.transfer(serverHttpRequest);

return webFilterChain.filter(serverWebExchange)
.doOnError(throwable -> LOG.error("handle metadata[{}] error.",
MetadataContextHolder.get(), throwable))
.doFinally((type) -> MetadataContextHolder.remove());
}

private Map<String, String> getIntervalMetadata(ServerHttpRequest serverHttpRequest, String headerName) {
HttpHeaders httpHeaders = serverHttpRequest.getHeaders();
String customMetadataStr = httpHeaders.getFirst(headerName);
try {
if (StringUtils.hasText(customMetadataStr)) {
customMetadataStr = URLDecoder.decode(customMetadataStr, UTF_8);
}
}
catch (UnsupportedEncodingException e) {
LOG.error("Runtime system does not support utf-8 coding.", e);
}
String customMetadataStr = UrlUtils.decode(httpHeaders.getFirst(headerName));
LOG.debug("Get upstream metadata string: {}", customMetadataStr);

return JacksonUtils.deserialize2Map(customMetadataStr);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
package com.tencent.cloud.metadata.core;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;

Expand All @@ -32,15 +30,16 @@
import com.tencent.cloud.common.constant.OrderConstant;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.core.annotation.Order;
import org.springframework.lang.NonNull;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

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

Expand All @@ -55,6 +54,12 @@ public class DecodeTransferMetadataServletFilter extends OncePerRequestFilter {

private static final Logger LOG = LoggerFactory.getLogger(DecodeTransferMetadataServletFilter.class);

private PolarisContextProperties polarisContextProperties;

public DecodeTransferMetadataServletFilter(PolarisContextProperties polarisContextProperties) {
this.polarisContextProperties = polarisContextProperties;
}

@Override
protected void doFilterInternal(@NonNull HttpServletRequest httpServletRequest,
@NonNull HttpServletResponse httpServletResponse, FilterChain filterChain)
Expand All @@ -65,11 +70,10 @@ protected void doFilterInternal(@NonNull HttpServletRequest httpServletRequest,
Map<String, String> mergedTransitiveMetadata = new HashMap<>();
mergedTransitiveMetadata.putAll(internalTransitiveMetadata);
mergedTransitiveMetadata.putAll(customTransitiveMetadata);

Map<String, String> internalDisposableMetadata = getInternalMetadata(httpServletRequest, CUSTOM_DISPOSABLE_METADATA);
Map<String, String> mergedDisposableMetadata = new HashMap<>(internalDisposableMetadata);

MetadataContextHolder.init(mergedTransitiveMetadata, mergedDisposableMetadata);
ServletMetadataProvider metadataProvider = new ServletMetadataProvider(httpServletRequest, polarisContextProperties.getLocalIpAddress());
MetadataContextHolder.init(mergedTransitiveMetadata, mergedDisposableMetadata, metadataProvider);

TransHeadersTransfer.transfer(httpServletRequest);

Expand All @@ -84,15 +88,7 @@ protected void doFilterInternal(@NonNull HttpServletRequest httpServletRequest,

private Map<String, String> getInternalMetadata(HttpServletRequest httpServletRequest, String headerName) {
// Get custom metadata string from http header.
String customMetadataStr = httpServletRequest.getHeader(headerName);
try {
if (StringUtils.hasText(customMetadataStr)) {
customMetadataStr = URLDecoder.decode(customMetadataStr, UTF_8);
}
}
catch (UnsupportedEncodingException e) {
LOG.error("Runtime system does not support utf-8 coding.", e);
}
String customMetadataStr = UrlUtils.decode(httpServletRequest.getHeader(headerName));
LOG.debug("Get upstream metadata string: {}", customMetadataStr);

// create custom metadata.
Expand Down
Loading

0 comments on commit 3606712

Please sign in to comment.