Completed metadata transfer example .

pull/430/head
misselvexu 3 years ago
parent c1a89e8b03
commit 1ac73b2a85

@ -21,6 +21,7 @@ package com.tencent.cloud.common.metadata;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import com.tencent.cloud.common.metadata.config.MetadataLocalProperties; import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils; import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
@ -74,6 +75,39 @@ public final class MetadataContextHolder {
return METADATA_CONTEXT.get(); return METADATA_CONTEXT.get();
} }
/**
* Get disposable metadata value from thread local .
* @param key metadata key .
* @param upstream upstream disposable , otherwise will return local static disposable metadata .
* @return target disposable metadata value .
*/
public static Optional<String> getDisposableMetadata(String key, boolean upstream) {
MetadataContext context = get();
if (upstream) {
return Optional.ofNullable(context.getContext(FRAGMENT_UPSTREAM_DISPOSABLE, key));
}
else {
return Optional.ofNullable(context.getContext(FRAGMENT_DISPOSABLE, key));
}
}
/**
* Get all disposable metadata value from thread local .
* @param upstream upstream disposable , otherwise will return local static disposable metadata .
* @return target disposable metadata value .
*/
public static Map<String, String> getAllDisposableMetadata(boolean upstream) {
Map<String, String> disposables = new HashMap<>();
MetadataContext context = get();
if (upstream) {
disposables.putAll(context.getFragmentContext(FRAGMENT_UPSTREAM_DISPOSABLE));
}
else {
disposables.putAll(context.getFragmentContext(FRAGMENT_DISPOSABLE));
}
return Collections.unmodifiableMap(disposables);
}
/** /**
* Set metadata context. * Set metadata context.
* @param metadataContext metadata context * @param metadataContext metadata context
@ -85,6 +119,7 @@ public final class MetadataContextHolder {
/** /**
* Save metadata map to thread local. * Save metadata map to thread local.
* @param dynamicTransitiveMetadata custom metadata collection * @param dynamicTransitiveMetadata custom metadata collection
* @param dynamicDisposableMetadata custom disposable metadata connection
*/ */
public static void init(Map<String, String> dynamicTransitiveMetadata, Map<String, String> dynamicDisposableMetadata) { public static void init(Map<String, String> dynamicTransitiveMetadata, Map<String, String> dynamicDisposableMetadata) {
// Init ThreadLocal. // Init ThreadLocal.

@ -22,6 +22,7 @@ import java.util.Map;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -42,7 +43,6 @@ public final class JacksonUtils {
private static final Logger LOG = LoggerFactory.getLogger(JacksonUtils.class); private static final Logger LOG = LoggerFactory.getLogger(JacksonUtils.class);
private JacksonUtils() { private JacksonUtils() {
} }
/** /**
@ -52,8 +52,25 @@ public final class JacksonUtils {
* @return Json String * @return Json String
*/ */
public static <T> String serialize2Json(T object) { public static <T> String serialize2Json(T object) {
return serialize2Json(object, false);
}
/**
* Object to Json.
* @param object object to be serialized
* @param pretty pretty print
* @param <T> type of object
* @return Json String
*/
public static <T> String serialize2Json(T object, boolean pretty) {
try { try {
return OM.writeValueAsString(object); if (pretty) {
ObjectWriter objectWriter = OM.writerWithDefaultPrettyPrinter();
return objectWriter.writeValueAsString(object);
}
else {
return OM.writeValueAsString(object);
}
} }
catch (JsonProcessingException e) { catch (JsonProcessingException e) {
LOG.error("Object to Json failed. {}", object, e); LOG.error("Object to Json failed. {}", object, e);

@ -15,9 +15,11 @@
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*/ */
package com.tencent.cloud.metadata.service.callee; package com.tencent.cloud.metadata.service.backend;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder; import com.tencent.cloud.common.metadata.MetadataContextHolder;
@ -48,17 +50,40 @@ public class MetadataBackendController {
* @return information of callee * @return information of callee
*/ */
@GetMapping("/info") @GetMapping("/info")
public Map<String, String> info() { public Map<String, Map<String, String>> info() {
LOG.info("Metadata Service Callee-2 [{}] is called.", port); LOG.info("Metadata Backend Service [{}] is called.", port);
Map<String, Map<String, String>> ret = new HashMap<>();
// Get Custom Metadata From Context // Get Custom Metadata From Context
MetadataContext context = MetadataContextHolder.get(); MetadataContext context = MetadataContextHolder.get();
Map<String, String> customMetadataMap = context.getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE); Map<String, String> customMetadataMap = context.getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE);
customMetadataMap.forEach((key, value) -> { customMetadataMap.forEach((key, value) -> {
LOG.info("Custom Metadata (Key-Value): {} : {}", key, value); LOG.info("Metadata Backend Custom Metadata (Key-Value): {} : {}", key, value);
}); });
return customMetadataMap; ret.put("transitive-metadata", customMetadataMap);
// Get Disposable metadata from upstream service
Optional<String> upstreamDisposableMetadata = MetadataContextHolder.getDisposableMetadata("", true);
LOG.info("Upstream Disposable Metadata (Key-Value) : {}, {}", "", upstreamDisposableMetadata.get());
// Get All Disposable metadata from upstream service
Map<String, String> upstreamDisposableMetadatas = MetadataContextHolder.getAllDisposableMetadata(true);
upstreamDisposableMetadatas.forEach((key, value) -> {
LOG.info("Backend All Upstream Custom Disposable Metadata (Key-Value): {} : {}", key, value);
});
ret.put("upstream-disposable-metadata", upstreamDisposableMetadatas);
// Get All Disposable metadata from upstream service
Map<String, String> localDisposableMetadatas = MetadataContextHolder.getAllDisposableMetadata(false);
localDisposableMetadatas.forEach((key, value) -> {
LOG.info("Backend All Upstream Custom Disposable Metadata (Key-Value): {} : {}", key, value);
});
ret.put("local-disposable-metadata", localDisposableMetadatas);
return ret;
} }
} }

@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*/ */
package com.tencent.cloud.metadata.service.callee; package com.tencent.cloud.metadata.service.backend;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;

@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*/ */
package com.tencent.cloud.metadata.service.caller; package com.tencent.cloud.metadata.service.frontend;
import java.util.Map; import java.util.Map;

@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*/ */
package com.tencent.cloud.metadata.service.caller; package com.tencent.cloud.metadata.service.frontend;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;

@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*/ */
package com.tencent.cloud.metadata.service.caller; package com.tencent.cloud.metadata.service.frontend;
import java.util.Map; import java.util.Map;

@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*/ */
package com.tencent.cloud.metadata.service.caller; package com.tencent.cloud.metadata.service.frontend;
import java.util.Map; import java.util.Map;

@ -1,89 +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.metadata.service.callee;
import java.util.Map;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
/**
* Metadata callee controller.
*
* @author Palmer Xu
*/
@RestController
@RequestMapping("/metadata/service/callee")
public class MetadataCalleeController {
private static final Logger LOG = LoggerFactory.getLogger(MetadataCalleeController.class);
@Value("${server.port:0}")
private int port;
private final MetadataBackendService metadataBackendService;
private final RestTemplate restTemplate;
public MetadataCalleeController(MetadataBackendService metadataBackendService, RestTemplate restTemplate) {
this.metadataBackendService = metadataBackendService;
this.restTemplate = restTemplate;
}
/**
* Get information of callee.
* @return information of callee
*/
@GetMapping("/info")
public Map<String, String> info() {
LOG.info("Metadata Service Callee [{}] is called.", port);
// Call remote service with RestTemplate
Map<String, String> calleeMetadata = restTemplate.getForObject(
"http://MetadataCalleeService2/metadata/service/callee2/info",
Map.class);
calleeMetadata.forEach((key, value) -> {
LOG.info("RestTemplate Callee2 Metadata (Key-Value): {} : {}", key, value);
});
// Call remote service with Feign
Map<String, String> calleeMetadata2 = metadataBackendService.info();
calleeMetadata2.forEach((key, value) -> {
LOG.info("Feign Callee2 Metadata (Key-Value): {} : {}", key, value);
});
// Get Custom Metadata From Context
MetadataContext context = MetadataContextHolder.get();
Map<String, String> customMetadataMap = context.getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE);
customMetadataMap.forEach((key, value) -> {
LOG.info("Custom Metadata (Key-Value): {} : {}", key, value);
});
return customMetadataMap;
}
}

@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*/ */
package com.tencent.cloud.metadata.service.callee; package com.tencent.cloud.metadata.service.middle;
import java.util.Map; import java.util.Map;
@ -27,7 +27,7 @@ import org.springframework.web.bind.annotation.GetMapping;
* *
* @author Palmer Xu * @author Palmer Xu
*/ */
@FeignClient(value = "MetadataBackendService2", @FeignClient(value = "MetadataBackendService",
fallback = MetadataBackendServiceFallback.class) fallback = MetadataBackendServiceFallback.class)
public interface MetadataBackendService { public interface MetadataBackendService {
@ -36,6 +36,5 @@ public interface MetadataBackendService {
* @return information of callee * @return information of callee
*/ */
@GetMapping("/metadata/service/backend/info") @GetMapping("/metadata/service/backend/info")
Map<String, String> info(); Map<String, Map<String, String>> info();
} }

@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*/ */
package com.tencent.cloud.metadata.service.callee; package com.tencent.cloud.metadata.service.middle;
import java.util.Map; import java.util.Map;
@ -32,7 +32,7 @@ import org.springframework.stereotype.Component;
public class MetadataBackendServiceFallback implements MetadataBackendService { public class MetadataBackendServiceFallback implements MetadataBackendService {
@Override @Override
public Map<String, String> info() { public Map<String, Map<String, String>> info() {
return Maps.newHashMap(); return Maps.newHashMap();
} }
} }

@ -0,0 +1,123 @@
/*
* 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.service.middle;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import static com.tencent.cloud.common.util.JacksonUtils.serialize2Json;
/**
* Metadata callee controller.
*
* @author Palmer Xu
*/
@RestController
@RequestMapping("/metadata/service/middle")
public class MetadataMiddleController {
private static final Logger LOG = LoggerFactory.getLogger(MetadataMiddleController.class);
@Value("${server.port:0}")
private int port;
private final MetadataBackendService metadataBackendService;
private final RestTemplate restTemplate;
public MetadataMiddleController(MetadataBackendService metadataBackendService, RestTemplate restTemplate) {
this.metadataBackendService = metadataBackendService;
this.restTemplate = restTemplate;
}
/**
* Get information of callee.
* @return information of callee
*/
@GetMapping("/info")
public Map<String, Map<String, String>> info() {
LOG.info("Metadata Middle Service [{}] is called.", port);
// Call remote service with RestTemplate
Map<String, Map<String, String>> backendResult = restTemplate.getForObject(
"http://MetadataBackendService/metadata/service/backend/info", Map.class);
if (backendResult != null) {
LOG.info("RestTemplate Backend Metadata");
serialize2Json(backendResult, true);
backendResult.clear();
}
// Call remote service with Feign
backendResult = metadataBackendService.info();
if (backendResult != null) {
LOG.info("Feign Backend Metadata");
serialize2Json(backendResult, true);
backendResult.clear();
}
// Build result
Map<String, Map<String, String>> ret = new HashMap<>();
// Get Custom Metadata From Context
MetadataContext context = MetadataContextHolder.get();
Map<String, String> customMetadataMap = context.getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE);
customMetadataMap.forEach((key, value) -> {
LOG.info("Metadata Backend Custom Metadata (Key-Value): {} : {}", key, value);
});
ret.put("transitive-metadata", customMetadataMap);
// Get Disposable metadata from upstream service
Optional<String> upstreamDisposableMetadata = MetadataContextHolder.getDisposableMetadata("", true);
LOG.info("Upstream Disposable Metadata (Key-Value) : {}, {}", "", upstreamDisposableMetadata.get());
// Get All Disposable metadata from upstream service
Map<String, String> upstreamDisposableMetadatas = MetadataContextHolder.getAllDisposableMetadata(true);
upstreamDisposableMetadatas.forEach((key, value) -> {
LOG.info("Backend All Upstream Custom Disposable Metadata (Key-Value): {} : {}", key, value);
});
ret.put("upstream-disposable-metadata", upstreamDisposableMetadatas);
// Get All Disposable metadata from upstream service
Map<String, String> localDisposableMetadatas = MetadataContextHolder.getAllDisposableMetadata(false);
localDisposableMetadatas.forEach((key, value) -> {
LOG.info("Backend All Upstream Custom Disposable Metadata (Key-Value): {} : {}", key, value);
});
ret.put("local-disposable-metadata", localDisposableMetadatas);
return ret;
}
}

@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*/ */
package com.tencent.cloud.metadata.service.callee; package com.tencent.cloud.metadata.service.middle;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
Loading…
Cancel
Save