add config refresh type switch & catch exception for traffic staining (#469)

* add config refresh type switch & catch exception for traffic staning

* add change log
pull/472/head
lepdou 2 years ago committed by GitHub
parent 7036f908e1
commit 7699ed16f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -20,3 +20,4 @@
- [Feature: Add router actuate endpoint](https://github.com/Tencent/spring-cloud-tencent/pull/464)
- [feat:rename the configuration of reporter.](https://github.com/Tencent/spring-cloud-tencent/pull/465)
- [docs:update mvnw.](https://github.com/Tencent/spring-cloud-tencent/pull/466)
- [Feature: add config refresh type switch & catch exception for traffic staining.](https://github.com/Tencent/spring-cloud-tencent/pull/469)

@ -35,6 +35,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
import org.springframework.cloud.context.properties.ConfigurationPropertiesBeans;
import org.springframework.cloud.context.properties.ConfigurationPropertiesRebinder;
import org.springframework.cloud.context.refresh.ContextRefresher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -53,9 +54,10 @@ public class PolarisConfigAutoConfiguration {
PolarisConfigProperties polarisConfigProperties,
PolarisPropertySourceManager polarisPropertySourceManager,
SpringValueRegistry springValueRegistry,
PlaceholderHelper placeholderHelper) {
PlaceholderHelper placeholderHelper,
ContextRefresher contextRefresher) {
return new PolarisPropertySourceAutoRefresher(polarisConfigProperties,
polarisPropertySourceManager, springValueRegistry, placeholderHelper);
polarisPropertySourceManager, springValueRegistry, placeholderHelper, contextRefresher);
}
@Bean

@ -25,6 +25,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
import com.tencent.cloud.common.util.JacksonUtils;
import com.tencent.cloud.polaris.config.config.PolarisConfigProperties;
import com.tencent.cloud.polaris.config.enums.RefreshType;
import com.tencent.cloud.polaris.config.spring.property.PlaceholderHelper;
import com.tencent.cloud.polaris.config.spring.property.SpringValue;
import com.tencent.cloud.polaris.config.spring.property.SpringValueRegistry;
@ -40,6 +41,7 @@ import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
import org.springframework.cloud.context.refresh.ContextRefresher;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
@ -61,6 +63,8 @@ public class PolarisPropertySourceAutoRefresher
private final PolarisPropertySourceManager polarisPropertySourceManager;
private final ContextRefresher contextRefresher;
private final AtomicBoolean registered = new AtomicBoolean(false);
private ConfigurableApplicationContext context;
@ -70,16 +74,17 @@ public class PolarisPropertySourceAutoRefresher
private ConfigurableBeanFactory beanFactory;
private final PlaceholderHelper placeholderHelper;
public PolarisPropertySourceAutoRefresher(
PolarisConfigProperties polarisConfigProperties,
PolarisPropertySourceManager polarisPropertySourceManager,
SpringValueRegistry springValueRegistry,
PlaceholderHelper placeholderHelper) {
PlaceholderHelper placeholderHelper,
ContextRefresher contextRefresher) {
this.polarisConfigProperties = polarisConfigProperties;
this.polarisPropertySourceManager = polarisPropertySourceManager;
this.springValueRegistry = springValueRegistry;
this.placeholderHelper = placeholderHelper;
this.contextRefresher = contextRefresher;
}
@Override
@ -138,17 +143,25 @@ public class PolarisPropertySourceAutoRefresher
break;
}
Collection<SpringValue> targetValues = springValueRegistry.get(beanFactory, changedKey);
if (targetValues == null || targetValues.isEmpty()) {
continue;
}
// update the value
for (SpringValue val : targetValues) {
updateSpringValue(val);
if (polarisConfigProperties.getRefreshType() == RefreshType.REFLECT) {
Collection<SpringValue> targetValues = springValueRegistry.get(beanFactory, changedKey);
if (targetValues == null || targetValues.isEmpty()) {
continue;
}
// update the attribute with @Value annotation
for (SpringValue val : targetValues) {
updateSpringValue(val);
}
}
}
if (polarisConfigProperties.getRefreshType() == RefreshType.REFLECT) {
// update @ConfigurationProperties beans
context.publishEvent(new EnvironmentChangeEvent(context, configKVFileChangeEvent.changedKeys()));
}
else {
contextRefresher.refresh();
}
context.publishEvent(new EnvironmentChangeEvent(context, configKVFileChangeEvent.changedKeys()));
});
}
}

@ -19,6 +19,8 @@ package com.tencent.cloud.polaris.config.config;
import java.util.List;
import com.tencent.cloud.polaris.config.enums.RefreshType;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
@ -50,6 +52,11 @@ public class PolarisConfigProperties {
*/
private boolean autoRefresh = true;
/**
* Attribute refresh type.
*/
private RefreshType refreshType = RefreshType.REFRESH_CONTEXT;
/**
* List of injected configuration files.
*/
@ -87,6 +94,14 @@ public class PolarisConfigProperties {
this.autoRefresh = autoRefresh;
}
public RefreshType getRefreshType() {
return refreshType;
}
public void setRefreshType(RefreshType refreshType) {
this.refreshType = refreshType;
}
public List<ConfigFileGroup> getGroups() {
return groups;
}

@ -0,0 +1,34 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
*/
package com.tencent.cloud.polaris.config.enums;
/**
* Attribute refresh type when config updated.
* @author lepdou 2022-07-26
*/
public enum RefreshType {
/**
* refresh spring context.
*/
REFRESH_CONTEXT,
/**
* Dynamically refresh a bean's properties via reflection calls.
*/
REFLECT
}

@ -47,6 +47,12 @@
"type": "com.tencent.cloud.polaris.config.enums.RefreshBehavior",
"defaultValue": "all_beans",
"description": "ConfigurationPropertiesBean refresh behavior."
},
{
"name": "spring.cloud.polaris.config.refresh-type",
"type": "com.tencent.cloud.polaris.config.enums.RefreshType",
"defaultValue": "refresh_context",
"description": "Attribute refresh type when config updated. refresh_context or reflect."
}
]
}

@ -26,6 +26,7 @@ import java.util.Map;
import com.google.common.collect.Lists;
import com.tencent.cloud.polaris.config.config.PolarisConfigProperties;
import com.tencent.cloud.polaris.config.enums.RefreshType;
import com.tencent.cloud.polaris.config.spring.property.PlaceholderHelper;
import com.tencent.cloud.polaris.config.spring.property.SpringValue;
import com.tencent.cloud.polaris.config.spring.property.SpringValueRegistry;
@ -74,8 +75,9 @@ public class PolarisPropertiesSourceAutoRefresherTest {
@Test
public void testConfigFileChanged() throws Exception {
PolarisPropertySourceAutoRefresher refresher = new PolarisPropertySourceAutoRefresher(polarisConfigProperties,
polarisPropertySourceManager, springValueRegistry, placeholderHelper);
polarisPropertySourceManager, springValueRegistry, placeholderHelper, contextRefresher);
when(polarisConfigProperties.getRefreshType()).thenReturn(RefreshType.REFLECT);
ConfigurableApplicationContext applicationContext = mock(ConfigurableApplicationContext.class);
ConfigurableListableBeanFactory beanFactory = mock(ConfigurableListableBeanFactory.class);
TypeConverter typeConverter = mock(TypeConverter.class);

@ -64,5 +64,6 @@ spring:
logging:
level:
com.tencent.cloud.plugin.gateway: debug
org.springframework.cloud.gateway: info
com.tencent.cloud.polaris: debug

@ -3,7 +3,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>polaris-router-featureenv-base</artifactId>
<artifactId>base</artifactId>
<groupId>com.tencent.cloud</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>

@ -3,7 +3,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>polaris-router-featureenv-base</artifactId>
<artifactId>base</artifactId>
<groupId>com.tencent.cloud</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>

@ -3,7 +3,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>polaris-router-featureenv-base</artifactId>
<artifactId>base</artifactId>
<groupId>com.tencent.cloud</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>

@ -10,7 +10,7 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>polaris-router-featureenv-base</artifactId>
<artifactId>base</artifactId>
<packaging>pom</packaging>
<modules>

@ -26,6 +26,9 @@ import java.util.Map;
import com.tencent.cloud.common.constant.MetadataConstant;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.util.JacksonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Mono;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
@ -43,6 +46,8 @@ import static org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter.R
*/
public class TrafficStainingGatewayFilter implements GlobalFilter, Ordered {
private static final Logger LOGGER = LoggerFactory.getLogger(TrafficStainingGatewayFilter.class);
private final List<TrafficStainer> trafficStainers;
public TrafficStainingGatewayFilter(List<TrafficStainer> trafficStainers) {
@ -87,13 +92,23 @@ public class TrafficStainingGatewayFilter implements GlobalFilter, Ordered {
Map<String, String> getStainedLabels(ServerWebExchange exchange) {
Map<String, String> stainedLabels = new HashMap<>();
int size = trafficStainers.size();
TrafficStainer stainer = null;
for (int i = size - 1; i >= 0; i--) {
TrafficStainer stainer = trafficStainers.get(i);
Map<String, String> labels = stainer.apply(exchange);
if (!CollectionUtils.isEmpty(labels)) {
stainedLabels.putAll(labels);
try {
stainer = trafficStainers.get(i);
Map<String, String> labels = stainer.apply(exchange);
if (!CollectionUtils.isEmpty(labels)) {
stainedLabels.putAll(labels);
}
}
catch (Exception e) {
if (stainer != null) {
LOGGER.error("[SCT] traffic stained error. stainer = {}", stainer.getClass().getName(), e);
}
}
}
LOGGER.debug("[SCT] traffic stained labels. {}", JacksonUtils.serialize2Json(stainedLabels));
return stainedLabels;
}

@ -9,7 +9,7 @@
{
"name": "spring.cloud.tencent.plugin.scg.staining.enabled",
"type": "java.lang.Boolean",
"defaultValue": true,
"defaultValue": false,
"description": "the switch for spring cloud gateway staining plugin."
},
{

Loading…
Cancel
Save