|
|
|
@ -21,22 +21,25 @@ package com.tencent.cloud.common.metadata;
|
|
|
|
|
import java.util.Collections;
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
|
|
import java.util.Optional;
|
|
|
|
|
import java.util.function.BiConsumer;
|
|
|
|
|
|
|
|
|
|
import com.tencent.cloud.common.constant.MetadataConstant;
|
|
|
|
|
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
|
|
|
|
|
import com.tencent.cloud.common.util.DiscoveryUtil;
|
|
|
|
|
import com.tencent.cloud.common.util.JacksonUtils;
|
|
|
|
|
import com.tencent.polaris.metadata.core.MetadataContainer;
|
|
|
|
|
import com.tencent.polaris.metadata.core.MetadataMapValue;
|
|
|
|
|
import com.tencent.polaris.metadata.core.MetadataObjectValue;
|
|
|
|
|
import com.tencent.polaris.metadata.core.MetadataStringValue;
|
|
|
|
|
import com.tencent.polaris.metadata.core.MetadataType;
|
|
|
|
|
import com.tencent.polaris.metadata.core.MetadataValue;
|
|
|
|
|
import com.tencent.polaris.metadata.core.TransitiveType;
|
|
|
|
|
import org.slf4j.Logger;
|
|
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
|
|
|
|
|
import org.springframework.util.StringUtils;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Metadata Context.
|
|
|
|
|
*
|
|
|
|
|
* @author Haotian Zhang
|
|
|
|
|
*/
|
|
|
|
|
public class MetadataContext {
|
|
|
|
|
public class MetadataContext extends com.tencent.polaris.metadata.core.manager.MetadataContext {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* transitive context.
|
|
|
|
@ -63,6 +66,11 @@ public class MetadataContext {
|
|
|
|
|
*/
|
|
|
|
|
public static final String FRAGMENT_RAW_TRANSHEADERS_KV = "trans-headers-kv";
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* the key of the header(key-value) list needed to be store as loadbalance data.
|
|
|
|
|
*/
|
|
|
|
|
public static final String FRAGMENT_LB_METADATA = "load-balance-metadata";
|
|
|
|
|
|
|
|
|
|
private static final Logger LOG = LoggerFactory.getLogger(MetadataContext.class);
|
|
|
|
|
/**
|
|
|
|
|
* Namespace of local instance.
|
|
|
|
@ -108,22 +116,70 @@ public class MetadataContext {
|
|
|
|
|
LOCAL_SERVICE = serviceName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private final Map<String, Map<String, String>> fragmentContexts;
|
|
|
|
|
public MetadataContext() {
|
|
|
|
|
super(MetadataConstant.POLARIS_TRANSITIVE_HEADER_PREFIX);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private final Map<String, Object> loadbalancerMetadata;
|
|
|
|
|
private Map<String, String> getMetadataAsMap(MetadataType metadataType, TransitiveType transitiveType, boolean downstream) {
|
|
|
|
|
MetadataContainer metadataContainer = getMetadataContainer(metadataType, downstream);
|
|
|
|
|
Map<String, String> values = new HashMap<>();
|
|
|
|
|
metadataContainer.iterateMetadataValues(new BiConsumer<String, MetadataValue>() {
|
|
|
|
|
@Override
|
|
|
|
|
public void accept(String s, MetadataValue metadataValue) {
|
|
|
|
|
if (metadataValue instanceof MetadataStringValue) {
|
|
|
|
|
MetadataStringValue metadataStringValue = (MetadataStringValue) metadataValue;
|
|
|
|
|
if (metadataStringValue.getTransitiveType() == transitiveType) {
|
|
|
|
|
values.put(s, metadataStringValue.getStringValue());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return values;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void putMetadataAsMap(MetadataType metadataType, TransitiveType transitiveType, boolean downstream, Map<String, String> values) {
|
|
|
|
|
MetadataContainer metadataContainer = getMetadataContainer(metadataType, downstream);
|
|
|
|
|
for (Map.Entry<String, String> entry : values.entrySet()) {
|
|
|
|
|
metadataContainer.putMetadataStringValue(entry.getKey(), entry.getValue(), transitiveType);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public MetadataContext() {
|
|
|
|
|
this.fragmentContexts = new ConcurrentHashMap<>();
|
|
|
|
|
this.loadbalancerMetadata = new ConcurrentHashMap<>();
|
|
|
|
|
private Map<String, String> getMapMetadataAsMap(MetadataType metadataType, String mapKey, TransitiveType transitiveType, boolean downstream) {
|
|
|
|
|
MetadataContainer metadataContainer = getMetadataContainer(metadataType, downstream);
|
|
|
|
|
Map<String, String> values = new HashMap<>();
|
|
|
|
|
MetadataValue metadataValue = metadataContainer.getMetadataValue(mapKey);
|
|
|
|
|
if (!(metadataValue instanceof MetadataMapValue)) {
|
|
|
|
|
return values;
|
|
|
|
|
}
|
|
|
|
|
MetadataMapValue metadataMapValue = (MetadataMapValue) metadataValue;
|
|
|
|
|
metadataMapValue.iterateMapValues(new BiConsumer<String, MetadataValue>() {
|
|
|
|
|
@Override
|
|
|
|
|
public void accept(String s, MetadataValue metadataValue) {
|
|
|
|
|
if (metadataValue instanceof MetadataStringValue) {
|
|
|
|
|
MetadataStringValue metadataStringValue = (MetadataStringValue) metadataValue;
|
|
|
|
|
if (metadataStringValue.getTransitiveType() == transitiveType) {
|
|
|
|
|
values.put(s, metadataStringValue.getStringValue());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return values;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void putMapMetadataAsMap(MetadataType metadataType, String mapKey,
|
|
|
|
|
TransitiveType transitiveType, boolean downstream, Map<String, String> values) {
|
|
|
|
|
MetadataContainer metadataContainer = getMetadataContainer(metadataType, downstream);
|
|
|
|
|
for (Map.Entry<String, String> entry : values.entrySet()) {
|
|
|
|
|
metadataContainer.putMetadataMapValue(mapKey, entry.getKey(), entry.getValue(), transitiveType);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Map<String, String> getDisposableMetadata() {
|
|
|
|
|
return this.getFragmentContext(MetadataContext.FRAGMENT_DISPOSABLE);
|
|
|
|
|
return getFragmentContext(FRAGMENT_DISPOSABLE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Map<String, String> getTransitiveMetadata() {
|
|
|
|
|
return this.getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE);
|
|
|
|
|
return getFragmentContext(FRAGMENT_TRANSITIVE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Map<String, String> getCustomMetadata() {
|
|
|
|
@ -140,51 +196,76 @@ public class MetadataContext {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Map<String, String> getTransHeaders() {
|
|
|
|
|
return this.getFragmentContext(MetadataContext.FRAGMENT_RAW_TRANSHEADERS);
|
|
|
|
|
return this.getFragmentContext(FRAGMENT_RAW_TRANSHEADERS);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Map<String, String> getTransHeadersKV() {
|
|
|
|
|
return this.getFragmentContext(MetadataContext.FRAGMENT_RAW_TRANSHEADERS_KV);
|
|
|
|
|
return getFragmentContext(FRAGMENT_RAW_TRANSHEADERS_KV);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Map<String, Object> getLoadbalancerMetadata() {
|
|
|
|
|
return this.loadbalancerMetadata;
|
|
|
|
|
MetadataContainer metadataContainer = getMetadataContainer(MetadataType.APPLICATION, false);
|
|
|
|
|
MetadataValue metadataValue = metadataContainer.getMetadataValue(FRAGMENT_LB_METADATA);
|
|
|
|
|
Map<String, Object> values = new HashMap<>();
|
|
|
|
|
if (metadataValue instanceof MetadataMapValue) {
|
|
|
|
|
MetadataMapValue metadataMapValue = (MetadataMapValue) metadataValue;
|
|
|
|
|
metadataMapValue.iterateMapValues(new BiConsumer<String, MetadataValue>() {
|
|
|
|
|
@Override
|
|
|
|
|
public void accept(String s, MetadataValue metadataValue) {
|
|
|
|
|
if (metadataValue instanceof MetadataObjectValue) {
|
|
|
|
|
Optional<?> objectValue = ((MetadataObjectValue<?>) metadataValue).getObjectValue();
|
|
|
|
|
objectValue.ifPresent(o -> values.put(s, o));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
return values;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void setLoadbalancer(String key, Object value) {
|
|
|
|
|
MetadataContainer metadataContainer = getMetadataContainer(MetadataType.APPLICATION, false);
|
|
|
|
|
metadataContainer.putMetadataMapObjectValue(FRAGMENT_LB_METADATA, key, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void setTransitiveMetadata(Map<String, String> transitiveMetadata) {
|
|
|
|
|
this.putFragmentContext(FRAGMENT_TRANSITIVE, Collections.unmodifiableMap(transitiveMetadata));
|
|
|
|
|
putFragmentContext(FRAGMENT_TRANSITIVE, Collections.unmodifiableMap(transitiveMetadata));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void setDisposableMetadata(Map<String, String> disposableMetadata) {
|
|
|
|
|
this.putFragmentContext(FRAGMENT_DISPOSABLE, Collections.unmodifiableMap(disposableMetadata));
|
|
|
|
|
putFragmentContext(FRAGMENT_DISPOSABLE, Collections.unmodifiableMap(disposableMetadata));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void setUpstreamDisposableMetadata(Map<String, String> upstreamDisposableMetadata) {
|
|
|
|
|
this.putFragmentContext(FRAGMENT_UPSTREAM_DISPOSABLE, Collections.unmodifiableMap(upstreamDisposableMetadata));
|
|
|
|
|
putFragmentContext(FRAGMENT_UPSTREAM_DISPOSABLE, Collections.unmodifiableMap(upstreamDisposableMetadata));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void setTransHeadersKV(String key, String value) {
|
|
|
|
|
this.putContext(FRAGMENT_RAW_TRANSHEADERS_KV, key, value);
|
|
|
|
|
putContext(FRAGMENT_RAW_TRANSHEADERS_KV, key, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void setTransHeaders(String key, String value) {
|
|
|
|
|
this.putContext(FRAGMENT_RAW_TRANSHEADERS, key, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void setLoadbalancer(String key, Object value) {
|
|
|
|
|
this.loadbalancerMetadata.put(key, value);
|
|
|
|
|
putContext(FRAGMENT_RAW_TRANSHEADERS, key, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Map<String, String> getFragmentContext(String fragment) {
|
|
|
|
|
Map<String, String> fragmentContext = fragmentContexts.get(fragment);
|
|
|
|
|
if (fragmentContext == null) {
|
|
|
|
|
return Collections.emptyMap();
|
|
|
|
|
switch (fragment) {
|
|
|
|
|
case FRAGMENT_TRANSITIVE:
|
|
|
|
|
return getMetadataAsMap(MetadataType.CUSTOM, TransitiveType.PASS_THROUGH, false);
|
|
|
|
|
case FRAGMENT_DISPOSABLE:
|
|
|
|
|
return getMetadataAsMap(MetadataType.CUSTOM, TransitiveType.DISPOSABLE, false);
|
|
|
|
|
case FRAGMENT_UPSTREAM_DISPOSABLE:
|
|
|
|
|
return getMetadataAsMap(MetadataType.CUSTOM, TransitiveType.DISPOSABLE, true);
|
|
|
|
|
case FRAGMENT_RAW_TRANSHEADERS:
|
|
|
|
|
return getMapMetadataAsMap(MetadataType.CUSTOM, FRAGMENT_RAW_TRANSHEADERS, TransitiveType.NONE, false);
|
|
|
|
|
case FRAGMENT_RAW_TRANSHEADERS_KV:
|
|
|
|
|
return getMapMetadataAsMap(MetadataType.CUSTOM, FRAGMENT_RAW_TRANSHEADERS_KV, TransitiveType.PASS_THROUGH, false);
|
|
|
|
|
default:
|
|
|
|
|
return getMapMetadataAsMap(MetadataType.CUSTOM, fragment, TransitiveType.NONE, false);
|
|
|
|
|
}
|
|
|
|
|
return Collections.unmodifiableMap(fragmentContext);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public String getContext(String fragment, String key) {
|
|
|
|
|
Map<String, String> fragmentContext = fragmentContexts.get(fragment);
|
|
|
|
|
Map<String, String> fragmentContext = getFragmentContext(fragment);
|
|
|
|
|
if (fragmentContext == null) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
@ -192,22 +273,32 @@ public class MetadataContext {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void putContext(String fragment, String key, String value) {
|
|
|
|
|
Map<String, String> fragmentContext = fragmentContexts.get(fragment);
|
|
|
|
|
if (fragmentContext == null) {
|
|
|
|
|
fragmentContext = new ConcurrentHashMap<>();
|
|
|
|
|
fragmentContexts.put(fragment, fragmentContext);
|
|
|
|
|
}
|
|
|
|
|
fragmentContext.put(key, value);
|
|
|
|
|
Map<String, String> values = new HashMap<>();
|
|
|
|
|
values.put(key, value);
|
|
|
|
|
putFragmentContext(fragment, values);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void putFragmentContext(String fragment, Map<String, String> context) {
|
|
|
|
|
fragmentContexts.put(fragment, context);
|
|
|
|
|
switch (fragment) {
|
|
|
|
|
case FRAGMENT_TRANSITIVE:
|
|
|
|
|
putMetadataAsMap(MetadataType.CUSTOM, TransitiveType.PASS_THROUGH, false, context);
|
|
|
|
|
break;
|
|
|
|
|
case FRAGMENT_DISPOSABLE:
|
|
|
|
|
putMetadataAsMap(MetadataType.CUSTOM, TransitiveType.DISPOSABLE, false, context);
|
|
|
|
|
break;
|
|
|
|
|
case FRAGMENT_UPSTREAM_DISPOSABLE:
|
|
|
|
|
putMetadataAsMap(MetadataType.CUSTOM, TransitiveType.DISPOSABLE, true, context);
|
|
|
|
|
break;
|
|
|
|
|
case FRAGMENT_RAW_TRANSHEADERS:
|
|
|
|
|
putMapMetadataAsMap(MetadataType.CUSTOM, FRAGMENT_RAW_TRANSHEADERS, TransitiveType.NONE, false, context);
|
|
|
|
|
break;
|
|
|
|
|
case FRAGMENT_RAW_TRANSHEADERS_KV:
|
|
|
|
|
putMapMetadataAsMap(MetadataType.CUSTOM, FRAGMENT_RAW_TRANSHEADERS_KV, TransitiveType.PASS_THROUGH, false, context);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
putMapMetadataAsMap(MetadataType.CUSTOM, fragment, TransitiveType.NONE, false, context);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public String toString() {
|
|
|
|
|
return "MetadataContext{" +
|
|
|
|
|
"fragmentContexts=" + JacksonUtils.serialize2Json(fragmentContexts) +
|
|
|
|
|
'}';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|