Rebuild metadata transfer example .

pull/430/head
misselvexu 3 years ago
parent 9a614beb1b
commit c1a89e8b03

@ -64,13 +64,13 @@ public class DecodeTransferMetadataReactiveFilter implements WebFilter, Ordered
ServerHttpRequest serverHttpRequest = serverWebExchange.getRequest();
Map<String, String> internalTransitiveMetadata = getIntervalMetadata(serverHttpRequest, CUSTOM_METADATA);
Map<String, String> internalDisposableMetadata = getIntervalMetadata(serverHttpRequest, CUSTOM_DISPOSABLE_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);

@ -60,13 +60,13 @@ public class DecodeTransferMetadataServletFilter extends OncePerRequestFilter {
@NonNull HttpServletResponse httpServletResponse, FilterChain filterChain)
throws ServletException, IOException {
Map<String, String> internalTransitiveMetadata = getInternalMetadata(httpServletRequest, CUSTOM_METADATA);
Map<String, String> internalDisposableMetadata = getInternalMetadata(httpServletRequest, CUSTOM_DISPOSABLE_METADATA);
Map<String, String> customTransitiveMetadata = CustomTransitiveMetadataResolver.resolve(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);

@ -69,28 +69,28 @@ public class EncodeTransferMedataFeignInterceptor implements RequestInterceptor,
newestCustomMetadata.put(key, value);
}
});
this.doApply(requestTemplate, disposableMetadata, CUSTOM_DISPOSABLE_METADATA);
this.buildMetadataHeader(requestTemplate, disposableMetadata, CUSTOM_DISPOSABLE_METADATA);
// process custom metadata finally
this.doApply(requestTemplate, newestCustomMetadata, CUSTOM_METADATA);
this.buildMetadataHeader(requestTemplate, newestCustomMetadata, CUSTOM_METADATA);
}
/**
* Set metadata into the request header of {@link RestTemplate} .
* Set metadata into the request header for {@link RestTemplate} .
* @param requestTemplate instance of {@link RestTemplate}
* @param metadata metadata map .
* @param headerName target metadata http header name .
*/
private void doApply(RequestTemplate requestTemplate, Map<String, String> metadata, String headerName) {
private void buildMetadataHeader(RequestTemplate requestTemplate, Map<String, String> metadata, String headerName) {
if (!CollectionUtils.isEmpty(metadata)) {
String encodedTransitiveMetadata = JacksonUtils.serialize2Json(metadata);
String encodedMetadata = JacksonUtils.serialize2Json(metadata);
requestTemplate.removeHeader(headerName);
try {
requestTemplate.header(headerName, encode(encodedTransitiveMetadata, UTF_8));
requestTemplate.header(headerName, encode(encodedMetadata, UTF_8));
}
catch (UnsupportedEncodingException e) {
LOG.error("Set header failed.", e);
requestTemplate.header(headerName, encodedTransitiveMetadata);
requestTemplate.header(headerName, encodedMetadata);
}
}
}

@ -21,6 +21,7 @@ package com.tencent.cloud.metadata.core;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import com.tencent.cloud.common.constant.MetadataConstant;
@ -37,6 +38,8 @@ import org.springframework.lang.NonNull;
import org.springframework.util.CollectionUtils;
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;
/**
* Interceptor used for adding the metadata in http headers from context when web client
@ -57,19 +60,39 @@ public class EncodeTransferMedataRestTemplateInterceptor implements ClientHttpRe
// get metadata of current thread
MetadataContext metadataContext = MetadataContextHolder.get();
Map<String, String> customMetadata = metadataContext.getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE);
Map<String, String> disposableMetadata = metadataContext.getFragmentContext(MetadataContext.FRAGMENT_DISPOSABLE);
if (!CollectionUtils.isEmpty(customMetadata)) {
String encodedTransitiveMetadata = JacksonUtils.serialize2Json(customMetadata);
// build custom metadata request header
this.buildMetadataHeader(httpRequest, customMetadata, CUSTOM_METADATA);
// Clean up one-time metadata coming from upstream .
Map<String, String> newestCustomMetadata = new HashMap<>();
customMetadata.forEach((key, value) -> {
if (!disposableMetadata.containsKey(key)) {
newestCustomMetadata.put(key, value);
}
});
// build custom disposable metadata request header
this.buildMetadataHeader(httpRequest, newestCustomMetadata, CUSTOM_DISPOSABLE_METADATA);
return clientHttpRequestExecution.execute(httpRequest, bytes);
}
/**
* Set metadata into the request header for {@link HttpRequest} .
* @param request instance of {@link HttpRequest}
* @param metadata metadata map .
* @param headerName target metadata http header name .
*/
private void buildMetadataHeader(HttpRequest request, Map<String, String> metadata, String headerName) {
if (!CollectionUtils.isEmpty(metadata)) {
String encodedMetadata = JacksonUtils.serialize2Json(metadata);
try {
httpRequest.getHeaders().set(MetadataConstant.HeaderName.CUSTOM_METADATA,
URLEncoder.encode(encodedTransitiveMetadata, UTF_8));
request.getHeaders().set(headerName, URLEncoder.encode(encodedMetadata, UTF_8));
}
catch (UnsupportedEncodingException e) {
httpRequest.getHeaders().set(MetadataConstant.HeaderName.CUSTOM_METADATA,
encodedTransitiveMetadata);
request.getHeaders().set(headerName, encodedMetadata);
}
}
return clientHttpRequestExecution.execute(httpRequest, bytes);
}
}

@ -20,6 +20,7 @@ package com.tencent.cloud.metadata.core;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import com.tencent.cloud.common.constant.MetadataConstant;
@ -36,6 +37,8 @@ import org.springframework.util.CollectionUtils;
import org.springframework.web.server.ServerWebExchange;
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;
import static org.springframework.cloud.gateway.filter.LoadBalancerClientFilter.LOAD_BALANCER_CLIENT_FILTER_ORDER;
/**
@ -64,17 +67,37 @@ public class EncodeTransferMedataScgFilter implements GlobalFilter, Ordered {
}
Map<String, String> customMetadata = metadataContext.getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE);
if (!CollectionUtils.isEmpty(customMetadata)) {
String metadataStr = JacksonUtils.serialize2Json(customMetadata);
this.buildMetadataHeader(builder, customMetadata, CUSTOM_METADATA);
Map<String, String> disposableMetadata = metadataContext.getFragmentContext(MetadataContext.FRAGMENT_DISPOSABLE);
// Clean up one-time metadata coming from upstream .
Map<String, String> newestCustomMetadata = new HashMap<>();
customMetadata.forEach((key, value) -> {
if (!disposableMetadata.containsKey(key)) {
newestCustomMetadata.put(key, value);
}
});
this.buildMetadataHeader(builder, newestCustomMetadata, CUSTOM_DISPOSABLE_METADATA);
return chain.filter(exchange.mutate().request(builder.build()).build());
}
/**
* Set metadata into the request header for {@link ServerHttpRequest.Builder} .
* @param builder instance of {@link ServerHttpRequest.Builder}
* @param metadata metadata map .
* @param headerName target metadata http header name .
*/
private void buildMetadataHeader(ServerHttpRequest.Builder builder, Map<String, String> metadata, String headerName) {
if (!CollectionUtils.isEmpty(metadata)) {
String encodedMetadata = JacksonUtils.serialize2Json(metadata);
try {
builder.header(MetadataConstant.HeaderName.CUSTOM_METADATA,
URLEncoder.encode(metadataStr, UTF_8));
builder.header(headerName, URLEncoder.encode(encodedMetadata, UTF_8));
}
catch (UnsupportedEncodingException e) {
builder.header(MetadataConstant.HeaderName.CUSTOM_METADATA, metadataStr);
builder.header(headerName, encodedMetadata);
}
}
return chain.filter(exchange.mutate().request(builder.build()).build());
}
}

@ -20,11 +20,11 @@ package com.tencent.cloud.metadata.core;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.tencent.cloud.common.constant.MetadataConstant;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.util.JacksonUtils;
@ -32,6 +32,8 @@ import com.tencent.cloud.common.util.JacksonUtils;
import org.springframework.util.CollectionUtils;
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;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.RIBBON_ROUTING_FILTER_ORDER;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.ROUTE_TYPE;
@ -67,16 +69,38 @@ public class EncodeTransferMetadataZuulFilter extends ZuulFilter {
// add new metadata and cover old
Map<String, String> customMetadata = metadataContext.getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE);
if (!CollectionUtils.isEmpty(customMetadata)) {
String metadataStr = JacksonUtils.serialize2Json(customMetadata);
this.buildMetadataHeader(requestContext, customMetadata, CUSTOM_METADATA);
Map<String, String> disposableMetadata = metadataContext.getFragmentContext(MetadataContext.FRAGMENT_DISPOSABLE);
// Clean up one-time metadata coming from upstream .
Map<String, String> newestCustomMetadata = new HashMap<>();
customMetadata.forEach((key, value) -> {
if (!disposableMetadata.containsKey(key)) {
newestCustomMetadata.put(key, value);
}
});
this.buildMetadataHeader(requestContext, newestCustomMetadata, CUSTOM_DISPOSABLE_METADATA);
return null;
}
/**
* Set metadata into the request header for {@link RequestContext} .
*
* @param context instance of {@link RequestContext}
* @param metadata metadata map .
* @param headerName target metadata http header name .
*/
private void buildMetadataHeader(RequestContext context, Map<String, String> metadata, String headerName) {
if (!CollectionUtils.isEmpty(metadata)) {
String encodedMetadata = JacksonUtils.serialize2Json(metadata);
try {
requestContext.addZuulRequestHeader(MetadataConstant.HeaderName.CUSTOM_METADATA,
URLEncoder.encode(metadataStr, UTF_8));
context.addZuulRequestHeader(headerName, URLEncoder.encode(encodedMetadata, UTF_8));
}
catch (UnsupportedEncodingException e) {
requestContext.addZuulRequestHeader(MetadataConstant.HeaderName.CUSTOM_METADATA, metadataStr);
context.addZuulRequestHeader(headerName, encodedMetadata);
}
}
return null;
}
}

@ -46,6 +46,11 @@ public class MetadataContext {
*/
public static final String FRAGMENT_DISPOSABLE = "disposable";
/**
* upstream disposable Context.
*/
public static final String FRAGMENT_UPSTREAM_DISPOSABLE = "upstream-disposable";
private static final Logger LOG = LoggerFactory.getLogger(MetadataContext.class);
/**
* Namespace of local instance.

@ -29,6 +29,7 @@ import org.springframework.util.CollectionUtils;
import static com.tencent.cloud.common.metadata.MetadataContext.FRAGMENT_DISPOSABLE;
import static com.tencent.cloud.common.metadata.MetadataContext.FRAGMENT_TRANSITIVE;
import static com.tencent.cloud.common.metadata.MetadataContext.FRAGMENT_UPSTREAM_DISPOSABLE;
/**
* Metadata Context Holder.
@ -96,22 +97,17 @@ public final class MetadataContextHolder {
Map<String, String> mergedTransitiveMetadata = new HashMap<>();
mergedTransitiveMetadata.putAll(staticTransitiveMetadata);
mergedTransitiveMetadata.putAll(dynamicTransitiveMetadata);
metadataContext.putFragmentContext(FRAGMENT_TRANSITIVE, Collections.unmodifiableMap(mergedTransitiveMetadata));
Map<String, String> mergedDisposableMetadata = new HashMap<>(dynamicDisposableMetadata);
metadataContext.putFragmentContext(FRAGMENT_UPSTREAM_DISPOSABLE, Collections.unmodifiableMap(mergedDisposableMetadata));
metadataContext.putFragmentContext(FRAGMENT_TRANSITIVE, Collections.unmodifiableMap(mergedTransitiveMetadata));
metadataContext.putFragmentContext(FRAGMENT_DISPOSABLE, Collections.unmodifiableMap(mergedDisposableMetadata));
Map<String, String> staticDisposableMetadata = metadataContext.getFragmentContext(FRAGMENT_DISPOSABLE);
metadataContext.putFragmentContext(FRAGMENT_DISPOSABLE, Collections.unmodifiableMap(staticDisposableMetadata));
}
MetadataContextHolder.set(metadataContext);
}
/**
* Clean up one-time metadata coming from upstream .
*/
public static void cleanDisposableMetadata() {
}
/**
* Remove metadata context.
*/

@ -10,8 +10,8 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>metadata-caller-service</artifactId>
<name>Spring Cloud Tencent Metadata Transfer Caller Service</name>
<artifactId>metadata-backend</artifactId>
<name>Spring Cloud Tencent Metadata Transfer Backend Service</name>
<dependencies>
<dependency>

@ -35,10 +35,10 @@ import org.springframework.web.bind.annotation.RestController;
* @author Palmer Xu
*/
@RestController
@RequestMapping("/metadata/service/callee2")
public class MetadataCalleeController {
@RequestMapping("/metadata/service/backend")
public class MetadataBackendController {
private static final Logger LOG = LoggerFactory.getLogger(MetadataCalleeController.class);
private static final Logger LOG = LoggerFactory.getLogger(MetadataBackendController.class);
@Value("${server.port:0}")
private int port;
@ -61,5 +61,4 @@ public class MetadataCalleeController {
return customMetadataMap;
}
}

@ -26,10 +26,9 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
* @author Palmer Xu
*/
@SpringBootApplication
public class MetadataCalleeService2 {
public class MetadataBackendService {
public static void main(String[] args) {
SpringApplication.run(MetadataCalleeService2.class, args);
SpringApplication.run(MetadataBackendService.class, args);
}
}

@ -2,7 +2,7 @@ server:
port: 48088
spring:
application:
name: MetadataCalleeService2
name: MetadataBackendService
cloud:
polaris:
address: grpc://183.47.111.80:8091

@ -10,8 +10,8 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>metadata-callee-service2</artifactId>
<name>Spring Cloud Tencent Metadata Transfer Callee Service 2</name>
<artifactId>metadata-frontend</artifactId>
<name>Spring Cloud Tencent Metadata Transfer Frontent Service</name>
<dependencies>
<dependency>

@ -35,20 +35,20 @@ import org.springframework.web.client.RestTemplate;
* @author Palmer Xu
*/
@RestController
@RequestMapping("/metadata/service/caller")
public class MetadataCallerController {
@RequestMapping("/metadata/service/frontend")
public class MetadataFrontendController {
private final RestTemplate restTemplate;
private final MetadataCalleeService metadataCalleeService;
private final MetadataMiddleService metadataMiddleService;
private final MetadataLocalProperties metadataLocalProperties;
public MetadataCallerController(RestTemplate restTemplate,
MetadataCalleeService metadataCalleeService,
public MetadataFrontendController(RestTemplate restTemplate,
MetadataMiddleService metadataMiddleService,
MetadataLocalProperties metadataLocalProperties) {
this.restTemplate = restTemplate;
this.metadataCalleeService = metadataCalleeService;
this.metadataMiddleService = metadataMiddleService;
this.metadataLocalProperties = metadataLocalProperties;
}
@ -61,7 +61,7 @@ public class MetadataCallerController {
Map<String, Map<String, String>> ret = Maps.newHashMap();
// Call remote service with feign client
Map<String, String> calleeMetadata = metadataCalleeService.info();
Map<String, String> calleeMetadata = metadataMiddleService.info();
ret.put("callee-transitive-metadata", calleeMetadata);
// Get Custom Metadata From Context
@ -105,5 +105,4 @@ public class MetadataCallerController {
public String healthCheck() {
return "pk ok";
}
}

@ -31,10 +31,10 @@ import org.springframework.web.client.RestTemplate;
*/
@SpringBootApplication
@EnableFeignClients
public class MetadataCallerService {
public class MetadataFrontendService {
public static void main(String[] args) {
SpringApplication.run(MetadataCallerService.class, args);
SpringApplication.run(MetadataFrontendService.class, args);
}
@Bean
@ -42,5 +42,4 @@ public class MetadataCallerService {
public RestTemplate restTemplate() {
return new RestTemplate();
}
}

@ -27,15 +27,14 @@ import org.springframework.web.bind.annotation.GetMapping;
*
* @author Palmer Xu
*/
@FeignClient(value = "MetadataCalleeService",
fallback = MetadataCalleeServiceFallback.class)
public interface MetadataCalleeService {
@FeignClient(value = "MetadataMiddleService",
fallback = MetadataMiddleServiceFallback.class)
public interface MetadataMiddleService {
/**
* Get information of callee.
* @return information of callee
*/
@GetMapping("/metadata/service/callee/info")
@GetMapping("/metadata/service/middle/info")
Map<String, String> info();
}

@ -29,11 +29,10 @@ import org.springframework.stereotype.Component;
* @author Palmer Xu
*/
@Component
public class MetadataCalleeServiceFallback implements MetadataCalleeService {
public class MetadataMiddleServiceFallback implements MetadataMiddleService {
@Override
public Map<String, String> info() {
return Maps.newHashMap();
}
}

@ -2,7 +2,7 @@ server:
port: 48080
spring:
application:
name: MetadataCallerService
name: MetadataFrontendService
cloud:
polaris:
address: grpc://183.47.111.80:8091
@ -12,7 +12,7 @@ spring:
enabled: true
register: true
heartbeat-enabled: true
health-check-url: /metadata/service/caller/healthCheck
health-check-url: /metadata/service/frontend/healthCheck
tencent:
metadata:
# Defined your metadata keys & values

@ -10,8 +10,8 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>metadata-callee-service</artifactId>
<name>Spring Cloud Tencent Metadata Transfer Callee Service</name>
<artifactId>metadata-middle</artifactId>
<name>Spring Cloud Tencent Metadata Transfer Middle Service</name>
<dependencies>
<dependency>

@ -27,15 +27,15 @@ import org.springframework.web.bind.annotation.GetMapping;
*
* @author Palmer Xu
*/
@FeignClient(value = "MetadataCalleeService2",
fallback = MetadataCalleeService2Fallback.class)
public interface MetadataCalleeService2 {
@FeignClient(value = "MetadataBackendService2",
fallback = MetadataBackendServiceFallback.class)
public interface MetadataBackendService {
/**
* Get information of callee.
* @return information of callee
*/
@GetMapping("/metadata/service/callee2/info")
@GetMapping("/metadata/service/backend/info")
Map<String, String> info();
}

@ -29,11 +29,10 @@ import org.springframework.stereotype.Component;
* @author Palmer Xu
*/
@Component
public class MetadataCalleeService2Fallback implements MetadataCalleeService2 {
public class MetadataBackendServiceFallback implements MetadataBackendService {
@Override
public Map<String, String> info() {
return Maps.newHashMap();
}
}

@ -44,12 +44,12 @@ public class MetadataCalleeController {
@Value("${server.port:0}")
private int port;
private final MetadataCalleeService2 metadataCalleeService2;
private final MetadataBackendService metadataBackendService;
private final RestTemplate restTemplate;
public MetadataCalleeController(MetadataCalleeService2 metadataCalleeService2, RestTemplate restTemplate) {
this.metadataCalleeService2 = metadataCalleeService2;
public MetadataCalleeController(MetadataBackendService metadataBackendService, RestTemplate restTemplate) {
this.metadataBackendService = metadataBackendService;
this.restTemplate = restTemplate;
}
@ -70,7 +70,7 @@ public class MetadataCalleeController {
});
// Call remote service with Feign
Map<String, String> calleeMetadata2 = metadataCalleeService2.info();
Map<String, String> calleeMetadata2 = metadataBackendService.info();
calleeMetadata2.forEach((key, value) -> {
LOG.info("Feign Callee2 Metadata (Key-Value): {} : {}", key, value);
});

@ -31,10 +31,10 @@ import org.springframework.web.client.RestTemplate;
*/
@SpringBootApplication
@EnableFeignClients
public class MetadataCalleeService {
public class MetadataMiddleService {
public static void main(String[] args) {
SpringApplication.run(MetadataCalleeService.class, args);
SpringApplication.run(MetadataMiddleService.class, args);
}
@Bean

@ -2,7 +2,7 @@ server:
port: 48084
spring:
application:
name: MetadataCalleeService
name: MetadataMiddleService
cloud:
polaris:
address: grpc://183.47.111.80:8091

@ -15,9 +15,9 @@
<name>Spring Cloud Starter Tencent Metadata Transfer Example</name>
<modules>
<module>metadata-callee-service</module>
<module>metadata-callee-service2</module>
<module>metadata-caller-service</module>
<module>metadata-frontend</module>
<module>metadata-middle</module>
<module>metadata-backend</module>
</modules>
<dependencies>

Loading…
Cancel
Save