feat:support dynamic multi-discovery. (#1595)
Co-authored-by: Haotian Zhang <skyebefreeman@qq.com>pull/1598/head
parent
8527891414
commit
587b5f7708
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
*
|
||||
* Licensed under the BSD 3-Clause License (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed
|
||||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
package com.tencent.cloud.common.tsf;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.context.annotation.Condition;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
|
||||
/**
|
||||
* Condition that if Only TSF Consul enabled.
|
||||
*
|
||||
* @author Haotian Zhang
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Conditional(ConditionalOnOnlyTsfConsulEnabled.OnTsfEnabledCondition.class)
|
||||
public @interface ConditionalOnOnlyTsfConsulEnabled {
|
||||
|
||||
class OnTsfEnabledCondition implements Condition {
|
||||
|
||||
@Override
|
||||
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
|
||||
return TsfContextUtils.isOnlyTsfConsulEnabled(conditionContext.getEnvironment());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
*
|
||||
* Licensed under the BSD 3-Clause License (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed
|
||||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
package com.tencent.cloud.common.tsf;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import com.tencent.polaris.api.utils.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
/**
|
||||
* Utils for TSF.
|
||||
*
|
||||
* @author Haotian Zhang
|
||||
*/
|
||||
public final class TsfContextUtils {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(TsfContextUtils.class);
|
||||
|
||||
private static final AtomicBoolean isTsfConsulEnabledFirstConfiguration = new AtomicBoolean(true);
|
||||
|
||||
private static final AtomicBoolean isOnlyTsfConsulEnabledFirstConfiguration = new AtomicBoolean(true);
|
||||
|
||||
private static boolean tsfConsulEnabled = false;
|
||||
|
||||
private static boolean onlyTsfConsulEnabled = false;
|
||||
|
||||
private TsfContextUtils() {
|
||||
}
|
||||
|
||||
public static boolean isTsfConsulEnabled(Environment environment) {
|
||||
if (environment != null && isTsfConsulEnabledFirstConfiguration.compareAndSet(true, false)) {
|
||||
if (isOnlyTsfConsulEnabled(environment)) {
|
||||
tsfConsulEnabled = true;
|
||||
}
|
||||
else {
|
||||
boolean consulEnabled = Boolean.parseBoolean(environment.getProperty("tsf_consul_enable", "true"));
|
||||
String tsfConsulIp = environment.getProperty("tsf_consul_ip");
|
||||
tsfConsulEnabled = consulEnabled && StringUtils.isNotBlank(tsfConsulIp);
|
||||
if (tsfConsulEnabled) {
|
||||
LOG.info("Tsf Consul is enabled: {}", tsfConsulIp);
|
||||
}
|
||||
}
|
||||
}
|
||||
return tsfConsulEnabled;
|
||||
}
|
||||
|
||||
public static boolean isOnlyTsfConsulEnabled(Environment environment) {
|
||||
if (environment != null && isOnlyTsfConsulEnabledFirstConfiguration.compareAndSet(true, false)) {
|
||||
boolean consulEnabled = Boolean.parseBoolean(environment.getProperty("tsf_consul_enable", "true"));
|
||||
String tsfConsulIp = environment.getProperty("tsf_consul_ip");
|
||||
String polarisAddress = environment.getProperty("polaris_address");
|
||||
if (StringUtils.isBlank(polarisAddress) && StringUtils.isNotBlank(environment.getProperty("spring.cloud.polaris.address"))) {
|
||||
polarisAddress = environment.getProperty("spring.cloud.polaris.address");
|
||||
}
|
||||
onlyTsfConsulEnabled = consulEnabled && StringUtils.isNotBlank(tsfConsulIp) && StringUtils.isBlank(polarisAddress);
|
||||
if (onlyTsfConsulEnabled) {
|
||||
LOG.info("Only Tsf Consul is enabled: {}", tsfConsulIp);
|
||||
}
|
||||
}
|
||||
return onlyTsfConsulEnabled;
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
<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/maven-v4_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-starter-tencent-multi-discovery-plugin</artifactId>
|
||||
<name>Spring Cloud Tencent Trace Plugin</name>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.tencent.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-tencent-polaris-discovery</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.tencent.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-tencent-polaris-config</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
*
|
||||
* Licensed under the BSD 3-Clause License (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed
|
||||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
package com.tencent.cloud.plugin.discovery.multi.config;
|
||||
|
||||
import com.tencent.cloud.plugin.discovery.multi.listeners.ConsulDiscoveryConfigChangeListener;
|
||||
import com.tencent.cloud.polaris.registry.PolarisRegistration;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* Auto configuration for multi discovery.
|
||||
*
|
||||
* @author Haotian Zhang
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
public class MultiDiscoveryAutoConfiguration {
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnProperty(value = "spring.cloud.consul.enabled", havingValue = "true")
|
||||
protected static class ConsulMultiDiscoveryConfig {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ConsulDiscoveryConfigChangeListener consulDiscoveryConfigChangeListener(PolarisRegistration polarisRegistration) {
|
||||
return new ConsulDiscoveryConfigChangeListener(polarisRegistration);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
*
|
||||
* Licensed under the BSD 3-Clause License (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed
|
||||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
package com.tencent.cloud.plugin.discovery.multi.listeners;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import com.tencent.cloud.polaris.config.annotation.PolarisConfigKVFileChangeListener;
|
||||
import com.tencent.cloud.polaris.config.listener.ConfigChangeEvent;
|
||||
import com.tencent.cloud.polaris.registry.PolarisRegistration;
|
||||
import com.tencent.polaris.api.plugin.common.PluginTypes;
|
||||
import com.tencent.polaris.api.plugin.server.ServerConnector;
|
||||
import com.tencent.polaris.api.rpc.InstanceRegisterRequest;
|
||||
import com.tencent.polaris.api.utils.StringUtils;
|
||||
import com.tencent.polaris.client.api.SDKContext;
|
||||
import com.tencent.polaris.discovery.client.flow.RegisterStateManager;
|
||||
import com.tencent.polaris.plugins.connector.common.DestroyableServerConnector;
|
||||
import com.tencent.polaris.plugins.connector.composite.CompositeConnector;
|
||||
import com.tencent.polaris.plugins.connector.consul.ConsulAPIConnector;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Consul Discovery Config Listener .
|
||||
*
|
||||
* @author Haotian Zhang
|
||||
*/
|
||||
public final class ConsulDiscoveryConfigChangeListener {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ConsulDiscoveryConfigChangeListener.class);
|
||||
|
||||
private final PolarisRegistration polarisRegistration;
|
||||
|
||||
private final SDKContext sdkContext;
|
||||
private final ConsulAPIConnector consulAPIConnector;
|
||||
private InstanceRegisterRequest instanceRegisterRequest;
|
||||
|
||||
public ConsulDiscoveryConfigChangeListener(PolarisRegistration polarisRegistration) {
|
||||
this.polarisRegistration = polarisRegistration;
|
||||
this.sdkContext = polarisRegistration.getPolarisContext();
|
||||
|
||||
ServerConnector connector = (ServerConnector) sdkContext.getPlugins()
|
||||
.getPlugin(PluginTypes.SERVER_CONNECTOR.getBaseType(), sdkContext.getValueContext()
|
||||
.getServerConnectorProtocol());
|
||||
ConsulAPIConnector temp = null;
|
||||
if (connector instanceof CompositeConnector) {
|
||||
CompositeConnector compositeConnector = (CompositeConnector) connector;
|
||||
for (DestroyableServerConnector sc : compositeConnector.getServerConnectors()) {
|
||||
if (sc instanceof ConsulAPIConnector) {
|
||||
temp = (ConsulAPIConnector) sc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (connector instanceof ConsulAPIConnector) {
|
||||
temp = (ConsulAPIConnector) connector;
|
||||
}
|
||||
this.consulAPIConnector = temp;
|
||||
}
|
||||
|
||||
@PolarisConfigKVFileChangeListener(interestedKeyPrefixes = "spring.cloud.consul.discovery")
|
||||
public void onChange(ConfigChangeEvent event) {
|
||||
if (consulAPIConnector != null) {
|
||||
initInstanceRegisterRequest();
|
||||
|
||||
Set<String> changedKeys = event.changedKeys();
|
||||
for (String changedKey : changedKeys) {
|
||||
if (StringUtils.equals(changedKey, "spring.cloud.consul.discovery.enabled")) {
|
||||
LOG.info("{} = {}", changedKey, event.getChange(changedKey));
|
||||
boolean discoveryEnabled = !StringUtils.equals("false", event.getChange(changedKey).getNewValue()
|
||||
.toString());
|
||||
consulAPIConnector.setDiscoveryEnable(discoveryEnabled);
|
||||
}
|
||||
else if (StringUtils.equals(changedKey, "spring.cloud.consul.discovery.register")) {
|
||||
LOG.info("{} = {}", changedKey, event.getChange(changedKey));
|
||||
boolean registerEnabled = !StringUtils.equals("false", event.getChange(changedKey).getNewValue()
|
||||
.toString());
|
||||
if (registerEnabled) {
|
||||
consulAPIConnector.registerInstance(RegisterStateManager.getRegisterState(sdkContext, instanceRegisterRequest)
|
||||
.getInstanceRegisterRequest().getRequest(), null);
|
||||
}
|
||||
else {
|
||||
consulAPIConnector.deregisterInstance(RegisterStateManager.getRegisterState(sdkContext, instanceRegisterRequest)
|
||||
.getInstanceRegisterRequest().getRequest());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void initInstanceRegisterRequest() {
|
||||
if (instanceRegisterRequest == null) {
|
||||
this.instanceRegisterRequest = new InstanceRegisterRequest();
|
||||
instanceRegisterRequest.setNamespace(polarisRegistration.getNamespace());
|
||||
instanceRegisterRequest.setService(polarisRegistration.getServiceId());
|
||||
instanceRegisterRequest.setHost(polarisRegistration.getHost());
|
||||
instanceRegisterRequest.setPort(polarisRegistration.getPort());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
com.tencent.cloud.plugin.discovery.multi.config.MultiDiscoveryAutoConfiguration
|
@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
*
|
||||
* Licensed under the BSD 3-Clause License (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed
|
||||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
package com.tencent.cloud.polaris.context.config.extend.tsf;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import com.tencent.polaris.api.utils.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
/**
|
||||
* Utils for TSF.
|
||||
*
|
||||
* @author Haotian Zhang
|
||||
*/
|
||||
public final class TsfContextUtils {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(TsfContextUtils.class);
|
||||
|
||||
private static final AtomicBoolean isFirstConfiguration = new AtomicBoolean(true);
|
||||
|
||||
private static boolean tsfConsulEnabled = false;
|
||||
|
||||
private TsfContextUtils() {
|
||||
}
|
||||
|
||||
public static boolean isTsfConsulEnabled(Environment environment) {
|
||||
if (environment != null && isFirstConfiguration.compareAndSet(true, false)) {
|
||||
String tsfConsulIp = environment.getProperty("tsf_consul_ip");
|
||||
String tsePolarisAddress = environment.getProperty("polaris_address");
|
||||
if (StringUtils.isBlank(tsePolarisAddress) && StringUtils.isNotBlank(environment.getProperty("spring.cloud.polaris.address"))) {
|
||||
tsePolarisAddress = environment.getProperty("spring.cloud.polaris.address");
|
||||
}
|
||||
tsfConsulEnabled = StringUtils.isNotBlank(tsfConsulIp) && StringUtils.isBlank(tsePolarisAddress);
|
||||
if (tsfConsulEnabled) {
|
||||
LOG.info("Tsf Consul is enabled: {}", tsfConsulIp);
|
||||
}
|
||||
}
|
||||
return tsfConsulEnabled;
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||
*
|
||||
* Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
*
|
||||
* Licensed under the BSD 3-Clause License (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed
|
||||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
package com.tencent.cloud.polaris.context.config.extend.tsf;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.tencent.cloud.common.tsf.TsfContextUtils;
|
||||
import com.tencent.polaris.api.utils.StringUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor;
|
||||
import org.springframework.boot.env.EnvironmentPostProcessor;
|
||||
import org.springframework.boot.logging.DeferredLogFactory;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
|
||||
/**
|
||||
* Read TSF env.
|
||||
*
|
||||
* @author Haotian Zhang
|
||||
*/
|
||||
public final class TsfLastEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
|
||||
|
||||
/**
|
||||
* run before {@link ConfigDataEnvironmentPostProcessor}.
|
||||
*/
|
||||
public static final int ORDER = ConfigDataEnvironmentPostProcessor.ORDER + 1;
|
||||
|
||||
private final Log LOGGER;
|
||||
|
||||
private TsfLastEnvironmentPostProcessor(DeferredLogFactory logFactory) {
|
||||
this.LOGGER = logFactory.getLog(getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return ORDER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
|
||||
String tsfAppId = environment.getProperty("tsf_app_id");
|
||||
// TSF deploy
|
||||
if (StringUtils.isNotBlank(tsfAppId)) {
|
||||
Map<String, Object> defaultProperties = new HashMap<>();
|
||||
|
||||
if (TsfContextUtils.isTsfConsulEnabled(environment)) {
|
||||
defaultProperties.put("spring.cloud.consul.discovery.enabled", environment.getProperty("spring.cloud.consul.discovery.enabled", "true"));
|
||||
defaultProperties.put("spring.cloud.consul.discovery.register", environment.getProperty("spring.cloud.consul.discovery.register", "true"));
|
||||
}
|
||||
|
||||
MapPropertySource tsfLastPropertySource = new MapPropertySource("tsf-last-properties", defaultProperties);
|
||||
environment.getPropertySources().addLast(tsfLastPropertySource);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in new issue