feat: support tsf unit. (#1681)
* 适配 TSF 单云单元化 --------- Co-authored-by: shedfreewu <shedfreewu@tencent.com>2024
parent
dd17356c3f
commit
7936f0e1fa
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.util;
|
||||
|
||||
import com.tencent.polaris.api.utils.ClassUtils;
|
||||
|
||||
public final class EnvironmentUtils {
|
||||
|
||||
private final static boolean IS_GATEWAY = ClassUtils.isClassPresent("org.springframework.cloud.gateway.filter.GlobalFilter");
|
||||
|
||||
private EnvironmentUtils() {
|
||||
}
|
||||
|
||||
public static boolean isGateway() {
|
||||
return IS_GATEWAY;
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>spring-cloud-tencent-plugin-starters</artifactId>
|
||||
<groupId>com.tencent.cloud</groupId>
|
||||
<version>${revision}</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>spring-cloud-tencent-unit-plugin</artifactId>
|
||||
<name>Spring Cloud Tencent Unit Plugin</name>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.tencent.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-tencent-polaris-discovery</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-actuator-autoconfigure</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.dataformat</groupId>
|
||||
<artifactId>jackson-dataformat-yaml</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.plugin.unit.config;
|
||||
|
||||
import com.tencent.cloud.common.tsf.ConditionalOnOnlyTsfConsulEnabled;
|
||||
import com.tencent.tsf.unit.core.GatewayUnitArchCallback;
|
||||
import com.tencent.tsf.unit.core.TencentUnitManager;
|
||||
import com.tencent.tsf.unit.core.TsfZoneFilterUnitCallback;
|
||||
import com.tencent.tsf.unit.core.remote.TsfUnitConsulManager;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
|
||||
@Configuration
|
||||
public class GatewayUnitAutoConfiguration {
|
||||
|
||||
/**
|
||||
* 网关时执行.
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnOnlyTsfConsulEnabled
|
||||
@ConditionalOnClass(name = "org.springframework.cloud.gateway.filter.GlobalFilter")
|
||||
static class GatewayUnitEnable {
|
||||
|
||||
@Value("${spring.application.name:}")
|
||||
private String applicationName;
|
||||
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
TencentUnitManager.addArchCallback(new GatewayUnitArchCallback(applicationName));
|
||||
TencentUnitManager.addRuleCallback(new TsfZoneFilterUnitCallback());
|
||||
TsfUnitConsulManager.init();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.plugin.unit.config;
|
||||
|
||||
import com.tencent.cloud.plugin.unit.discovery.UnitFeignEagerLoadSmartLifecycle;
|
||||
import com.tencent.cloud.plugin.unit.discovery.UnitPolarisDiscoveryClient;
|
||||
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryClient;
|
||||
import com.tencent.cloud.polaris.eager.instrument.feign.FeignEagerLoadSmartLifecycle;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
|
||||
public class UnitBeanPostProcessor implements BeanPostProcessor {
|
||||
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
if (bean instanceof PolarisDiscoveryClient discoveryClient) {
|
||||
return new UnitPolarisDiscoveryClient(discoveryClient);
|
||||
}
|
||||
|
||||
if (bean instanceof FeignEagerLoadSmartLifecycle) {
|
||||
return new UnitFeignEagerLoadSmartLifecycle();
|
||||
}
|
||||
|
||||
return bean;
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.plugin.unit.discovery;
|
||||
|
||||
import com.tencent.cloud.polaris.eager.instrument.feign.FeignEagerLoadSmartLifecycle;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class UnitFeignEagerLoadSmartLifecycle extends FeignEagerLoadSmartLifecycle {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(UnitFeignEagerLoadSmartLifecycle.class);
|
||||
|
||||
|
||||
public UnitFeignEagerLoadSmartLifecycle() {
|
||||
super(null, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
LOG.info("ignore feign eager load in unit mode");
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.plugin.unit.discovery;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
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.polaris.discovery.PolarisDiscoveryClient;
|
||||
import com.tencent.tsf.unit.core.TencentUnitContext;
|
||||
import com.tencent.tsf.unit.core.TencentUnitManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
|
||||
/**
|
||||
* Support unit discovery.
|
||||
* TODO: support reactive discovery.
|
||||
*/
|
||||
public class UnitPolarisDiscoveryClient extends PolarisDiscoveryClient {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(UnitPolarisDiscoveryClient.class);
|
||||
|
||||
private final PolarisDiscoveryClient delegate;
|
||||
|
||||
public UnitPolarisDiscoveryClient(PolarisDiscoveryClient delegate) {
|
||||
super(null);
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return delegate.description();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ServiceInstance> getInstances(String service) {
|
||||
if (TencentUnitManager.isEnable()) {
|
||||
// if service is not in the format of namespace/service, we will use the namespace in unit context
|
||||
String[] parts = service.split("/");
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("[getInstance] service:{}, unit context:{}", service, TencentUnitContext.getOriginCompositeContextMap());
|
||||
}
|
||||
|
||||
if (parts.length != 2) {
|
||||
String namespace = TencentUnitContext.getStringRouteTag(TencentUnitContext.CLOUD_SPACE_ROUTE_TARGET_NAMESPACE_ID);
|
||||
|
||||
MetadataContext metadataContext = MetadataContextHolder.get();
|
||||
metadataContext.putFragmentContext(MetadataContext.FRAGMENT_APPLICATION_NONE,
|
||||
MetadataConstant.POLARIS_TARGET_NAMESPACE, namespace);
|
||||
return delegate.getInstances(service);
|
||||
}
|
||||
else {
|
||||
MetadataContext metadataContext = MetadataContextHolder.get();
|
||||
metadataContext.putFragmentContext(MetadataContext.FRAGMENT_APPLICATION_NONE,
|
||||
MetadataConstant.POLARIS_TARGET_NAMESPACE, parts[0]);
|
||||
|
||||
return delegate.getInstances(parts[1]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return delegate.getInstances(service);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getServices() {
|
||||
return delegate.getServices();
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.plugin.unit.instrument.feign;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import com.tencent.cloud.common.constant.OrderConstant;
|
||||
import com.tencent.cloud.plugin.unit.utils.SpringCloudUnitUtils;
|
||||
import com.tencent.tsf.unit.core.TencentUnitContext;
|
||||
import com.tencent.tsf.unit.core.TencentUnitManager;
|
||||
import com.tencent.tsf.unit.core.model.UnitArch;
|
||||
import feign.RequestInterceptor;
|
||||
import feign.RequestTemplate;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
/**
|
||||
* Interceptor used for setting Feign RequestTemplate metadata provider.
|
||||
*
|
||||
* @author lepdou, Hoatian Zhang
|
||||
*/
|
||||
public class UnitFeignRequestInterceptor implements RequestInterceptor, Ordered {
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return OrderConstant.Client.Feign.UNIT_INTERCEPTOR_ORDER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(RequestTemplate requestTemplate) {
|
||||
// 开启单元化
|
||||
if (TencentUnitManager.isEnable()) {
|
||||
String httpServiceName = requestTemplate.feignTarget().url();
|
||||
URI uri = URI.create(httpServiceName);
|
||||
// 截取http://provider-demo 为 provider-demo,
|
||||
String serviceName = uri.getHost();
|
||||
|
||||
SpringCloudUnitUtils.preRequestRecordUnitContext(serviceName);
|
||||
|
||||
if (TencentUnitContext.containRouteTag(TencentUnitContext.CLOUD_SPACE_ROUTE_GATEWAY)) {
|
||||
UnitArch.Gateway gateway = (UnitArch.Gateway) TencentUnitContext.getObjectRouteTag(TencentUnitContext.CLOUD_SPACE_ROUTE_GATEWAY);
|
||||
requestTemplate.target(uri.getScheme() + "//" + gateway.getServiceName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.plugin.unit.instrument.resttemplate;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
||||
import com.tencent.cloud.common.constant.OrderConstant;
|
||||
import com.tencent.cloud.plugin.unit.utils.SpringCloudUnitUtils;
|
||||
import com.tencent.tsf.unit.core.TencentUnitContext;
|
||||
import com.tencent.tsf.unit.core.TencentUnitManager;
|
||||
import com.tencent.tsf.unit.core.model.UnitArch;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
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.web.util.UriComponentsBuilder;
|
||||
|
||||
/**
|
||||
* Interceptor used for unit in RestTemplate.
|
||||
*
|
||||
* @author Shedfree Wu
|
||||
*/
|
||||
public class UnitRestTemplateInterceptor implements ClientHttpRequestInterceptor, Ordered {
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return OrderConstant.Client.RestTemplate.UNIT_INTERCEPTOR_ORDER;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.springframework.http.client.ClientHttpRequestInterceptor#intercept(org.springframework.http.HttpRequest, byte[], org.springframework.http.client.ClientHttpRequestExecution)
|
||||
*/
|
||||
@Override
|
||||
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
|
||||
return execution.execute(getHttpRequestWrapper(request), body);
|
||||
}
|
||||
|
||||
public HttpRequest getHttpRequestWrapper(HttpRequest httpRequest) {
|
||||
// 未开启单元化, 直接返回
|
||||
if (!TencentUnitManager.isEnable()) {
|
||||
return httpRequest;
|
||||
}
|
||||
|
||||
String serviceName = httpRequest.getURI().getHost();
|
||||
SpringCloudUnitUtils.preRequestRecordUnitContext(serviceName);
|
||||
// 不需要转发到网关, 直接返回
|
||||
if (!TencentUnitContext.containRouteTag(TencentUnitContext.CLOUD_SPACE_ROUTE_GATEWAY)) {
|
||||
return httpRequest;
|
||||
}
|
||||
|
||||
UnitArch.Gateway gateway = (UnitArch.Gateway) TencentUnitContext.getObjectRouteTag(TencentUnitContext.CLOUD_SPACE_ROUTE_GATEWAY);
|
||||
URI unitRouteUri = UriComponentsBuilder.fromUri(httpRequest.getURI()).host(gateway.getServiceName()).build()
|
||||
.toUri();
|
||||
return new UriModifyHttpRequestWrapper(httpRequest, unitRouteUri);
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.plugin.unit.instrument.resttemplate;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.springframework.http.HttpRequest;
|
||||
import org.springframework.http.client.support.HttpRequestWrapper;
|
||||
|
||||
public class UriModifyHttpRequestWrapper extends HttpRequestWrapper {
|
||||
|
||||
private final URI uri;
|
||||
|
||||
public UriModifyHttpRequestWrapper(HttpRequest request, URI uri) {
|
||||
super(request);
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getURI() {
|
||||
return uri;
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.plugin.unit.plugin;
|
||||
|
||||
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
|
||||
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
|
||||
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
|
||||
import com.tencent.tsf.unit.core.TencentUnitContext;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
public class UnitClientFinallyEnhancedPlugin implements EnhancedPlugin {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(UnitClientFinallyEnhancedPlugin.class);
|
||||
|
||||
public UnitClientFinallyEnhancedPlugin() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnhancedPluginType getType() {
|
||||
return EnhancedPluginType.Client.FINALLY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(EnhancedPluginContext context) throws Throwable {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("clean unit context, unit context:{}", TencentUnitContext.getOriginCompositeContextMap());
|
||||
}
|
||||
TencentUnitContext.removeAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return Ordered.LOWEST_PRECEDENCE;
|
||||
}
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.plugin.unit.plugin;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.tencent.cloud.common.constant.MetadataConstant;
|
||||
import com.tencent.cloud.common.util.JacksonUtils;
|
||||
import com.tencent.cloud.common.util.ReflectionUtils;
|
||||
import com.tencent.cloud.common.util.UrlUtils;
|
||||
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
|
||||
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
|
||||
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
|
||||
import com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant;
|
||||
import com.tencent.tsf.unit.core.TencentUnitContext;
|
||||
import feign.Request;
|
||||
import shade.polaris.com.google.common.collect.ImmutableMap;
|
||||
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* Pre EnhancedPlugin for feign to encode unit metadata.
|
||||
*
|
||||
* @author Shedfree Wu
|
||||
*/
|
||||
public class UnitFeignEnhancedPlugin implements EnhancedPlugin {
|
||||
@Override
|
||||
public EnhancedPluginType getType() {
|
||||
return EnhancedPluginType.Client.BEFORE_CALLING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(EnhancedPluginContext context) throws Throwable {
|
||||
if (!(context.getOriginRequest() instanceof Request request)) {
|
||||
return;
|
||||
}
|
||||
|
||||
TencentUnitContext.UnitCompositeContextMap unitCompositeContextMap = TencentUnitContext.getOriginCompositeContextMap();
|
||||
if (!com.tencent.polaris.api.utils.CollectionUtils.isEmpty(unitCompositeContextMap.getSystemContext())) {
|
||||
buildMetadataHeader(request, unitCompositeContextMap.getSystemContext(), MetadataConstant.HeaderName.TSF_UNIT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set metadata into the request header for {@link Request} .
|
||||
* @param request instance of {@link Request}
|
||||
* @param metadata metadata map .
|
||||
* @param headerName target metadata http header name .
|
||||
*/
|
||||
private void buildMetadataHeader(Request request, Map<String, String> metadata, String headerName) {
|
||||
if (!CollectionUtils.isEmpty(metadata)) {
|
||||
buildHeaderMap(request, ImmutableMap.of(headerName, JacksonUtils.serialize2Json(metadata)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set headerMap into the request header for {@link Request} .
|
||||
* @param request instance of {@link Request}
|
||||
* @param headerMap header map .
|
||||
*/
|
||||
private void buildHeaderMap(Request request, Map<String, String> headerMap) {
|
||||
if (!CollectionUtils.isEmpty(headerMap)) {
|
||||
Map<String, Collection<String>> headers = getModifiableHeaders(request);
|
||||
headerMap.forEach((key, value) -> headers.put(key, Collections.singletonList(UrlUtils.encode(value))));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The value obtained directly from the headers method is an unmodifiable map.
|
||||
* If the Feign client uses the URL, the original headers are unmodifiable.
|
||||
* @param request feign request
|
||||
* @return modifiable headers
|
||||
*/
|
||||
private Map<String, Collection<String>> getModifiableHeaders(Request request) {
|
||||
Map<String, Collection<String>> headers;
|
||||
headers = (Map<String, Collection<String>>) ReflectionUtils.getFieldValue(request, "headers");
|
||||
|
||||
if (!(headers instanceof LinkedHashMap)) {
|
||||
headers = new LinkedHashMap<>(headers);
|
||||
ReflectionUtils.setFieldValue(request, "headers", headers);
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return PluginOrderConstant.ClientPluginOrder.CONSUMER_UNIT_METADATA_PLUGIN_ORDER;
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.plugin.unit.plugin;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.tencent.cloud.common.constant.MetadataConstant;
|
||||
import com.tencent.cloud.common.util.JacksonUtils;
|
||||
import com.tencent.cloud.common.util.UrlUtils;
|
||||
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
|
||||
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
|
||||
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
|
||||
import com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant;
|
||||
import com.tencent.polaris.api.utils.CollectionUtils;
|
||||
import com.tencent.tsf.unit.core.TencentUnitContext;
|
||||
import shade.polaris.com.google.common.collect.ImmutableMap;
|
||||
|
||||
import org.springframework.http.HttpRequest;
|
||||
|
||||
/**
|
||||
* Pre EnhancedPlugin for rest template to encode unit metadata.
|
||||
*
|
||||
* @author Shedfree Wu
|
||||
*/
|
||||
public class UnitRestTemplateEnhancedPlugin implements EnhancedPlugin {
|
||||
@Override
|
||||
public EnhancedPluginType getType() {
|
||||
return EnhancedPluginType.Client.BEFORE_CALLING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(EnhancedPluginContext context) throws Throwable {
|
||||
if (!(context.getOriginRequest() instanceof HttpRequest httpRequest)) {
|
||||
return;
|
||||
}
|
||||
|
||||
TencentUnitContext.UnitCompositeContextMap unitCompositeContextMap = TencentUnitContext.getOriginCompositeContextMap();
|
||||
if (!CollectionUtils.isEmpty(unitCompositeContextMap.getSystemContext())) {
|
||||
buildMetadataHeader(httpRequest, unitCompositeContextMap.getSystemContext(), MetadataConstant.HeaderName.TSF_UNIT);
|
||||
}
|
||||
}
|
||||
|
||||
private void buildHeaderMap(HttpRequest request, Map<String, String> headerMap) {
|
||||
if (!CollectionUtils.isEmpty(headerMap)) {
|
||||
headerMap.forEach((key, value) -> request.getHeaders().set(key, UrlUtils.encode(value)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)) {
|
||||
buildHeaderMap(request, ImmutableMap.of(headerName, JacksonUtils.serialize2Json(metadata)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return PluginOrderConstant.ClientPluginOrder.CONSUMER_UNIT_METADATA_PLUGIN_ORDER;
|
||||
}
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.plugin.unit.plugin;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.tencent.cloud.common.constant.MetadataConstant;
|
||||
import com.tencent.cloud.common.util.JacksonUtils;
|
||||
import com.tencent.cloud.common.util.UrlUtils;
|
||||
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
|
||||
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
|
||||
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
|
||||
import com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant;
|
||||
import com.tencent.tsf.unit.core.TencentUnitContext;
|
||||
import shade.polaris.com.google.common.collect.ImmutableMap;
|
||||
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
/**
|
||||
* Pre EnhancedPlugin for scg to encode unit metadata.
|
||||
*
|
||||
* @author Shedfree Wu
|
||||
*/
|
||||
public class UnitScgEnhancedPlugin implements EnhancedPlugin {
|
||||
@Override
|
||||
public EnhancedPluginType getType() {
|
||||
return EnhancedPluginType.Client.PRE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(EnhancedPluginContext context) throws Throwable {
|
||||
if (!(context.getOriginRequest() instanceof ServerWebExchange exchange)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// get request builder
|
||||
ServerHttpRequest.Builder builder = exchange.getRequest().mutate();
|
||||
|
||||
TencentUnitContext.UnitCompositeContextMap unitCompositeContextMap = TencentUnitContext.getOriginCompositeContextMap();
|
||||
if (!com.tencent.polaris.api.utils.CollectionUtils.isEmpty(unitCompositeContextMap.getSystemContext())) {
|
||||
buildMetadataHeader(builder, unitCompositeContextMap.getSystemContext(), MetadataConstant.HeaderName.TSF_UNIT);
|
||||
}
|
||||
|
||||
context.setOriginRequest(exchange.mutate().request(builder.build()).build());
|
||||
}
|
||||
|
||||
private void buildHeaderMap(ServerHttpRequest.Builder builder, Map<String, String> headerMap) {
|
||||
if (!CollectionUtils.isEmpty(headerMap)) {
|
||||
headerMap.forEach((key, value) -> builder.header(key, UrlUtils.encode(value)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)) {
|
||||
buildHeaderMap(builder, ImmutableMap.of(headerName, JacksonUtils.serialize2Json(metadata)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return PluginOrderConstant.ClientPluginOrder.CONSUMER_UNIT_METADATA_PLUGIN_ORDER;
|
||||
}
|
||||
}
|
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.plugin.unit.plugin;
|
||||
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.tencent.cloud.common.constant.MetadataConstant;
|
||||
import com.tencent.cloud.common.util.JacksonUtils;
|
||||
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
|
||||
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
|
||||
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
|
||||
import com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant;
|
||||
import com.tencent.polaris.api.utils.StringUtils;
|
||||
import com.tencent.tsf.unit.core.TencentUnitContext;
|
||||
import com.tencent.tsf.unit.core.TencentUnitManager;
|
||||
import com.tencent.tsf.unit.core.model.UnitTagPosition;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class UnitServletPreEnhancedPlugin implements EnhancedPlugin {
|
||||
private static final Logger logger = LoggerFactory.getLogger(UnitServletPreEnhancedPlugin.class);
|
||||
|
||||
@Override
|
||||
public EnhancedPluginType getType() {
|
||||
return EnhancedPluginType.Server.PRE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(EnhancedPluginContext context) throws Throwable {
|
||||
if (!(context.getOriginRequest() instanceof HttpServletRequest httpServletRequest)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TencentUnitManager.isEnable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
TencentUnitContext.removeAll();
|
||||
|
||||
String unitContextEncoded = httpServletRequest.getHeader(MetadataConstant.HeaderName.TSF_UNIT);
|
||||
if (StringUtils.isNotEmpty(unitContextEncoded)) {
|
||||
Map<String, String> unitMap = JacksonUtils.deserialize2Map(URLDecoder.decode(unitContextEncoded, StandardCharsets.UTF_8));
|
||||
|
||||
TencentUnitContext.putSourceTags(unitMap);
|
||||
if (TencentUnitManager.isContextPassingThroughEnabled()) {
|
||||
// 不能传递所有的 key, 只需要传递客户要素和业务系统,灰度信息
|
||||
Optional.ofNullable(unitMap.get(TencentUnitContext.CLOUD_SPACE_CUSTOMER_IDENTIFIER)).
|
||||
ifPresent(value -> TencentUnitContext.putSystemTag(TencentUnitContext.CLOUD_SPACE_CUSTOMER_IDENTIFIER, value));
|
||||
Optional.ofNullable(unitMap.get(TencentUnitContext.CLOUD_SPACE_TARGET_SYSTEM)).
|
||||
ifPresent(value -> TencentUnitContext.putSystemTag(TencentUnitContext.CLOUD_SPACE_TARGET_SYSTEM, value));
|
||||
Optional.ofNullable(unitMap.get(TencentUnitContext.CLOUD_SPACE_GRAY_UNIT_INFO)).
|
||||
ifPresent(value -> TencentUnitContext.putSystemTag(TencentUnitContext.CLOUD_SPACE_GRAY_UNIT_INFO, value));
|
||||
}
|
||||
else {
|
||||
// 没有 passing through 标志,灰度信息也要透传
|
||||
Optional.ofNullable(unitMap.get(TencentUnitContext.CLOUD_SPACE_GRAY_UNIT_INFO)).
|
||||
ifPresent(value -> TencentUnitContext.putSystemTag(TencentUnitContext.CLOUD_SPACE_GRAY_UNIT_INFO, value));
|
||||
}
|
||||
}
|
||||
|
||||
for (String grayKey : TencentUnitManager.getGrayUnitHeaderKey()) {
|
||||
String value = httpServletRequest.getHeader(grayKey);
|
||||
// 非空 value 才设置,便于匹配灰度规则时能否直接跳过
|
||||
if (StringUtils.isNotEmpty(value)) {
|
||||
TencentUnitContext.putGrayUserTag(UnitTagPosition.HEADER.name(), grayKey, value);
|
||||
}
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("[getSerializeTagsFromRequestMeta] unit context:{}",
|
||||
TencentUnitContext.getOriginCompositeContextMap());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return PluginOrderConstant.ServerPluginOrder.TRACE_SERVER_PRE_PLUGIN_ORDER;
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.tsf.unit.core;
|
||||
|
||||
import com.tencent.polaris.api.utils.IPAddressUtils;
|
||||
|
||||
public final class Env {
|
||||
|
||||
private Env() {
|
||||
}
|
||||
|
||||
private final static String consulToken;
|
||||
|
||||
private final static String consulHost;
|
||||
|
||||
private final static Integer consulPort;
|
||||
|
||||
private final static String namespaceId;
|
||||
|
||||
static {
|
||||
// 只支持从环境变量取
|
||||
consulHost = IPAddressUtils.getIpCompatible(getSystemProperty("tsf_consul_ip", "localhost"));
|
||||
consulPort = Integer.parseInt(getSystemProperty("tsf_consul_port", "8500"));
|
||||
consulToken = getSystemProperty("tsf_token", "");
|
||||
namespaceId = getSystemProperty("tsf_namespace_id", "");
|
||||
}
|
||||
|
||||
private static String getSystemProperty(String name, String defaultValue) {
|
||||
String val = null;
|
||||
if (System.getenv(name) != null) {
|
||||
val = System.getenv(name);
|
||||
}
|
||||
if (System.getProperty(name) != null) {
|
||||
val = System.getProperty(name);
|
||||
}
|
||||
return (val == null) ? defaultValue : val;
|
||||
}
|
||||
|
||||
public static String getConsulToken() {
|
||||
return consulToken;
|
||||
}
|
||||
|
||||
public static String getConsulHost() {
|
||||
return consulHost;
|
||||
}
|
||||
|
||||
public static Integer getConsulPort() {
|
||||
return consulPort;
|
||||
}
|
||||
|
||||
public static String getNamespaceId() {
|
||||
return namespaceId;
|
||||
}
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.tsf.unit.core;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.tencent.polaris.api.utils.StringUtils;
|
||||
import com.tencent.tsf.unit.core.model.UnitArch.Gateway;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class GatewayUnitArchCallback implements IUnitChangeCallback {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(GatewayUnitArchCallback.class);
|
||||
private final String applicationName;
|
||||
|
||||
public GatewayUnitArchCallback(String applicationName) {
|
||||
this.applicationName = applicationName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void callback() {
|
||||
boolean enableUnit = false;
|
||||
for (Map.Entry<String, Gateway> entry : TencentUnitManager.getLocalBusinessSystemGwMap().entrySet()) {
|
||||
Gateway gateway = entry.getValue();
|
||||
if (StringUtils.equals(applicationName, gateway.getServiceName())
|
||||
&& StringUtils.equals(Env.getNamespaceId(), gateway.getNamespaceId())) {
|
||||
enableUnit = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!enableUnit) {
|
||||
for (Map.Entry<String, Gateway> entry: TencentUnitManager.getLocalOnlyGwMap().entrySet()) {
|
||||
Gateway gateway = entry.getValue();
|
||||
if (StringUtils.equals(applicationName, gateway.getServiceName())
|
||||
&& StringUtils.equals(Env.getNamespaceId(), gateway.getNamespaceId())) {
|
||||
enableUnit = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("[callback] enableUnit:{}, applicationName:{}, ns:{}, localBusinessSystemGwMap:{}, localOnlyGwMap:{}",
|
||||
enableUnit, applicationName, Env.getNamespaceId(), TencentUnitManager.getLocalBusinessSystemGwMap(), TencentUnitManager.getLocalOnlyGwMap());
|
||||
}
|
||||
if (TencentUnitManager.isEnable() != enableUnit) {
|
||||
LOGGER.info("[callback] unit enable change, new status:{}", enableUnit);
|
||||
}
|
||||
TencentUnitManager.setEnable(enableUnit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.getClass().getSimpleName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof GatewayUnitArchCallback that)) {
|
||||
return false;
|
||||
}
|
||||
return StringUtils.equals(applicationName, that.applicationName) && StringUtils.equals(getName(), that.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getName(), applicationName);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.tsf.unit.core;
|
||||
|
||||
public interface IUnitChangeCallback {
|
||||
|
||||
void callback();
|
||||
|
||||
String getName();
|
||||
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.tsf.unit.core;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
import com.tencent.tsf.unit.core.mapping.api.IMappingService;
|
||||
import com.tencent.tsf.unit.core.mapping.impl.CustomerMappingService;
|
||||
|
||||
/**
|
||||
* 找到MappingService的实现.
|
||||
*/
|
||||
public final class MappingServiceLoader {
|
||||
|
||||
private MappingServiceLoader() {
|
||||
}
|
||||
|
||||
private static IMappingService service;
|
||||
|
||||
static {
|
||||
ServiceLoader<IMappingService> mappingServices = ServiceLoader.load(IMappingService.class);
|
||||
if (mappingServices != null) {
|
||||
Iterator<IMappingService> itr = mappingServices.iterator();
|
||||
while (itr.hasNext()) {
|
||||
service = itr.next();
|
||||
}
|
||||
}
|
||||
|
||||
// 默认实现
|
||||
if (service == null) {
|
||||
service = new CustomerMappingService();
|
||||
}
|
||||
}
|
||||
|
||||
public static IMappingService getService() {
|
||||
return service;
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.tsf.unit.core;
|
||||
|
||||
|
||||
import com.tencent.polaris.api.utils.StringUtils;
|
||||
|
||||
public enum TransformAlgorithmEnum {
|
||||
|
||||
/**
|
||||
* hash后取模.
|
||||
*/
|
||||
HASHCODE,
|
||||
/**
|
||||
* 直接取模.
|
||||
*/
|
||||
MOD,
|
||||
/**
|
||||
* 字符串截取.
|
||||
*/
|
||||
SUBSTR,
|
||||
/**
|
||||
* 扩展用.
|
||||
*/
|
||||
OTHER;
|
||||
|
||||
public static TransformAlgorithmEnum getTransformAlgorith(String type) {
|
||||
if (StringUtils.isEmpty(type)) {
|
||||
return OTHER;
|
||||
}
|
||||
for (TransformAlgorithmEnum transformAlgorithmEnum : TransformAlgorithmEnum.values()) {
|
||||
if (transformAlgorithmEnum.name().equalsIgnoreCase(type)) {
|
||||
return transformAlgorithmEnum;
|
||||
}
|
||||
}
|
||||
// 其他的当做 other
|
||||
return OTHER;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.tsf.unit.core;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import com.tencent.polaris.api.utils.StringUtils;
|
||||
import com.tencent.tsf.unit.core.zonefilter.TsfZoneFilterManager;
|
||||
|
||||
public class TsfZoneFilterUnitCallback implements IUnitChangeCallback {
|
||||
|
||||
@Override
|
||||
public void callback() {
|
||||
TsfZoneFilterManager.setDisabledZoneSet(TencentUnitManager.getDisableZoneSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.getClass().getSimpleName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof TsfZoneFilterUnitCallback that)) {
|
||||
return false;
|
||||
}
|
||||
return StringUtils.equals(getName(), that.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getName());
|
||||
}
|
||||
}
|
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.tsf.unit.core;
|
||||
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import com.tencent.tsf.unit.core.model.UnitTagPosition;
|
||||
|
||||
public class UnitTag {
|
||||
|
||||
private UnitTagPosition tagPosition;
|
||||
/**
|
||||
* 标签名.
|
||||
*/
|
||||
private String tagField;
|
||||
|
||||
/**
|
||||
* 标签运算符.
|
||||
* 定义在 UnitTagConstant.OPERATOR
|
||||
*/
|
||||
private String tagOperator;
|
||||
|
||||
/**
|
||||
* 标签的被运算对象值.
|
||||
*/
|
||||
private String tagValue;
|
||||
|
||||
public UnitTag() {
|
||||
}
|
||||
|
||||
public UnitTag(String tagField, String tagValue) {
|
||||
this.tagField = tagField;
|
||||
this.tagValue = tagValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UnitTag{" +
|
||||
"position=" + tagPosition +
|
||||
", tagField='" + tagField + '\'' +
|
||||
", tagOperator='" + tagOperator + '\'' +
|
||||
", tagValue='" + tagValue + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof UnitTag tag)) {
|
||||
return false;
|
||||
}
|
||||
return Objects.equals(tagPosition, tag.tagPosition) &&
|
||||
tagField.equals(tag.tagField) &&
|
||||
tagOperator.equals(tag.tagOperator) &&
|
||||
tagValue.equals(tag.tagValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(tagField, tagOperator, tagValue);
|
||||
}
|
||||
|
||||
public UnitTagPosition getTagPosition() {
|
||||
return tagPosition;
|
||||
}
|
||||
|
||||
public void setTagPosition(UnitTagPosition tagPosition) {
|
||||
this.tagPosition = tagPosition;
|
||||
}
|
||||
|
||||
public String getTagField() {
|
||||
return tagField;
|
||||
}
|
||||
|
||||
public void setTagField(String tagField) {
|
||||
this.tagField = tagField;
|
||||
}
|
||||
|
||||
public String getTagOperator() {
|
||||
return tagOperator;
|
||||
}
|
||||
|
||||
public void setTagOperator(String tagOperator) {
|
||||
this.tagOperator = tagOperator;
|
||||
}
|
||||
|
||||
public String getTagValue() {
|
||||
return tagValue;
|
||||
}
|
||||
|
||||
public void setTagValue(String tagValue) {
|
||||
this.tagValue = tagValue;
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.tsf.unit.core;
|
||||
|
||||
public class UnitTagConstant {
|
||||
|
||||
/**
|
||||
* 规则之间运算表达式的逻辑关系.
|
||||
*/
|
||||
public static class TagRuleRelation {
|
||||
/**
|
||||
* 与.
|
||||
*/
|
||||
public static final String AND = "AND";
|
||||
/**
|
||||
* 或.
|
||||
*/
|
||||
public static final String OR = "OR";
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作符.
|
||||
*/
|
||||
public static class OPERATOR {
|
||||
|
||||
/**
|
||||
* 包含.
|
||||
*/
|
||||
public static final String IN = "IN";
|
||||
/**
|
||||
* 不包含.
|
||||
*/
|
||||
public static final String NOT_IN = "NOT_IN";
|
||||
/**
|
||||
* 等于.
|
||||
*/
|
||||
public static final String EQUAL = "EQUAL";
|
||||
/**
|
||||
* 不等于.
|
||||
*/
|
||||
public static final String NOT_EQUAL = "NOT_EQUAL";
|
||||
/**
|
||||
* 正则.
|
||||
*/
|
||||
public static final String REGEX = "REGEX";
|
||||
/**
|
||||
* 范围.
|
||||
*/
|
||||
public static final String RANGE = "RANGE";
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.tsf.unit.core.algorithm;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.tencent.polaris.api.utils.StringUtils;
|
||||
import com.tencent.tsf.unit.core.TransformAlgorithmEnum;
|
||||
|
||||
public class HashCodeAlgorithm implements IUnitTransformAlgorithm {
|
||||
|
||||
private final Map<String, Object> options;
|
||||
|
||||
private final int mod;
|
||||
|
||||
public HashCodeAlgorithm(Map<String, Object> options) {
|
||||
this.options = options;
|
||||
mod = Integer.parseInt(String.valueOf(options.get("mod")));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return TransformAlgorithmEnum.HASHCODE.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String transform(String cid) {
|
||||
if (StringUtils.isEmpty(cid)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return String.valueOf(cid.hashCode() % mod);
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.tsf.unit.core.algorithm;
|
||||
|
||||
public interface IUnitTransformAlgorithm {
|
||||
|
||||
String getName();
|
||||
|
||||
String transform(String cid);
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.tsf.unit.core.algorithm;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.tencent.polaris.api.utils.StringUtils;
|
||||
import com.tencent.tsf.unit.core.TransformAlgorithmEnum;
|
||||
import com.tencent.tsf.unit.core.exception.ErrorCode;
|
||||
import com.tencent.tsf.unit.core.exception.TencentUnitException;
|
||||
|
||||
public class ModAlgorithm implements IUnitTransformAlgorithm {
|
||||
|
||||
private final Map<String, Object> options;
|
||||
|
||||
private final int mod;
|
||||
|
||||
public ModAlgorithm(Map<String, Object> options) {
|
||||
this.options = options;
|
||||
mod = Integer.parseInt(String.valueOf(options.get("mod")));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return TransformAlgorithmEnum.MOD.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String transform(String cid) {
|
||||
if (StringUtils.isEmpty(cid)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
long id = Long.parseLong(cid);
|
||||
return String.valueOf(id % mod);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new TencentUnitException(ErrorCode.CUSTOMER_NUMBER_TRANSFORM_ERROR, "format invalid, customNumber:" + cid, e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.tsf.unit.core.algorithm;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.tencent.tsf.unit.core.TransformAlgorithmEnum;
|
||||
|
||||
public class SubstrAlgorithm implements IUnitTransformAlgorithm {
|
||||
|
||||
private final Map<String, Object> options;
|
||||
|
||||
public SubstrAlgorithm(Map<String, Object> options) {
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return TransformAlgorithmEnum.SUBSTR.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String transform(String cid) {
|
||||
return cid;
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.tsf.unit.core.exception;
|
||||
|
||||
public enum ErrorCode {
|
||||
/**
|
||||
* 内部加载配置错误.
|
||||
*/
|
||||
LOAD_ERROR(10000),
|
||||
/**
|
||||
* 客户直接或间接输入的通用参数错误.
|
||||
*/
|
||||
COMMON_PARAMETER_ERROR(10001),
|
||||
/**
|
||||
* 客户号映射服务为空.
|
||||
*/
|
||||
MAPPING_SERVICE_EMPTY_ERROR(10002),
|
||||
/**
|
||||
* 客户号映射服务的 url 为空.
|
||||
*/
|
||||
MAPPING_URL_EMPTY_ERROR(10003),
|
||||
/**
|
||||
* 客户号映射服务的响应码错误.
|
||||
*/
|
||||
MAPPING_RESPONSE_CODE_ERROR(10004),
|
||||
/**
|
||||
* 客户号映射服务的响应体空错误.
|
||||
*/
|
||||
MAPPING_RESPONSE_EMPTY_BODY_ERROR(10005),
|
||||
/**
|
||||
* 客户号服务响应体解析后无 customer number.
|
||||
*/
|
||||
MAPPING_RESPONSE_CUSTOMER_NUMBER_EMPTY_ERROR(10006),
|
||||
/**
|
||||
* 客户号服务请求出现 IO 错误.
|
||||
*/
|
||||
MAPPING_REQUEST_IO_ERROR(10007),
|
||||
/**
|
||||
* 客户号转换错误.
|
||||
*/
|
||||
CUSTOMER_NUMBER_TRANSFORM_ERROR(10008),
|
||||
/**
|
||||
* 客户要素解析错误.
|
||||
*/
|
||||
CUSTOMER_IDENTIFIER_TRANSFORM_ERROR(10009);
|
||||
|
||||
private final int code;
|
||||
|
||||
ErrorCode(int code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.tsf.unit.core.exception;
|
||||
|
||||
public class TencentUnitException extends RuntimeException {
|
||||
|
||||
private final ErrorCode code;
|
||||
|
||||
public TencentUnitException(ErrorCode code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public TencentUnitException(ErrorCode code, String message) {
|
||||
super(message);
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public TencentUnitException(ErrorCode code, String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
StringBuilder builder = new StringBuilder(String.format("ERR-%d(%s): ", code.getCode(), code.name()));
|
||||
builder.append(super.getMessage());
|
||||
Throwable cause = getCause();
|
||||
if (null != cause) {
|
||||
builder.append(", cause: ").append(cause.getMessage());
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public ErrorCode getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.tsf.unit.core.mapping.api;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MappingEntity {
|
||||
|
||||
// 客户号
|
||||
private String customerNumber;
|
||||
|
||||
public MappingEntity() {
|
||||
|
||||
}
|
||||
|
||||
public MappingEntity(String customerNumber) {
|
||||
this.customerNumber = customerNumber;
|
||||
}
|
||||
|
||||
public String getCustomerNumber() {
|
||||
return customerNumber;
|
||||
}
|
||||
|
||||
public void setCustomerNumber(String customerNumber) {
|
||||
this.customerNumber = customerNumber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MappingEntity{" +
|
||||
"customerNumber='" + customerNumber + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.tsf.unit.core.mapping.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.tencent.polaris.api.utils.StringUtils;
|
||||
import com.tencent.tsf.unit.core.TencentUnitManager;
|
||||
import com.tencent.tsf.unit.core.exception.ErrorCode;
|
||||
import com.tencent.tsf.unit.core.exception.TencentUnitException;
|
||||
import com.tencent.tsf.unit.core.mapping.api.IMappingService;
|
||||
import com.tencent.tsf.unit.core.mapping.api.MappingEntity;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import shade.polaris.okhttp3.HttpUrl;
|
||||
import shade.polaris.okhttp3.OkHttpClient;
|
||||
import shade.polaris.okhttp3.Request;
|
||||
import shade.polaris.okhttp3.Response;
|
||||
|
||||
public class CustomerMappingService implements IMappingService {
|
||||
|
||||
private static final String DEFAULT_ROUTER_IDENTIFIER_QUERY_KEY = "RouterIdentifier";
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(CustomerMappingService.class);
|
||||
|
||||
// 连接超时=2s,请求超时=2s
|
||||
private final OkHttpClient client = new OkHttpClient.Builder().
|
||||
connectTimeout(2, TimeUnit.SECONDS).readTimeout(2, TimeUnit.SECONDS).build();
|
||||
|
||||
@Override
|
||||
public MappingEntity processMapping(String params) {
|
||||
String mappingUrl = getMappingUrl();
|
||||
if (StringUtils.isEmpty(mappingUrl)) {
|
||||
String msg = "[MappingService] mapping url is null";
|
||||
LOG.warn(msg);
|
||||
throw new TencentUnitException(ErrorCode.MAPPING_URL_EMPTY_ERROR, msg);
|
||||
}
|
||||
|
||||
// params解析
|
||||
String url = urlBuild(mappingUrl, params);
|
||||
Request request = new Request.Builder().url(url).build();
|
||||
try {
|
||||
Response response = client.newCall(request).execute();
|
||||
if (!response.isSuccessful()) {
|
||||
String msg = String.format("request fail. url:%s, code:%s, err:%s",
|
||||
url, response.code(), response.message());
|
||||
LOG.error("[CustomerMappingService] " + msg);
|
||||
if (response.body() != null) {
|
||||
response.body().close();
|
||||
}
|
||||
throw new TencentUnitException(ErrorCode.MAPPING_RESPONSE_CODE_ERROR, msg);
|
||||
}
|
||||
|
||||
if (response.body() == null) {
|
||||
String msg = String.format("response body is null. url:%s", url);
|
||||
LOG.error("[CustomerMappingService] " + msg);
|
||||
throw new TencentUnitException(ErrorCode.MAPPING_RESPONSE_EMPTY_BODY_ERROR, msg);
|
||||
}
|
||||
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
MappingEntity entity = objectMapper.readValue(response.body().string(), MappingEntity.class);
|
||||
response.body().close();
|
||||
return entity;
|
||||
}
|
||||
catch (IOException e) {
|
||||
String msg = String.format("occur IOException. url:%s, err:%s", url, e);
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.error("[CustomerMappingService] " + msg, e);
|
||||
}
|
||||
else {
|
||||
LOG.error("[CustomerMappingService] " + msg);
|
||||
}
|
||||
throw new TencentUnitException(ErrorCode.MAPPING_REQUEST_IO_ERROR, msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
private String urlBuild(String mappingUrl, String params) {
|
||||
if (params == null) {
|
||||
return mappingUrl;
|
||||
}
|
||||
|
||||
HttpUrl.Builder urlBuilder = HttpUrl.get(mappingUrl).newBuilder();
|
||||
if (StringUtils.isNotEmpty(params)) {
|
||||
urlBuilder.addQueryParameter(DEFAULT_ROUTER_IDENTIFIER_QUERY_KEY, params);
|
||||
}
|
||||
return urlBuilder.build().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 每次都从配置中获取.
|
||||
*/
|
||||
public String getMappingUrl() {
|
||||
return TencentUnitManager.getLocalCloudMappingApi();
|
||||
}
|
||||
}
|
@ -0,0 +1,446 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.tsf.unit.core.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 详细定义参考 iwiki /p/4009047246.
|
||||
*/
|
||||
public class UnitArch {
|
||||
|
||||
private TencentUnitArch tencent;
|
||||
|
||||
public TencentUnitArch getTencent() {
|
||||
return tencent;
|
||||
}
|
||||
|
||||
public void setTencent(TencentUnitArch tencent) {
|
||||
this.tencent = tencent;
|
||||
}
|
||||
|
||||
public static class TencentUnitArch {
|
||||
private UnitCloudArch unitCloudArchitecture;
|
||||
|
||||
public UnitCloudArch getUnitCloudArchitecture() {
|
||||
return unitCloudArchitecture;
|
||||
}
|
||||
|
||||
public void setUnitCloudArchitecture(UnitCloudArch unitCloudArchitecture) {
|
||||
this.unitCloudArchitecture = unitCloudArchitecture;
|
||||
}
|
||||
}
|
||||
|
||||
public static class UnitCloudArch {
|
||||
|
||||
private String localCloudId;
|
||||
|
||||
private List<CloudSpace> cloudSpaces;
|
||||
|
||||
private List<BusinessSystem> businessSystems;
|
||||
|
||||
public String getLocalCloudId() {
|
||||
return localCloudId;
|
||||
}
|
||||
|
||||
public void setLocalCloudId(String localCloudId) {
|
||||
this.localCloudId = localCloudId;
|
||||
}
|
||||
|
||||
public List<CloudSpace> getCloudSpaces() {
|
||||
return cloudSpaces;
|
||||
}
|
||||
|
||||
public void setCloudSpaces(List<CloudSpace> cloudSpaces) {
|
||||
this.cloudSpaces = cloudSpaces;
|
||||
}
|
||||
|
||||
public List<BusinessSystem> getBusinessSystems() {
|
||||
return businessSystems;
|
||||
}
|
||||
|
||||
public void setBusinessSystems(
|
||||
List<BusinessSystem> businessSystems) {
|
||||
this.businessSystems = businessSystems;
|
||||
}
|
||||
}
|
||||
|
||||
public static class CloudSpace {
|
||||
private String cloudId;
|
||||
|
||||
private String cloudName;
|
||||
|
||||
private String regionId;
|
||||
|
||||
private String RegionName;
|
||||
|
||||
private List<Sdu> sdus;
|
||||
|
||||
private List<Gdu> gdus;
|
||||
|
||||
private List<Sdu> graySdus;
|
||||
|
||||
private List<Gdu> grayGdus;
|
||||
|
||||
private List<Gateway> gateways;
|
||||
|
||||
private List<Gateway> scopeGateways;
|
||||
|
||||
private String mappingServiceUrl;
|
||||
|
||||
public String getCloudId() {
|
||||
return cloudId;
|
||||
}
|
||||
|
||||
public void setCloudId(String cloudId) {
|
||||
this.cloudId = cloudId;
|
||||
}
|
||||
|
||||
public String getCloudName() {
|
||||
return cloudName;
|
||||
}
|
||||
|
||||
public void setCloudName(String cloudName) {
|
||||
this.cloudName = cloudName;
|
||||
}
|
||||
|
||||
public String getRegionId() {
|
||||
return regionId;
|
||||
}
|
||||
|
||||
public void setRegionId(String regionId) {
|
||||
this.regionId = regionId;
|
||||
}
|
||||
|
||||
public String getRegionName() {
|
||||
return RegionName;
|
||||
}
|
||||
|
||||
public void setRegionName(String regionName) {
|
||||
RegionName = regionName;
|
||||
}
|
||||
|
||||
public List<Sdu> getSdus() {
|
||||
return sdus;
|
||||
}
|
||||
|
||||
public void setSdus(List<Sdu> sdus) {
|
||||
this.sdus = sdus;
|
||||
}
|
||||
|
||||
public List<Gdu> getGdus() {
|
||||
return gdus;
|
||||
}
|
||||
|
||||
public void setGdus(List<Gdu> gdus) {
|
||||
this.gdus = gdus;
|
||||
}
|
||||
|
||||
public List<Sdu> getGraySdus() {
|
||||
return graySdus;
|
||||
}
|
||||
|
||||
public void setGraySdus(List<Sdu> graySdus) {
|
||||
this.graySdus = graySdus;
|
||||
}
|
||||
|
||||
public List<Gdu> getGrayGdus() {
|
||||
return grayGdus;
|
||||
}
|
||||
|
||||
public void setGrayGdus(List<Gdu> grayGdus) {
|
||||
this.grayGdus = grayGdus;
|
||||
}
|
||||
|
||||
public List<Gateway> getGateways() {
|
||||
return gateways;
|
||||
}
|
||||
|
||||
public void setGateways(List<Gateway> gateways) {
|
||||
this.gateways = gateways;
|
||||
}
|
||||
|
||||
public List<Gateway> getScopeGateways() {
|
||||
return scopeGateways;
|
||||
}
|
||||
|
||||
public void setScopeGateways(List<Gateway> scopeGateways) {
|
||||
this.scopeGateways = scopeGateways;
|
||||
}
|
||||
|
||||
public String getMappingServiceUrl() {
|
||||
return mappingServiceUrl;
|
||||
}
|
||||
|
||||
public void setMappingServiceUrl(String mappingServiceUrl) {
|
||||
this.mappingServiceUrl = mappingServiceUrl;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Sdu extends DeploymentUnit {
|
||||
private GduRule gduRule;
|
||||
|
||||
public GduRule getGduRule() {
|
||||
return gduRule;
|
||||
}
|
||||
|
||||
public void setGduRule(GduRule gduRule) {
|
||||
this.gduRule = gduRule;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Gdu extends DeploymentUnit {
|
||||
|
||||
}
|
||||
|
||||
public static class DeploymentUnit {
|
||||
private String id;
|
||||
|
||||
private String name;
|
||||
|
||||
private String zoneId;
|
||||
|
||||
private String zoneName;
|
||||
|
||||
private List<UnitNamespace> namespaces;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getZoneId() {
|
||||
return zoneId;
|
||||
}
|
||||
|
||||
public void setZoneId(String zoneId) {
|
||||
this.zoneId = zoneId;
|
||||
}
|
||||
|
||||
public String getZoneName() {
|
||||
return zoneName;
|
||||
}
|
||||
|
||||
public void setZoneName(String zoneName) {
|
||||
this.zoneName = zoneName;
|
||||
}
|
||||
|
||||
public List<UnitNamespace> getNamespaces() {
|
||||
return namespaces;
|
||||
}
|
||||
|
||||
public void setNamespaces(List<UnitNamespace> namespaces) {
|
||||
this.namespaces = namespaces;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Gateway {
|
||||
private String id;
|
||||
|
||||
private Address address;
|
||||
|
||||
private String businessSystemName;
|
||||
|
||||
private RouteScope routeScope;
|
||||
|
||||
private String serviceName;
|
||||
|
||||
private String namespaceId;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Address getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(Address address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public String getBusinessSystemName() {
|
||||
return businessSystemName;
|
||||
}
|
||||
|
||||
public void setBusinessSystemName(String businessSystemName) {
|
||||
this.businessSystemName = businessSystemName;
|
||||
}
|
||||
|
||||
public RouteScope getRouteScope() {
|
||||
return routeScope;
|
||||
}
|
||||
|
||||
public void setRouteScope(RouteScope routeScope) {
|
||||
this.routeScope = routeScope;
|
||||
}
|
||||
|
||||
public String getServiceName() {
|
||||
return serviceName;
|
||||
}
|
||||
|
||||
public void setServiceName(String serviceName) {
|
||||
this.serviceName = serviceName;
|
||||
}
|
||||
|
||||
public String getNamespaceId() {
|
||||
return namespaceId;
|
||||
}
|
||||
|
||||
public void setNamespaceId(String namespaceId) {
|
||||
this.namespaceId = namespaceId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Gateway{" +
|
||||
"id='" + id + '\'' +
|
||||
", address=" + address +
|
||||
", businessSystemName='" + businessSystemName + '\'' +
|
||||
", serviceName='" + serviceName + '\'' +
|
||||
", namespaceId='" + namespaceId + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
public static class Address {
|
||||
private String host;
|
||||
|
||||
private String port;
|
||||
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public String getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setPort(String port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Address{" +
|
||||
"host='" + host + '\'' +
|
||||
", port='" + port + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
public static class GduRule {
|
||||
private GduRuleRoute route;
|
||||
|
||||
public GduRuleRoute getRoute() {
|
||||
return route;
|
||||
}
|
||||
|
||||
public void setRoute(GduRuleRoute route) {
|
||||
this.route = route;
|
||||
}
|
||||
}
|
||||
|
||||
public static class BusinessSystem {
|
||||
private String id;
|
||||
|
||||
private String name;
|
||||
|
||||
private String type;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
|
||||
public static class GduRuleRoute {
|
||||
private String cloudSpaceId;
|
||||
|
||||
private String unitId;
|
||||
|
||||
public String getCloudSpaceId() {
|
||||
return cloudSpaceId;
|
||||
}
|
||||
|
||||
public void setCloudSpaceId(String cloudSpaceId) {
|
||||
this.cloudSpaceId = cloudSpaceId;
|
||||
}
|
||||
|
||||
public String getUnitId() {
|
||||
return unitId;
|
||||
}
|
||||
|
||||
public void setUnitId(String unitId) {
|
||||
this.unitId = unitId;
|
||||
}
|
||||
}
|
||||
|
||||
public enum RouteScope {
|
||||
/**
|
||||
* LOCAL.
|
||||
*/
|
||||
LOCAL,
|
||||
/**
|
||||
* REMOTE.
|
||||
*/
|
||||
REMOTE,
|
||||
/**
|
||||
* LOCAL_REMOTE.
|
||||
*/
|
||||
LOCAL_REMOTE
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.tsf.unit.core.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class UnitGray {
|
||||
|
||||
private TencentUnitGray tencent;
|
||||
|
||||
public TencentUnitGray getTencent() {
|
||||
return tencent;
|
||||
}
|
||||
|
||||
public void setTencent(TencentUnitGray tencent) {
|
||||
this.tencent = tencent;
|
||||
}
|
||||
|
||||
public static class TencentUnitGray {
|
||||
private UnitGrayList unitGrayList;
|
||||
|
||||
public UnitGrayList getUnitGrayList() {
|
||||
return unitGrayList;
|
||||
}
|
||||
|
||||
public void setUnitGrayList(UnitGrayList unitGrayList) {
|
||||
this.unitGrayList = unitGrayList;
|
||||
}
|
||||
}
|
||||
|
||||
public static class UnitGrayList {
|
||||
private String version;
|
||||
|
||||
private List<String> ids;
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public List<String> getIds() {
|
||||
return ids;
|
||||
}
|
||||
|
||||
public void setIds(List<String> ids) {
|
||||
this.ids = ids;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.tsf.unit.core.model;
|
||||
|
||||
public class UnitNamespace {
|
||||
|
||||
private String id;
|
||||
|
||||
private String name;
|
||||
|
||||
private String businessSystemName;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getBusinessSystemName() {
|
||||
return businessSystemName;
|
||||
}
|
||||
|
||||
public void setBusinessSystemName(String businessSystemName) {
|
||||
this.businessSystemName = businessSystemName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UnitNamespace{" +
|
||||
"id='" + id + '\'' +
|
||||
", name='" + name + '\'' +
|
||||
", businessSystemName='" + businessSystemName + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -0,0 +1,566 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.tsf.unit.core.model;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.tencent.tsf.unit.core.UnitTag;
|
||||
import com.tencent.tsf.unit.core.algorithm.IUnitTransformAlgorithm;
|
||||
|
||||
public class UnitRouteInfo {
|
||||
|
||||
private TencentUnitRouteRule tencent;
|
||||
|
||||
public TencentUnitRouteRule getTencent() {
|
||||
return tencent;
|
||||
}
|
||||
|
||||
public void setTencent(TencentUnitRouteRule tencent) {
|
||||
this.tencent = tencent;
|
||||
}
|
||||
|
||||
public static class TencentUnitRouteRule {
|
||||
private UnitRouteRule unitRouteRule;
|
||||
|
||||
private List<UnitRoute> gduRouteRule;
|
||||
|
||||
private GrayUnitRouteRule grayUnitRouteRule;
|
||||
|
||||
private RouterIdentifier routerIdentifier;
|
||||
|
||||
public UnitRouteRule getUnitRouteRule() {
|
||||
return unitRouteRule;
|
||||
}
|
||||
|
||||
public void setUnitRouteRule(UnitRouteRule unitRouteRule) {
|
||||
this.unitRouteRule = unitRouteRule;
|
||||
}
|
||||
|
||||
public List<UnitRoute> getGduRouteRule() {
|
||||
return gduRouteRule;
|
||||
}
|
||||
|
||||
public void setGduRouteRule(List<UnitRoute> gduRouteRule) {
|
||||
this.gduRouteRule = gduRouteRule;
|
||||
}
|
||||
|
||||
public GrayUnitRouteRule getGrayUnitRouteRule() {
|
||||
return grayUnitRouteRule;
|
||||
}
|
||||
|
||||
public void setGrayUnitRouteRule(
|
||||
GrayUnitRouteRule grayUnitRouteRule) {
|
||||
this.grayUnitRouteRule = grayUnitRouteRule;
|
||||
}
|
||||
|
||||
public RouterIdentifier getRouterIdentifier() {
|
||||
return routerIdentifier;
|
||||
}
|
||||
|
||||
public void setRouterIdentifier(
|
||||
RouterIdentifier routerIdentifier) {
|
||||
this.routerIdentifier = routerIdentifier;
|
||||
}
|
||||
}
|
||||
|
||||
public static class GrayUnitRouteRule {
|
||||
|
||||
private List<GrayUnitRoute> unitRoutes;
|
||||
|
||||
public List<GrayUnitRoute> getUnitRoutes() {
|
||||
return unitRoutes;
|
||||
}
|
||||
|
||||
public void setUnitRoutes(
|
||||
List<GrayUnitRoute> unitRoutes) {
|
||||
this.unitRoutes = unitRoutes;
|
||||
}
|
||||
}
|
||||
|
||||
public static class UnitRouteRule {
|
||||
private String id;
|
||||
|
||||
private String name;
|
||||
|
||||
private String desc;
|
||||
|
||||
private Boolean passingThroughEnabled;
|
||||
|
||||
private List<TagTransform> tagTransforms;
|
||||
|
||||
private List<UnitRoute> unitRoutes;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public void setDesc(String desc) {
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public Boolean getPassingThroughEnabled() {
|
||||
return passingThroughEnabled;
|
||||
}
|
||||
|
||||
public void setPassingThroughEnabled(Boolean passingThroughEnabled) {
|
||||
this.passingThroughEnabled = passingThroughEnabled;
|
||||
}
|
||||
|
||||
public List<TagTransform> getTagTransforms() {
|
||||
return tagTransforms;
|
||||
}
|
||||
|
||||
public void setTagTransforms(
|
||||
List<TagTransform> tagTransforms) {
|
||||
this.tagTransforms = tagTransforms;
|
||||
}
|
||||
|
||||
public List<UnitRoute> getUnitRoutes() {
|
||||
return unitRoutes;
|
||||
}
|
||||
|
||||
public void setUnitRoutes(List<UnitRoute> unitRoutes) {
|
||||
this.unitRoutes = unitRoutes;
|
||||
}
|
||||
}
|
||||
|
||||
public static class TagTransform {
|
||||
private TagTransformLocation source;
|
||||
|
||||
private TransformAction transform;
|
||||
|
||||
private TagTransformLocation destination;
|
||||
|
||||
public TagTransformLocation getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
public void setSource(TagTransformLocation source) {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public TransformAction getTransform() {
|
||||
return transform;
|
||||
}
|
||||
|
||||
public void setTransform(TransformAction transform) {
|
||||
this.transform = transform;
|
||||
}
|
||||
|
||||
public TagTransformLocation getDestination() {
|
||||
return destination;
|
||||
}
|
||||
|
||||
public void setDestination(TagTransformLocation destination) {
|
||||
this.destination = destination;
|
||||
}
|
||||
}
|
||||
|
||||
public static class TagTransformLocation {
|
||||
private String tagName;
|
||||
|
||||
public String getTagName() {
|
||||
return tagName;
|
||||
}
|
||||
|
||||
public void setTagName(String tagName) {
|
||||
this.tagName = tagName;
|
||||
}
|
||||
}
|
||||
|
||||
public static class TransformAction {
|
||||
private TransformAlgorithm algorithm;
|
||||
// 解析 algorithm 后放入的实际操作类
|
||||
@JsonIgnore
|
||||
private IUnitTransformAlgorithm unitTransformAlgorithm;
|
||||
|
||||
public TransformAlgorithm getAlgorithm() {
|
||||
return algorithm;
|
||||
}
|
||||
|
||||
public void setAlgorithm(TransformAlgorithm algorithm) {
|
||||
this.algorithm = algorithm;
|
||||
}
|
||||
|
||||
public IUnitTransformAlgorithm getUnitTransformAlgorithm() {
|
||||
return unitTransformAlgorithm;
|
||||
}
|
||||
|
||||
public void setUnitTransformAlgorithm(
|
||||
IUnitTransformAlgorithm unitTransformAlgorithm) {
|
||||
this.unitTransformAlgorithm = unitTransformAlgorithm;
|
||||
}
|
||||
}
|
||||
|
||||
public static class TransformAlgorithm {
|
||||
private String name;
|
||||
// algorithm 的操作算子,由 name 决定
|
||||
private Map<String, Object> options;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Map<String, Object> getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
public void setOptions(Map<String, Object> options) {
|
||||
this.options = options;
|
||||
}
|
||||
}
|
||||
|
||||
public static class GrayUnitRoute {
|
||||
private GrayUnitRouteMatch match;
|
||||
|
||||
private GrayMatchRoute route;
|
||||
|
||||
public GrayUnitRouteMatch getMatch() {
|
||||
return match;
|
||||
}
|
||||
|
||||
public void setMatch(GrayUnitRouteMatch match) {
|
||||
this.match = match;
|
||||
}
|
||||
|
||||
public GrayMatchRoute getRoute() {
|
||||
return route;
|
||||
}
|
||||
|
||||
public void setRoute(GrayMatchRoute route) {
|
||||
this.route = route;
|
||||
}
|
||||
}
|
||||
|
||||
public static class UnitRoute {
|
||||
private UnitRouteMatch match;
|
||||
|
||||
private MatchRoute route;
|
||||
|
||||
public UnitRouteMatch getMatch() {
|
||||
return match;
|
||||
}
|
||||
|
||||
public void setMatch(UnitRouteMatch match) {
|
||||
this.match = match;
|
||||
}
|
||||
|
||||
public MatchRoute getRoute() {
|
||||
return route;
|
||||
}
|
||||
|
||||
public void setRoute(MatchRoute route) {
|
||||
this.route = route;
|
||||
}
|
||||
}
|
||||
|
||||
public static class GrayUnitRouteMatch extends UnitRouteMatch {
|
||||
private Boolean grayListEnabled;
|
||||
|
||||
public Boolean getGrayListEnabled() {
|
||||
return grayListEnabled;
|
||||
}
|
||||
|
||||
public void setGrayListEnabled(Boolean grayListEnabled) {
|
||||
this.grayListEnabled = grayListEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
public static class UnitRouteMatch {
|
||||
private String name;
|
||||
|
||||
private String operator;
|
||||
|
||||
private List<UnitTag> conditions;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getOperator() {
|
||||
return operator;
|
||||
}
|
||||
|
||||
public void setOperator(String operator) {
|
||||
this.operator = operator;
|
||||
}
|
||||
|
||||
public List<UnitTag> getConditions() {
|
||||
return conditions;
|
||||
}
|
||||
|
||||
public void setConditions(List<UnitTag> conditions) {
|
||||
this.conditions = conditions;
|
||||
}
|
||||
}
|
||||
|
||||
public static class GrayMatchRoute {
|
||||
|
||||
private List<GrayMatchRouteUnit> units;
|
||||
|
||||
public List<GrayMatchRouteUnit> getUnits() {
|
||||
return units;
|
||||
}
|
||||
|
||||
public void setUnits(
|
||||
List<GrayMatchRouteUnit> units) {
|
||||
this.units = units;
|
||||
}
|
||||
}
|
||||
|
||||
public static class GrayMatchRouteUnit {
|
||||
private String id;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GrayMatchRouteUnit{" +
|
||||
"id='" + id + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
public static class MatchRoute {
|
||||
private String unitId;
|
||||
|
||||
private MatchRouteFailover failover;
|
||||
|
||||
public String getUnitId() {
|
||||
return unitId;
|
||||
}
|
||||
|
||||
public void setUnitId(String unitId) {
|
||||
this.unitId = unitId;
|
||||
}
|
||||
|
||||
public MatchRouteFailover getFailover() {
|
||||
return failover;
|
||||
}
|
||||
|
||||
public void setFailover(MatchRouteFailover failover) {
|
||||
this.failover = failover;
|
||||
}
|
||||
|
||||
public String getActualUnitId() {
|
||||
if (failover != null && failover.getEnabled()) {
|
||||
return failover.getRoute().getUnitId();
|
||||
}
|
||||
else {
|
||||
return unitId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class MatchRouteFailover {
|
||||
private Boolean enabled;
|
||||
|
||||
private FailoverRoute route;
|
||||
|
||||
private String scope;
|
||||
|
||||
public Boolean getEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(Boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public FailoverRoute getRoute() {
|
||||
return route;
|
||||
}
|
||||
|
||||
public void setRoute(FailoverRoute route) {
|
||||
this.route = route;
|
||||
}
|
||||
|
||||
public String getScope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
public void setScope(String scope) {
|
||||
this.scope = scope;
|
||||
}
|
||||
}
|
||||
|
||||
public static class FailoverRoute {
|
||||
private String unitId;
|
||||
|
||||
private FailoverRouteLocationFilter locationFilter;
|
||||
|
||||
public String getUnitId() {
|
||||
return unitId;
|
||||
}
|
||||
|
||||
public void setUnitId(String unitId) {
|
||||
this.unitId = unitId;
|
||||
}
|
||||
|
||||
public FailoverRouteLocationFilter getLocationFilter() {
|
||||
return locationFilter;
|
||||
}
|
||||
|
||||
public void setLocationFilter(FailoverRouteLocationFilter locationFilter) {
|
||||
this.locationFilter = locationFilter;
|
||||
}
|
||||
}
|
||||
|
||||
public static class FailoverRouteLocationFilter {
|
||||
private UnitRouteMatch zoneFilter;
|
||||
|
||||
public UnitRouteMatch getZoneFilter() {
|
||||
return zoneFilter;
|
||||
}
|
||||
|
||||
public void setZoneFilter(UnitRouteMatch zoneFilter) {
|
||||
this.zoneFilter = zoneFilter;
|
||||
}
|
||||
}
|
||||
|
||||
public static class RouterIdentifier {
|
||||
private String keySeparator;
|
||||
|
||||
private String keyValueSeparator;
|
||||
|
||||
private String shardingIdentifierKey;
|
||||
|
||||
private String routerIdentifierHeader;
|
||||
|
||||
private List<MappingService> shardingIdentifierMappingServices;
|
||||
|
||||
@JsonIgnore
|
||||
private Map<String, MappingService> mappingServiceMap;
|
||||
|
||||
public RouterIdentifier() {
|
||||
}
|
||||
|
||||
public RouterIdentifier(String keySeparator, String keyValueSeparator,
|
||||
String shardingIdentifierKey,
|
||||
String routerIdentifierHeader) {
|
||||
this.keySeparator = keySeparator;
|
||||
this.keyValueSeparator = keyValueSeparator;
|
||||
this.shardingIdentifierKey = shardingIdentifierKey;
|
||||
this.routerIdentifierHeader = routerIdentifierHeader;
|
||||
}
|
||||
|
||||
public String getKeySeparator() {
|
||||
return keySeparator;
|
||||
}
|
||||
|
||||
public void setKeySeparator(String keySeparator) {
|
||||
this.keySeparator = keySeparator;
|
||||
}
|
||||
|
||||
public String getKeyValueSeparator() {
|
||||
return keyValueSeparator;
|
||||
}
|
||||
|
||||
public void setKeyValueSeparator(String keyValueSeparator) {
|
||||
this.keyValueSeparator = keyValueSeparator;
|
||||
}
|
||||
|
||||
public String getShardingIdentifierKey() {
|
||||
return shardingIdentifierKey;
|
||||
}
|
||||
|
||||
public void setShardingIdentifierKey(String shardingIdentifierKey) {
|
||||
this.shardingIdentifierKey = shardingIdentifierKey;
|
||||
}
|
||||
|
||||
public String getRouterIdentifierHeader() {
|
||||
return routerIdentifierHeader;
|
||||
}
|
||||
|
||||
public void setRouterIdentifierHeader(String routerIdentifierHeader) {
|
||||
this.routerIdentifierHeader = routerIdentifierHeader;
|
||||
}
|
||||
|
||||
public List<MappingService> getShardingIdentifierMappingServices() {
|
||||
return shardingIdentifierMappingServices;
|
||||
}
|
||||
|
||||
public void setShardingIdentifierMappingServices(
|
||||
List<MappingService> shardingIdentifierMappingServices) {
|
||||
this.shardingIdentifierMappingServices = shardingIdentifierMappingServices;
|
||||
}
|
||||
|
||||
public Map<String, MappingService> getMappingServiceMap() {
|
||||
return mappingServiceMap;
|
||||
}
|
||||
|
||||
public void setMappingServiceMap(
|
||||
Map<String, MappingService> mappingServiceMap) {
|
||||
this.mappingServiceMap = mappingServiceMap;
|
||||
}
|
||||
}
|
||||
|
||||
public static class MappingService {
|
||||
private String cloudId;
|
||||
|
||||
private String apiPath;
|
||||
|
||||
public String getCloudId() {
|
||||
return cloudId;
|
||||
}
|
||||
|
||||
public void setCloudId(String cloudId) {
|
||||
this.cloudId = cloudId;
|
||||
}
|
||||
|
||||
public String getApiPath() {
|
||||
return apiPath;
|
||||
}
|
||||
|
||||
public void setApiPath(String apiPath) {
|
||||
this.apiPath = apiPath;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.tsf.unit.core.model;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
|
||||
public enum UnitTagPosition {
|
||||
|
||||
/**
|
||||
* HTTP HEADER.
|
||||
*/
|
||||
HEADER,
|
||||
/**
|
||||
* HTTP QUERY.
|
||||
*/
|
||||
QUERY,
|
||||
/**
|
||||
* HTTP COOKIE.
|
||||
*/
|
||||
COOKIE,
|
||||
/**
|
||||
* HTTP PATH.
|
||||
*/
|
||||
PATH,
|
||||
/**
|
||||
* TSF TAG.
|
||||
*/
|
||||
TSF_TAG;
|
||||
|
||||
@JsonCreator
|
||||
public static UnitTagPosition fromString(String key) {
|
||||
for (UnitTagPosition tagPosition : UnitTagPosition.values()) {
|
||||
if (tagPosition.name().equalsIgnoreCase(key)) {
|
||||
return tagPosition;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.tsf.unit.core.model;
|
||||
|
||||
public enum UnitType {
|
||||
/**
|
||||
* SDU.
|
||||
*/
|
||||
SDU,
|
||||
/**
|
||||
* GDU.
|
||||
*/
|
||||
GDU
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.tsf.unit.core.remote;
|
||||
|
||||
import com.ecwid.consul.v1.ConsulClient;
|
||||
import com.ecwid.consul.v1.QueryParams;
|
||||
import com.ecwid.consul.v1.Response;
|
||||
import com.ecwid.consul.v1.kv.model.GetValue;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
|
||||
import com.tencent.cloud.common.util.GzipUtil;
|
||||
import com.tencent.tsf.unit.core.Env;
|
||||
import com.tencent.tsf.unit.core.TencentUnitManager;
|
||||
import com.tencent.tsf.unit.core.model.UnitArch;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public final class TencentUnitArchKVLoader {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(TencentUnitArchKVLoader.class);
|
||||
/**
|
||||
* consul 长轮询等待时间.
|
||||
*/
|
||||
private final static Integer watchTime = 55;
|
||||
/**
|
||||
* 数据当前游标.
|
||||
*/
|
||||
private static Long index = -1L;
|
||||
private static String rawContent;
|
||||
|
||||
private TencentUnitArchKVLoader() {
|
||||
}
|
||||
|
||||
private static String getUnitArchKey() {
|
||||
return "unit/cloudArchitecture/data";
|
||||
}
|
||||
|
||||
public static void syncUnitArch() {
|
||||
String newContent = null;
|
||||
try {
|
||||
ConsulClient client = TsfUnitConsulManager.getConsulClient();
|
||||
|
||||
if (client == null) {
|
||||
LOGGER.warn("[syncUnitArch] tsf unit consul client is null");
|
||||
return;
|
||||
}
|
||||
|
||||
Response<GetValue> response = client.getKVValue(getUnitArchKey(),
|
||||
Env.getConsulToken(), new QueryParams(watchTime, index));
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("[syncUnitArch] resp:{}", response);
|
||||
}
|
||||
// data not change
|
||||
if (response.getConsulIndex() == null || index.equals(response.getConsulIndex())) {
|
||||
return;
|
||||
}
|
||||
index = response.getConsulIndex();
|
||||
// 推空保护,启动后理论上不存在单元化配置被删除的场景
|
||||
if (response.getValue() != null) {
|
||||
// 控制台 gzip 压缩加 base64 转换,这里进行解压
|
||||
newContent = GzipUtil.base64DecodeDecompress(response.getValue().getDecodedValue());
|
||||
loadUnitArch(newContent);
|
||||
}
|
||||
|
||||
}
|
||||
catch (Throwable t) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("[syncUnitArch] newContent:{} error:", newContent, t);
|
||||
}
|
||||
else {
|
||||
LOGGER.warn("[syncUnitArch] error: {}", t.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void loadUnitArch(String content) throws JsonProcessingException {
|
||||
LOGGER.info("[unit] unit arch config old raw content:\n{}", rawContent);
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
|
||||
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
TencentUnitManager.setUnitArch(mapper.readValue(content, UnitArch.class));
|
||||
|
||||
rawContent = content;
|
||||
LOGGER.info("[unit] unit arch config new raw content:\n{}", rawContent);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.tsf.unit.core.remote;
|
||||
|
||||
import com.ecwid.consul.v1.ConsulClient;
|
||||
import com.ecwid.consul.v1.QueryParams;
|
||||
import com.ecwid.consul.v1.Response;
|
||||
import com.ecwid.consul.v1.kv.model.GetValue;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
|
||||
import com.tencent.cloud.common.util.GzipUtil;
|
||||
import com.tencent.tsf.unit.core.Env;
|
||||
import com.tencent.tsf.unit.core.TencentUnitManager;
|
||||
import com.tencent.tsf.unit.core.model.UnitGray;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public final class TencentUnitGrayKVLoader {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(TencentUnitGrayKVLoader.class);
|
||||
/**
|
||||
* consul 长轮询等待时间.
|
||||
*/
|
||||
private final static Integer watchTime = 55;
|
||||
/**
|
||||
* 数据当前游标.
|
||||
*/
|
||||
private static Long index = -1L;
|
||||
private static String rawContent;
|
||||
|
||||
private TencentUnitGrayKVLoader() {
|
||||
}
|
||||
|
||||
private static String getUnitGrayKey() {
|
||||
return "unit/grayList/data";
|
||||
}
|
||||
|
||||
public static void syncUnitGray() {
|
||||
String newContent = null;
|
||||
try {
|
||||
ConsulClient client = TsfUnitConsulManager.getConsulClient();
|
||||
|
||||
if (client == null) {
|
||||
LOGGER.warn("[syncUnitGray] tsf unit consul client is null");
|
||||
return;
|
||||
}
|
||||
Response<GetValue> response = client.getKVValue(getUnitGrayKey(),
|
||||
Env.getConsulToken(), new QueryParams(watchTime, index));
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("[syncUnitGray] resp:{}", response);
|
||||
}
|
||||
// data not change
|
||||
if (response.getConsulIndex() == null || index.equals(response.getConsulIndex())) {
|
||||
return;
|
||||
}
|
||||
index = response.getConsulIndex();
|
||||
// 推空保护,启动后理论上不存在单元化配置被删除的场景
|
||||
if (response.getValue() != null) {
|
||||
// 控制台 gzip 压缩加 base64 转换,这里进行解压
|
||||
newContent = GzipUtil.base64DecodeDecompress(response.getValue().getDecodedValue());
|
||||
loadUnitGray(newContent);
|
||||
}
|
||||
}
|
||||
catch (Throwable t) {
|
||||
if (LOGGER.isTraceEnabled()) {
|
||||
LOGGER.trace("[syncUnitGray] newContent:{} error:", newContent, t);
|
||||
}
|
||||
else {
|
||||
LOGGER.warn("[syncUnitGray] error: {}", t.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void loadUnitGray(String content) throws JsonProcessingException {
|
||||
LOGGER.info("[unit] unit gray old raw content:\n{}", rawContent);
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
|
||||
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
TencentUnitManager.setUnitGray(mapper.readValue(content, UnitGray.class));
|
||||
|
||||
rawContent = content;
|
||||
LOGGER.info("[unit] unit gray new raw content:\n{}", rawContent);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.tsf.unit.core.remote;
|
||||
|
||||
import com.ecwid.consul.v1.ConsulClient;
|
||||
import com.ecwid.consul.v1.QueryParams;
|
||||
import com.ecwid.consul.v1.Response;
|
||||
import com.ecwid.consul.v1.kv.model.GetValue;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
|
||||
import com.tencent.cloud.common.util.GzipUtil;
|
||||
import com.tencent.tsf.unit.core.Env;
|
||||
import com.tencent.tsf.unit.core.TencentUnitManager;
|
||||
import com.tencent.tsf.unit.core.model.UnitRouteInfo;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public final class TencentUnitRouteRuleKVLoader {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(TencentUnitRouteRuleKVLoader.class);
|
||||
/**
|
||||
* consul 长轮询等待时间.
|
||||
*/
|
||||
private final static Integer watchTime = 55;
|
||||
/**
|
||||
* 数据当前游标.
|
||||
*/
|
||||
private static Long index = -1L;
|
||||
private static String rawContent;
|
||||
|
||||
private TencentUnitRouteRuleKVLoader() {
|
||||
}
|
||||
|
||||
private static String getUnitRouteRuleKey() {
|
||||
return "unit/routeRule/data";
|
||||
}
|
||||
|
||||
public static void syncUnitRouteRule() {
|
||||
String newContent = null;
|
||||
try {
|
||||
ConsulClient client = TsfUnitConsulManager.getConsulClient();
|
||||
|
||||
if (client == null) {
|
||||
LOGGER.warn("[syncUnitRouteRule] tsf unit consul client is null");
|
||||
return;
|
||||
}
|
||||
Response<GetValue> response = client.getKVValue(getUnitRouteRuleKey(),
|
||||
Env.getConsulToken(), new QueryParams(watchTime, index));
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("[syncUnitRouteRule] resp:{}", response);
|
||||
}
|
||||
// data not change
|
||||
if (response.getConsulIndex() == null || index.equals(response.getConsulIndex())) {
|
||||
return;
|
||||
}
|
||||
index = response.getConsulIndex();
|
||||
// 推空保护,启动后理论上不存在单元化配置被删除的场景
|
||||
if (response.getValue() != null) {
|
||||
// 控制台 gzip 压缩加 base64 转换,这里进行解压
|
||||
newContent = GzipUtil.base64DecodeDecompress(response.getValue().getDecodedValue());
|
||||
loadUnitRouteRule(newContent);
|
||||
}
|
||||
}
|
||||
catch (Throwable t) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("[syncUnitRouteRule] newContent:{} error:", newContent, t);
|
||||
}
|
||||
else {
|
||||
LOGGER.warn("[syncUnitRouteRule] error: {}", t.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void loadUnitRouteRule(String content) throws JsonProcessingException {
|
||||
LOGGER.info("[unit] unit route rule old raw content:\n{}", rawContent);
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
|
||||
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
TencentUnitManager.setUnitRouteRule(mapper.readValue(content, UnitRouteInfo.class));
|
||||
|
||||
rawContent = content;
|
||||
LOGGER.info("[unit] unit route rule new raw content:\n{}", rawContent);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.tsf.unit.core.remote;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import com.ecwid.consul.v1.ConsulClient;
|
||||
import com.tencent.polaris.api.utils.IPAddressUtils;
|
||||
import com.tencent.tsf.unit.core.Env;
|
||||
|
||||
public final class TsfUnitConsulManager {
|
||||
|
||||
protected static final AtomicInteger POOL_SEQ = new AtomicInteger(1);
|
||||
|
||||
// 只需要 3 个长轮训
|
||||
private final static ScheduledExecutorService executorService = Executors.newScheduledThreadPool(3, new ThreadFactory() {
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread t = new Thread(r);
|
||||
t.setName("tsf-unit-consul-" + POOL_SEQ.getAndIncrement());
|
||||
t.setDaemon(true); // 设置为守护线程
|
||||
return t;
|
||||
}
|
||||
});
|
||||
private static ConsulClient consulClient = null;
|
||||
|
||||
private static volatile boolean init = false;
|
||||
|
||||
private TsfUnitConsulManager() {
|
||||
}
|
||||
|
||||
public static synchronized void init() {
|
||||
if (!init) {
|
||||
init = true;
|
||||
consulClient = new ConsulClient(IPAddressUtils.getIpCompatible(Env.getConsulHost()), Env.getConsulPort());
|
||||
|
||||
// 初始化先同步拉取一次
|
||||
TencentUnitArchKVLoader.syncUnitArch();
|
||||
TencentUnitRouteRuleKVLoader.syncUnitRouteRule();
|
||||
TencentUnitGrayKVLoader.syncUnitGray();
|
||||
// 启动长轮训定时任务
|
||||
executorService.scheduleAtFixedRate(TencentUnitArchKVLoader::syncUnitArch, 55, 1, TimeUnit.SECONDS);
|
||||
executorService.scheduleAtFixedRate(TencentUnitRouteRuleKVLoader::syncUnitRouteRule, 55, 1, TimeUnit.SECONDS);
|
||||
executorService.scheduleAtFixedRate(TencentUnitGrayKVLoader::syncUnitGray, 55, 1, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
public static ConsulClient getConsulClient() {
|
||||
return consulClient;
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
com.tencent.cloud.plugin.unit.config.GatewayUnitAutoConfiguration
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 Tencent. 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.plugin.unit.config;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
public class UnitAutoConfigurationTest {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(UnitAutoConfiguration.class))
|
||||
.withPropertyValues(
|
||||
"tsf_consul_ip=localhost"
|
||||
);
|
||||
|
||||
@Test
|
||||
void shouldCreateBeansWhenConditionsMet() {
|
||||
contextRunner.run(context -> {
|
||||
assertThat(context).hasSingleBean(UnitBeanPostProcessor.class);
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Reference in new issue