diff --git a/CHANGELOG.md b/CHANGELOG.md
index 06c1f8175..7cc73b071 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
# Change Log
---
-
+[UT: Add config module unit test](https://github.com/Tencent/spring-cloud-tencent/pull/229)
+[Feature: Add config change listener feature support](https://github.com/Tencent/spring-cloud-tencent/pull/220)
+[Feature: Support spring cloud gateway routers](https://github.com/Tencent/spring-cloud-tencent/pull/230)
+[Feature: Add instance metadata spi for registration](https://github.com/Tencent/spring-cloud-tencent/pull/244)
+[Bugfix: fix guava version conflict bug & fix router strong dependency on LoadBalancerClientFilter](https://github.com/Tencent/spring-cloud-tencent/pull/236)
diff --git a/pom.xml b/pom.xml
index 4268d2385..d6d0cc37a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -38,9 +38,11 @@
- spring-cloud-tencent-polaris-context
spring-cloud-tencent-commons
+ spring-cloud-tencent-polaris-context
+ spring-cloud-tencent-polaris-loadbalancer
spring-cloud-starter-tencent-metadata-transfer
+ spring-cloud-starter-tencent-polaris-config
spring-cloud-starter-tencent-polaris-discovery
spring-cloud-starter-tencent-polaris-ratelimit
spring-cloud-starter-tencent-polaris-circuitbreaker
@@ -48,8 +50,6 @@
spring-cloud-tencent-dependencies
spring-cloud-tencent-examples
spring-cloud-tencent-coverage
- spring-cloud-starter-tencent-polaris-config
- spring-cloud-tencent-polaris-loadbalancer
diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/intercepter/EncodeTransferMedataFeignInterceptorTest.java b/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/intercepter/EncodeTransferMedataFeignInterceptorTest.java
index 406d078e3..9d8c7ea3f 100644
--- a/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/intercepter/EncodeTransferMedataFeignInterceptorTest.java
+++ b/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/intercepter/EncodeTransferMedataFeignInterceptorTest.java
@@ -19,9 +19,10 @@
package com.tencent.cloud.metadata.core.intercepter;
import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
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.metadata.config.MetadataLocalProperties;
import com.tencent.cloud.metadata.core.EncodeTransferMedataFeignInterceptor;
import feign.RequestInterceptor;
@@ -64,10 +65,9 @@ public class EncodeTransferMedataFeignInterceptorTest {
private TestApplication.TestFeign testFeign;
@Test
- public void test1() {
+ public void testTransitiveMetadataFromApplicationConfig() {
String metadata = testFeign.test();
- Assertions.assertThat(metadata)
- .isEqualTo("{\"b\":\"2\"}");
+ Assertions.assertThat(metadata).isEqualTo("2");
Assertions.assertThat(metadataLocalProperties.getContent().get("a"))
.isEqualTo("1");
Assertions.assertThat(metadataLocalProperties.getContent().get("b"))
@@ -83,16 +83,13 @@ public class EncodeTransferMedataFeignInterceptorTest {
public String test(
@RequestHeader(MetadataConstant.HeaderName.CUSTOM_METADATA) String customMetadataStr)
throws UnsupportedEncodingException {
- return URLDecoder.decode(customMetadataStr, "UTF-8");
+ return MetadataContextHolder.get().getContext(MetadataContext.FRAGMENT_TRANSITIVE, "b");
}
@FeignClient(name = "test-feign", url = "http://localhost:8081")
public interface TestFeign {
- @RequestMapping(value = "/test",
- headers = {"X-SCT-Metadata-Transitive-a=11",
- "X-SCT-Metadata-Transitive-b=22",
- "X-SCT-Metadata-Transitive-c=33"})
+ @RequestMapping("/test")
String test();
}
diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/intercepter/EncodeTransferMedataRestTemplateInterceptorTest.java b/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/intercepter/EncodeTransferMedataRestTemplateInterceptorTest.java
index 183333c26..10626e5a6 100644
--- a/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/intercepter/EncodeTransferMedataRestTemplateInterceptorTest.java
+++ b/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/intercepter/EncodeTransferMedataRestTemplateInterceptorTest.java
@@ -19,11 +19,12 @@
package com.tencent.cloud.metadata.core.intercepter;
import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
import com.tencent.cloud.common.constant.MetadataConstant;
-import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
+import com.tencent.cloud.common.metadata.MetadataContext;
+import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.metadata.core.EncodeTransferMedataRestTemplateInterceptor;
+import org.assertj.core.api.Assertions;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -32,6 +33,9 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.context.annotation.Bean;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -51,9 +55,6 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
properties = { "spring.config.location = classpath:application-test.yml", "spring.main.web-application-type = reactive" })
public class EncodeTransferMedataRestTemplateInterceptorTest {
- @Autowired
- private MetadataLocalProperties metadataLocalProperties;
-
@Autowired
private RestTemplate restTemplate;
@@ -61,30 +62,14 @@ public class EncodeTransferMedataRestTemplateInterceptorTest {
private int localServerPort;
@Test
- public void test1() {
-// HttpHeaders httpHeaders = new HttpHeaders();
-// httpHeaders.set(MetadataConstant.HeaderName.CUSTOM_METADATA,
-// "{\"a\":\"11\",\"b\":\"22\",\"c\":\"33\"}");
-// HttpEntity httpEntity = new HttpEntity<>(httpHeaders);
-// String metadata = restTemplate
-// .exchange("http://localhost:" + localServerPort + "/test", HttpMethod.GET,
-// httpEntity, String.class)
-// .getBody();
-// Assertions.assertThat(metadata)
-// .isEqualTo("{\"a\":\"11\",\"b\":\"22\",\"c\":\"33\"}");
-// Assertions.assertThat(metadataLocalProperties.getContent().get("a"))
-// .isEqualTo("1");
-// Assertions.assertThat(metadataLocalProperties.getContent().get("b"))
-// .isEqualTo("2");
-// Assertions
-// .assertThat(MetadataContextHolder.get().getContext(MetadataContext.FRAGMENT_TRANSITIVE, "a"))
-// .isEqualTo("11");
-// Assertions
-// .assertThat(MetadataContextHolder.get().getContext(MetadataContext.FRAGMENT_TRANSITIVE, "b"))
-// .isEqualTo("22");
-// Assertions
-// .assertThat(MetadataContextHolder.get().getContext(MetadataContext.FRAGMENT_TRANSITIVE, "c"))
-// .isEqualTo("33");
+ public void testTransitiveMetadataFromApplicationConfig() {
+ HttpHeaders httpHeaders = new HttpHeaders();
+ HttpEntity httpEntity = new HttpEntity<>(httpHeaders);
+ String metadata = restTemplate
+ .exchange("http://localhost:" + localServerPort + "/test", HttpMethod.GET,
+ httpEntity, String.class)
+ .getBody();
+ Assertions.assertThat(metadata).isEqualTo("2");
}
@SpringBootApplication
@@ -100,7 +85,7 @@ public class EncodeTransferMedataRestTemplateInterceptorTest {
public String test(
@RequestHeader(MetadataConstant.HeaderName.CUSTOM_METADATA) String customMetadataStr)
throws UnsupportedEncodingException {
- return URLDecoder.decode(customMetadataStr, "UTF-8");
+ return MetadataContextHolder.get().getContext(MetadataContext.FRAGMENT_TRANSITIVE, "b");
}
}
diff --git a/spring-cloud-starter-tencent-polaris-config/pom.xml b/spring-cloud-starter-tencent-polaris-config/pom.xml
index 10b362a67..a7f0e5894 100644
--- a/spring-cloud-starter-tencent-polaris-config/pom.xml
+++ b/spring-cloud-starter-tencent-polaris-config/pom.xml
@@ -11,6 +11,7 @@
4.0.0
spring-cloud-starter-tencent-polaris-config
+ Spring Cloud Starter Tencent Polaris Config
@@ -64,5 +65,28 @@
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ org.mockito
+ mockito-inline
+ test
+
+
+
+ org.mockito
+ mockito-core
+ test
+
+
+
+ net.bytebuddy
+ byte-buddy
+ test
+
diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/ConditionalOnConnectRemoteServerEnabled.java b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/ConditionalOnConnectRemoteServerEnabled.java
new file mode 100644
index 000000000..89283ae18
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/ConditionalOnConnectRemoteServerEnabled.java
@@ -0,0 +1,37 @@
+/*
+ * 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;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+
+/**
+ * Whether to connect to a remote server, suitable for local development mode.
+ *
+ * @author lepdou 2022-06-11
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.TYPE, ElementType.METHOD })
+@ConditionalOnProperty(value = "spring.cloud.polaris.config.connect-remote-server", matchIfMissing = true)
+public @interface ConditionalOnConnectRemoteServerEnabled {
+
+}
diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/PolarisConfigBootstrapAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/PolarisConfigBootstrapAutoConfiguration.java
index 1a7e05ac9..101ca4a35 100644
--- a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/PolarisConfigBootstrapAutoConfiguration.java
+++ b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/PolarisConfigBootstrapAutoConfiguration.java
@@ -51,16 +51,18 @@ public class PolarisConfigBootstrapAutoConfiguration {
}
@Bean
- public ConfigFileService configFileService(SDKContext sdkContext) {
- return ConfigFileServiceFactory.createConfigFileService(sdkContext);
+ public PolarisPropertySourceManager polarisPropertySourceManager() {
+ return new PolarisPropertySourceManager();
}
@Bean
- public PolarisPropertySourceManager polarisPropertySourceManager() {
- return new PolarisPropertySourceManager();
+ @ConditionalOnConnectRemoteServerEnabled
+ public ConfigFileService configFileService(SDKContext sdkContext) {
+ return ConfigFileServiceFactory.createConfigFileService(sdkContext);
}
@Bean
+ @ConditionalOnConnectRemoteServerEnabled
public PolarisConfigFileLocator polarisConfigFileLocator(
PolarisConfigProperties polarisConfigProperties,
PolarisContextProperties polarisContextProperties,
@@ -73,6 +75,7 @@ public class PolarisConfigBootstrapAutoConfiguration {
}
@Bean
+ @ConditionalOnConnectRemoteServerEnabled
public ConfigurationModifier configurationModifier(PolarisConfigProperties polarisConfigProperties,
PolarisContextProperties polarisContextProperties) {
return new ConfigurationModifier(polarisConfigProperties, polarisContextProperties);
diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigFileLocator.java b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigFileLocator.java
index cad31d1de..240eb4cc0 100644
--- a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigFileLocator.java
+++ b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigFileLocator.java
@@ -84,13 +84,14 @@ public class PolarisConfigFileLocator implements PropertySourceLocator {
CompositePropertySource compositePropertySource = new CompositePropertySource(
POLARIS_CONFIG_PROPERTY_SOURCE_NAME);
+ // load spring boot default config files
+ initInternalConfigFiles(compositePropertySource);
+
+ // load custom config files
List configFileGroups = polarisConfigProperties.getGroups();
if (CollectionUtils.isEmpty(configFileGroups)) {
return compositePropertySource;
}
-
- initInternalConfigFiles(compositePropertySource);
-
initCustomPolarisConfigFiles(compositePropertySource, configFileGroups);
return compositePropertySource;
@@ -190,12 +191,10 @@ public class PolarisConfigFileLocator implements PropertySourceLocator {
// unknown extension is resolved as properties file
if (ConfigFileFormat.isPropertyFile(fileName)
|| ConfigFileFormat.isUnknownFile(fileName)) {
- configKVFile = configFileService.getConfigPropertiesFile(namespace, group,
- fileName);
+ configKVFile = configFileService.getConfigPropertiesFile(namespace, group, fileName);
}
else if (ConfigFileFormat.isYamlFile(fileName)) {
- configKVFile = configFileService.getConfigYamlFile(namespace, group,
- fileName);
+ configKVFile = configFileService.getConfigYamlFile(namespace, group, fileName);
}
else {
LOGGER.warn(
diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-starter-tencent-polaris-config/src/main/resources/META-INF/additional-spring-configuration-metadata.json
index ee84cbd47..9954a62ce 100644
--- a/spring-cloud-starter-tencent-polaris-config/src/main/resources/META-INF/additional-spring-configuration-metadata.json
+++ b/spring-cloud-starter-tencent-polaris-config/src/main/resources/META-INF/additional-spring-configuration-metadata.json
@@ -34,6 +34,13 @@
"defaultValue": "",
"description": "List of imported config files.",
"sourceType": "com.tencent.cloud.polaris.config.config.PolarisConfigProperties"
+ },
+ {
+ "name": "spring.cloud.polaris.config.connect-remote-server",
+ "type": "java.lang.Boolean",
+ "defaultValue": "true",
+ "description": "Whether to connect to a remote server, suitable for local development mode.",
+ "sourceType": "com.tencent.cloud.polaris.config.config.PolarisConfigProperties"
}
]
}
diff --git a/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/adapter/MockedConfigKVFile.java b/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/adapter/MockedConfigKVFile.java
new file mode 100644
index 000000000..026fe4d52
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/adapter/MockedConfigKVFile.java
@@ -0,0 +1,170 @@
+/*
+ * 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.adapter;
+
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.tencent.polaris.configuration.api.core.ConfigFileChangeListener;
+import com.tencent.polaris.configuration.api.core.ConfigKVFile;
+import com.tencent.polaris.configuration.api.core.ConfigKVFileChangeEvent;
+import com.tencent.polaris.configuration.api.core.ConfigKVFileChangeListener;
+
+/**
+ * Mock config kv file for test.
+ *@author lepdou 2022-06-11
+ */
+public class MockedConfigKVFile implements ConfigKVFile {
+
+ private final Map properties;
+ private final List listeners = new ArrayList<>();
+
+ public MockedConfigKVFile(Map properties) {
+ this.properties = properties;
+ }
+
+ @Override
+ public String getProperty(String s, String s1) {
+ return String.valueOf(properties.get(s));
+ }
+
+ @Override
+ public Integer getIntProperty(String s, Integer integer) {
+ return null;
+ }
+
+ @Override
+ public Long getLongProperty(String s, Long aLong) {
+ return null;
+ }
+
+ @Override
+ public Short getShortProperty(String s, Short aShort) {
+ return null;
+ }
+
+ @Override
+ public Float getFloatProperty(String s, Float aFloat) {
+ return null;
+ }
+
+ @Override
+ public Double getDoubleProperty(String s, Double aDouble) {
+ return null;
+ }
+
+ @Override
+ public Byte getByteProperty(String s, Byte aByte) {
+ return null;
+ }
+
+ @Override
+ public Boolean getBooleanProperty(String s, Boolean aBoolean) {
+ return null;
+ }
+
+ @Override
+ public String[] getArrayProperty(String s, String s1, String[] strings) {
+ return new String[0];
+ }
+
+ @Override
+ public > T getEnumProperty(String s, Class aClass, T t) {
+ return null;
+ }
+
+ @Override
+ public T getJsonProperty(String s, Class aClass, T t) {
+ return null;
+ }
+
+ @Override
+ public T getJsonProperty(String s, Type type, T t) {
+ return null;
+ }
+
+ @Override
+ public Set getPropertyNames() {
+ return properties.keySet();
+ }
+
+ @Override
+ public void addChangeListener(ConfigKVFileChangeListener configKVFileChangeListener) {
+ listeners.add(configKVFileChangeListener);
+ }
+
+ @Override
+ public void removeChangeListener(ConfigKVFileChangeListener configKVFileChangeListener) {
+
+ }
+
+ @Override
+ public String getContent() {
+ return null;
+ }
+
+ @Override
+ public T asJson(Class aClass, T t) {
+ return null;
+ }
+
+ @Override
+ public T asJson(Type type, T t) {
+ return null;
+ }
+
+ @Override
+ public boolean hasContent() {
+ return false;
+ }
+
+ @Override
+ public void addChangeListener(ConfigFileChangeListener configFileChangeListener) {
+
+ }
+
+ @Override
+ public void removeChangeListener(ConfigFileChangeListener configFileChangeListener) {
+
+ }
+
+ public void fireChangeListener(ConfigKVFileChangeEvent event) {
+ for (ConfigKVFileChangeListener listener : listeners) {
+ listener.onChange(event);
+ }
+ }
+
+ @Override
+ public String getNamespace() {
+ return null;
+ }
+
+ @Override
+ public String getFileGroup() {
+ return null;
+ }
+
+ @Override
+ public String getFileName() {
+ return null;
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigFileLocatorTest.java b/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigFileLocatorTest.java
new file mode 100644
index 000000000..6fe0bfa2a
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigFileLocatorTest.java
@@ -0,0 +1,188 @@
+/*
+ * 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.adapter;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import com.google.common.collect.Lists;
+import com.tencent.cloud.polaris.config.config.ConfigFileGroup;
+import com.tencent.cloud.polaris.config.config.PolarisConfigProperties;
+import com.tencent.cloud.polaris.context.PolarisContextProperties;
+import com.tencent.polaris.configuration.api.core.ConfigFileService;
+import com.tencent.polaris.configuration.api.core.ConfigKVFile;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import org.springframework.core.env.Environment;
+import org.springframework.core.env.PropertySource;
+
+import static org.mockito.Mockito.when;
+
+/**
+ * test for {@link PolarisConfigFileLocator}
+ *@author lepdou 2022-06-11
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class PolarisConfigFileLocatorTest {
+
+ @Mock
+ private PolarisConfigProperties polarisConfigProperties;
+ @Mock
+ private PolarisContextProperties polarisContextProperties;
+ @Mock
+ private ConfigFileService configFileService;
+ @Mock
+ private PolarisPropertySourceManager polarisPropertySourceManager;
+ @Mock
+ private Environment environment;
+
+ private final String testNamespace = "testNamespace";
+ private final String testServiceName = "testServiceName";
+
+ @Test
+ public void testLoadApplicationPropertiesFile() {
+ PolarisConfigFileLocator locator = new PolarisConfigFileLocator(polarisConfigProperties, polarisContextProperties,
+ configFileService, polarisPropertySourceManager, environment);
+
+ when(polarisContextProperties.getNamespace()).thenReturn(testNamespace);
+ when(polarisContextProperties.getService()).thenReturn(testServiceName);
+
+ // application.properties
+ Map applicationProperties = new HashMap<>();
+ applicationProperties.put("k1", "v1");
+ applicationProperties.put("k2", "v2");
+ applicationProperties.put("k3", "v3");
+ ConfigKVFile propertiesFile = new MockedConfigKVFile(applicationProperties);
+ when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "application.properties"))
+ .thenReturn(propertiesFile);
+
+ Map emptyMap = new HashMap<>();
+ ConfigKVFile emptyConfigFile = new MockedConfigKVFile(emptyMap);
+ when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "application.yml")).thenReturn(emptyConfigFile);
+ when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "bootstrap.properties")).thenReturn(emptyConfigFile);
+ when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "bootstrap.yml")).thenReturn(emptyConfigFile);
+
+ when(polarisConfigProperties.getGroups()).thenReturn(null);
+ when(environment.getActiveProfiles()).thenReturn(new String[] {});
+
+ PropertySource> propertySource = locator.locate(environment);
+
+ Assert.assertEquals("v1", propertySource.getProperty("k1"));
+ Assert.assertEquals("v2", propertySource.getProperty("k2"));
+ Assert.assertEquals("v3", propertySource.getProperty("k3"));
+ }
+
+ @Test
+ public void testActiveProfileFilesPriorityBiggerThanDefault() {
+ PolarisConfigFileLocator locator = new PolarisConfigFileLocator(polarisConfigProperties, polarisContextProperties,
+ configFileService, polarisPropertySourceManager, environment);
+
+ when(polarisContextProperties.getNamespace()).thenReturn(testNamespace);
+ when(polarisContextProperties.getService()).thenReturn(testServiceName);
+
+ // application.properties
+ Map applicationProperties = new HashMap<>();
+ applicationProperties.put("k1", "v1");
+ applicationProperties.put("k2", "v2");
+ applicationProperties.put("k3", "v3");
+ ConfigKVFile propertiesFile = new MockedConfigKVFile(applicationProperties);
+ when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "application.properties"))
+ .thenReturn(propertiesFile);
+
+ // application-dev.properties
+ Map devProperties = new HashMap<>();
+ devProperties.put("k1", "v11");
+ ConfigKVFile devFile = new MockedConfigKVFile(devProperties);
+ when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "application-dev.properties"))
+ .thenReturn(devFile);
+
+ Map emptyMap = new HashMap<>();
+ ConfigKVFile emptyConfigFile = new MockedConfigKVFile(emptyMap);
+ when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "application.yml")).thenReturn(emptyConfigFile);
+ when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "application-dev.yml")).thenReturn(emptyConfigFile);
+ when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "bootstrap.properties")).thenReturn(emptyConfigFile);
+ when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "bootstrap-dev.properties")).thenReturn(emptyConfigFile);
+ when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "bootstrap.yml")).thenReturn(emptyConfigFile);
+ when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "bootstrap-dev.yml")).thenReturn(emptyConfigFile);
+
+ when(polarisConfigProperties.getGroups()).thenReturn(null);
+ when(environment.getActiveProfiles()).thenReturn(new String[] {"dev"});
+
+ PropertySource> propertySource = locator.locate(environment);
+
+ Assert.assertEquals("v11", propertySource.getProperty("k1"));
+ Assert.assertEquals("v2", propertySource.getProperty("k2"));
+ Assert.assertEquals("v3", propertySource.getProperty("k3"));
+ }
+
+ @Test
+ public void testGetCustomFiles() {
+ PolarisConfigFileLocator locator = new PolarisConfigFileLocator(polarisConfigProperties, polarisContextProperties,
+ configFileService, polarisPropertySourceManager, environment);
+
+ when(polarisContextProperties.getNamespace()).thenReturn(testNamespace);
+ when(polarisContextProperties.getService()).thenReturn(testServiceName);
+
+ Map emptyMap = new HashMap<>();
+ ConfigKVFile emptyConfigFile = new MockedConfigKVFile(emptyMap);
+
+ when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "application.properties")).thenReturn(emptyConfigFile);
+ when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "application.yml")).thenReturn(emptyConfigFile);
+ when(configFileService.getConfigPropertiesFile(testNamespace, testServiceName, "bootstrap.properties")).thenReturn(emptyConfigFile);
+ when(configFileService.getConfigYamlFile(testNamespace, testServiceName, "bootstrap.yml")).thenReturn(emptyConfigFile);
+
+ List customFiles = new LinkedList<>();
+ ConfigFileGroup configFileGroup = new ConfigFileGroup();
+ String customGroup = "group1";
+ configFileGroup.setName(customGroup);
+ String customFile1 = "file1.properties";
+ String customFile2 = "file2.properties";
+ configFileGroup.setFiles(Lists.newArrayList(customFile1, customFile2));
+ customFiles.add(configFileGroup);
+
+ when(polarisConfigProperties.getGroups()).thenReturn(customFiles);
+ when(environment.getActiveProfiles()).thenReturn(new String[] {});
+
+ // file1.properties
+ Map file1Map = new HashMap<>();
+ file1Map.put("k1", "v1");
+ file1Map.put("k2", "v2");
+ ConfigKVFile file1 = new MockedConfigKVFile(file1Map);
+ when(configFileService.getConfigPropertiesFile(testNamespace, customGroup, customFile1)).thenReturn(file1);
+
+ // file2.properties
+ Map file2Map = new HashMap<>();
+ file2Map.put("k1", "v11");
+ file2Map.put("k3", "v3");
+ ConfigKVFile file2 = new MockedConfigKVFile(file2Map);
+ when(configFileService.getConfigPropertiesFile(testNamespace, customGroup, customFile2)).thenReturn(file2);
+
+ PropertySource> propertySource = locator.locate(environment);
+
+ Assert.assertEquals("v1", propertySource.getProperty("k1"));
+ Assert.assertEquals("v2", propertySource.getProperty("k2"));
+ Assert.assertEquals("v3", propertySource.getProperty("k3"));
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/adapter/PolarisPropertiesSourceAutoRefresherTest.java b/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/adapter/PolarisPropertiesSourceAutoRefresherTest.java
new file mode 100644
index 000000000..648860f35
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/adapter/PolarisPropertiesSourceAutoRefresherTest.java
@@ -0,0 +1,122 @@
+/*
+ * 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.adapter;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.google.common.collect.Lists;
+import com.tencent.cloud.polaris.config.config.PolarisConfigProperties;
+import com.tencent.polaris.configuration.api.core.ChangeType;
+import com.tencent.polaris.configuration.api.core.ConfigKVFileChangeEvent;
+import com.tencent.polaris.configuration.api.core.ConfigPropertyChangeInfo;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import org.springframework.cloud.context.refresh.ContextRefresher;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * test for {@link PolarisPropertySourceAutoRefresher}
+ *@author lepdou 2022-06-11
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class PolarisPropertiesSourceAutoRefresherTest {
+
+ @Mock
+ private PolarisConfigProperties polarisConfigProperties;
+ @Mock
+ private PolarisPropertySourceManager polarisPropertySourceManager;
+ @Mock
+ private ContextRefresher contextRefresher;
+
+ private final String testNamespace = "testNamespace";
+ private final String testServiceName = "testServiceName";
+ private final String testFileName = "application.properties";
+
+ @Test
+ public void testConfigFileChanged() {
+ PolarisPropertySourceAutoRefresher refresher = new PolarisPropertySourceAutoRefresher(polarisConfigProperties,
+ polarisPropertySourceManager, contextRefresher);
+
+ when(polarisConfigProperties.isAutoRefresh()).thenReturn(true);
+
+ Map content = new HashMap<>();
+ content.put("k1", "v1");
+ content.put("k2", "v2");
+ content.put("k3", "v3");
+ MockedConfigKVFile file = new MockedConfigKVFile(content);
+ PolarisPropertySource polarisPropertySource = new PolarisPropertySource(testNamespace, testServiceName, testFileName,
+ file, content);
+
+ when(polarisPropertySourceManager.getAllPropertySources()).thenReturn(Lists.newArrayList(polarisPropertySource));
+
+ ConfigPropertyChangeInfo changeInfo = new ConfigPropertyChangeInfo("k1", "v1", "v11", ChangeType.MODIFIED);
+ ConfigPropertyChangeInfo changeInfo2 = new ConfigPropertyChangeInfo("k4", null, "v4", ChangeType.ADDED);
+ ConfigPropertyChangeInfo changeInfo3 = new ConfigPropertyChangeInfo("k2", "v2", null, ChangeType.DELETED);
+ Map changeInfos = new HashMap<>();
+ changeInfos.put("k1", changeInfo);
+ changeInfos.put("k2", changeInfo3);
+ changeInfos.put("k4", changeInfo2);
+
+ ConfigKVFileChangeEvent event = new ConfigKVFileChangeEvent(changeInfos);
+ refresher.onApplicationEvent(null);
+
+ file.fireChangeListener(event);
+
+ Assert.assertEquals("v11", polarisPropertySource.getProperty("k1"));
+ Assert.assertEquals("v3", polarisPropertySource.getProperty("k3"));
+ Assert.assertNull(polarisPropertySource.getProperty("k2"));
+ Assert.assertEquals("v4", polarisPropertySource.getProperty("k4"));
+ verify(contextRefresher).refresh();
+ }
+
+ @Test
+ public void testNewConfigFile() {
+ PolarisPropertySourceAutoRefresher refresher = new PolarisPropertySourceAutoRefresher(polarisConfigProperties,
+ polarisPropertySourceManager, contextRefresher);
+
+ when(polarisConfigProperties.isAutoRefresh()).thenReturn(true);
+
+ Map emptyContent = new HashMap<>();
+ MockedConfigKVFile file = new MockedConfigKVFile(emptyContent);
+ PolarisPropertySource polarisPropertySource = new PolarisPropertySource(testNamespace, testServiceName, testFileName,
+ file, emptyContent);
+
+ when(polarisPropertySourceManager.getAllPropertySources()).thenReturn(Lists.newArrayList(polarisPropertySource));
+
+ ConfigPropertyChangeInfo changeInfo = new ConfigPropertyChangeInfo("k1", null, "v1", ChangeType.ADDED);
+ Map changeInfos = new HashMap<>();
+ changeInfos.put("k1", changeInfo);
+
+ ConfigKVFileChangeEvent event = new ConfigKVFileChangeEvent(changeInfos);
+ refresher.onApplicationEvent(null);
+
+ file.fireChangeListener(event);
+
+ Assert.assertEquals("v1", polarisPropertySource.getProperty("k1"));
+ verify(contextRefresher).refresh();
+ }
+
+}
diff --git a/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/listener/ConfigChangeListenerTest.java b/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/listener/ConfigChangeListenerTest.java
new file mode 100644
index 000000000..f3f70b4bc
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/listener/ConfigChangeListenerTest.java
@@ -0,0 +1,124 @@
+/*
+ * 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.listener;
+
+import com.google.common.collect.Sets;
+import com.tencent.cloud.polaris.config.annotation.PolarisConfigKVFileChangeListener;
+import com.tencent.polaris.configuration.api.core.ConfigPropertyChangeInfo;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.stereotype.Component;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.DEFINED_PORT;
+
+/**
+ * Integration testing for change listener.
+ *@author lepdou 2022-06-11
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment = DEFINED_PORT,
+ classes = ConfigChangeListenerTest.TestApplication.class,
+ properties = {"server.port=8081",
+ "spring.config.location = classpath:application-test.yml"})
+public class ConfigChangeListenerTest {
+
+ @Autowired
+ private ApplicationEventPublisher applicationEventPublisher;
+ @Autowired
+ private ConfigurableApplicationContext applicationContext;
+ @Autowired
+ private TestApplication.TestConfig testConfig;
+
+ @Test
+ public void test() throws InterruptedException {
+ //before change
+ Assert.assertEquals(1000, testConfig.getTimeout());
+
+ //submit change event
+ System.setProperty("timeout", "2000");
+ EnvironmentChangeEvent event = new EnvironmentChangeEvent(applicationContext,
+ Sets.newHashSet("timeout"));
+
+ applicationEventPublisher.publishEvent(event);
+
+ //after change
+ Assert.assertEquals(2, testConfig.getChangeCnt());
+ Assert.assertEquals(2000, testConfig.getTimeout());
+ }
+
+
+ @SpringBootApplication
+ protected static class TestApplication {
+
+ @Component
+ protected static class TestConfig {
+
+ @Value("${timeout:1000}")
+ private int timeout;
+
+ private int changeCnt;
+
+ public int getTimeout() {
+ return timeout;
+ }
+
+ public void setTimeout(int timeout) {
+ this.timeout = timeout;
+ }
+
+ public int getChangeCnt() {
+ return changeCnt;
+ }
+
+ @PolarisConfigKVFileChangeListener(interestedKeys = {"timeout"})
+ public void configChangedListener(ConfigChangeEvent event) {
+ ConfigPropertyChangeInfo changeInfo = event.getChange("timeout");
+ timeout = Integer.parseInt(changeInfo.getNewValue());
+ changeCnt++;
+ }
+
+ @PolarisConfigKVFileChangeListener(interestedKeyPrefixes = {"timeout"})
+ public void configChangedListener2(ConfigChangeEvent event) {
+ ConfigPropertyChangeInfo changeInfo = event.getChange("timeout");
+ timeout = Integer.parseInt(changeInfo.getNewValue());
+ changeCnt++;
+ }
+ }
+
+ @Component
+ protected static class EventPublisher implements ApplicationEventPublisher {
+
+ @Override
+ public void publishEvent(Object o) {
+
+ }
+ }
+ }
+
+}
diff --git a/spring-cloud-starter-tencent-polaris-config/src/test/resources/application-test.yml b/spring-cloud-starter-tencent-polaris-config/src/test/resources/application-test.yml
new file mode 100644
index 000000000..c90d1340b
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-config/src/test/resources/application-test.yml
@@ -0,0 +1,9 @@
+spring:
+ application:
+ name: test
+ cloud:
+ polaris:
+ address: grpc://127.0.0.1:8091
+ namespace: default
+ config:
+ connect-remote-server: false
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisRegistration.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisRegistration.java
index bf83ee293..20cfcf6ed 100644
--- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisRegistration.java
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisRegistration.java
@@ -19,12 +19,14 @@
package com.tencent.cloud.polaris.registry;
import java.net.URI;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import com.tencent.cloud.common.metadata.StaticMetadataManager;
import com.tencent.cloud.polaris.DiscoveryPropertiesAutoConfiguration;
import com.tencent.cloud.polaris.PolarisDiscoveryProperties;
+import com.tencent.cloud.polaris.context.spi.InstanceMetadataProvider;
import com.tencent.polaris.client.api.SDKContext;
import org.apache.commons.lang.StringUtils;
@@ -40,6 +42,9 @@ import org.springframework.util.CollectionUtils;
*/
public class PolarisRegistration implements Registration, ServiceInstance {
+ private final static String METADATA_KEY_IP = "internal-ip";
+ private final static String METADATA_KEY_ADDRESS = "internal-address";
+
private final DiscoveryPropertiesAutoConfiguration discoveryPropertiesAutoConfiguration;
private final PolarisDiscoveryProperties polarisDiscoveryProperties;
@@ -48,15 +53,24 @@ public class PolarisRegistration implements Registration, ServiceInstance {
private final StaticMetadataManager staticMetadataManager;
+ private final InstanceMetadataProvider instanceMetadataProvider;
+
private Map metadata;
+ private final String host;
+
public PolarisRegistration(
DiscoveryPropertiesAutoConfiguration discoveryPropertiesAutoConfiguration,
- PolarisDiscoveryProperties polarisDiscoveryProperties, SDKContext context, StaticMetadataManager staticMetadataManager) {
+ PolarisDiscoveryProperties polarisDiscoveryProperties, SDKContext context,
+ StaticMetadataManager staticMetadataManager,
+ InstanceMetadataProvider instanceMetadataProvider) {
this.discoveryPropertiesAutoConfiguration = discoveryPropertiesAutoConfiguration;
this.polarisDiscoveryProperties = polarisDiscoveryProperties;
this.polarisContext = context;
this.staticMetadataManager = staticMetadataManager;
+ this.instanceMetadataProvider = instanceMetadataProvider;
+
+ host = polarisContext.getConfig().getGlobal().getAPI().getBindIP();
}
@Override
@@ -66,7 +80,7 @@ public class PolarisRegistration implements Registration, ServiceInstance {
@Override
public String getHost() {
- return polarisContext.getConfig().getGlobal().getAPI().getBindIP();
+ return host;
}
@Override
@@ -92,10 +106,35 @@ public class PolarisRegistration implements Registration, ServiceInstance {
@Override
public Map getMetadata() {
if (CollectionUtils.isEmpty(metadata)) {
- metadata = new HashMap<>();
- metadata.putAll(staticMetadataManager.getMergedStaticMetadata());
+ Map instanceMetadata = new HashMap<>();
+
+ // put internal metadata
+ instanceMetadata.put(METADATA_KEY_IP, host);
+ instanceMetadata.put(METADATA_KEY_ADDRESS, host + ":" + polarisDiscoveryProperties.getPort());
+
+ instanceMetadata.putAll(staticMetadataManager.getMergedStaticMetadata());
+
// location info will be putted both in metadata and instance's field
- metadata.putAll(staticMetadataManager.getLocationMetadata());
+ instanceMetadata.putAll(staticMetadataManager.getLocationMetadata());
+
+ // custom metadata from spi
+ if (instanceMetadataProvider != null) {
+ if (StringUtils.isNotBlank(instanceMetadataProvider.getRegion())) {
+ instanceMetadata.put(StaticMetadataManager.LOCATION_KEY_ZONE, instanceMetadataProvider.getRegion());
+ }
+ if (StringUtils.isNotBlank(instanceMetadataProvider.getZone())) {
+ instanceMetadata.put(StaticMetadataManager.LOCATION_KEY_ZONE, instanceMetadataProvider.getZone());
+ }
+ if (StringUtils.isNotBlank(instanceMetadataProvider.getCampus())) {
+ instanceMetadata.put(StaticMetadataManager.LOCATION_KEY_ZONE, instanceMetadataProvider.getCampus());
+ }
+
+ if (!CollectionUtils.isEmpty(instanceMetadataProvider.getMetadata())) {
+ instanceMetadata.putAll(instanceMetadataProvider.getMetadata());
+ }
+ }
+
+ this.metadata = Collections.unmodifiableMap(instanceMetadata);
}
return metadata;
}
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistryAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistryAutoConfiguration.java
index 5eadee573..e868996d5 100644
--- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistryAutoConfiguration.java
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistryAutoConfiguration.java
@@ -21,6 +21,7 @@ package com.tencent.cloud.polaris.registry;
import com.tencent.cloud.common.metadata.StaticMetadataManager;
import com.tencent.cloud.polaris.DiscoveryPropertiesAutoConfiguration;
import com.tencent.cloud.polaris.PolarisDiscoveryProperties;
+import com.tencent.cloud.polaris.context.spi.InstanceMetadataProvider;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryAutoConfiguration;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler;
import com.tencent.polaris.client.api.SDKContext;
@@ -34,6 +35,7 @@ import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationC
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.lang.Nullable;
/**
* Autoconfiguration of service registry of Polaris.
@@ -62,9 +64,9 @@ public class PolarisServiceRegistryAutoConfiguration {
public PolarisRegistration polarisRegistration(
DiscoveryPropertiesAutoConfiguration discoveryPropertiesAutoConfiguration,
PolarisDiscoveryProperties polarisDiscoveryProperties, SDKContext context,
- StaticMetadataManager staticMetadataManager) {
+ StaticMetadataManager staticMetadataManager, @Nullable InstanceMetadataProvider instanceMetadataProvider) {
return new PolarisRegistration(discoveryPropertiesAutoConfiguration,
- polarisDiscoveryProperties, context, staticMetadataManager);
+ polarisDiscoveryProperties, context, staticMetadataManager, instanceMetadataProvider);
}
@Bean
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/registry/PolarisRegistrationTest.java b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/registry/PolarisRegistrationTest.java
index a81d69d2a..11d380a75 100644
--- a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/registry/PolarisRegistrationTest.java
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/registry/PolarisRegistrationTest.java
@@ -78,7 +78,7 @@ public class PolarisRegistrationTest {
doReturn(Collections.singletonMap("key2", "value2")).when(staticMetadataManager).getLocationMetadata();
polarisRegistration = new PolarisRegistration(
- discoveryPropertiesAutoConfiguration, polarisDiscoveryProperties, polarisContext, staticMetadataManager);
+ discoveryPropertiesAutoConfiguration, polarisDiscoveryProperties, polarisContext, staticMetadataManager, null);
}
@Test
@@ -111,7 +111,7 @@ public class PolarisRegistrationTest {
Map metadata = polarisRegistration.getMetadata();
assertThat(metadata).isNotNull();
assertThat(metadata).isNotEmpty();
- assertThat(metadata.size()).isEqualTo(2);
+ assertThat(metadata.size()).isEqualTo(4);
assertThat(metadata.get("key1")).isEqualTo("value1");
assertThat(metadata.get("key2")).isEqualTo("value2");
}
diff --git a/spring-cloud-starter-tencent-polaris-router/pom.xml b/spring-cloud-starter-tencent-polaris-router/pom.xml
index 91e482abb..1424f98b5 100644
--- a/spring-cloud-starter-tencent-polaris-router/pom.xml
+++ b/spring-cloud-starter-tencent-polaris-router/pom.xml
@@ -52,6 +52,12 @@
true
+
+ org.springframework.cloud
+ spring-cloud-gateway-server
+ true
+
+
org.springframework.boot
spring-boot-starter-test
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisLoadBalancerCompositeRule.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisLoadBalancerCompositeRule.java
index 4b9dc5900..4be83e682 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisLoadBalancerCompositeRule.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisLoadBalancerCompositeRule.java
@@ -40,9 +40,9 @@ import com.tencent.cloud.common.pojo.PolarisServer;
import com.tencent.cloud.polaris.loadbalancer.LoadBalancerUtils;
import com.tencent.cloud.polaris.loadbalancer.PolarisWeightedRule;
import com.tencent.cloud.polaris.loadbalancer.config.PolarisLoadBalancerProperties;
-import com.tencent.cloud.polaris.router.config.PolarisMetadataRouterProperties;
-import com.tencent.cloud.polaris.router.config.PolarisNearByRouterProperties;
-import com.tencent.cloud.polaris.router.config.PolarisRuleBasedRouterProperties;
+import com.tencent.cloud.polaris.router.config.properties.PolarisMetadataRouterProperties;
+import com.tencent.cloud.polaris.router.config.properties.PolarisNearByRouterProperties;
+import com.tencent.cloud.polaris.router.config.properties.PolarisRuleBasedRouterProperties;
import com.tencent.polaris.api.pojo.Instance;
import com.tencent.polaris.api.pojo.ServiceInfo;
import com.tencent.polaris.api.pojo.ServiceInstances;
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/beanprocessor/LoadBalancerClientFilterBeanPostProcessor.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/beanprocessor/LoadBalancerClientFilterBeanPostProcessor.java
new file mode 100644
index 000000000..5111bda51
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/beanprocessor/LoadBalancerClientFilterBeanPostProcessor.java
@@ -0,0 +1,66 @@
+/*
+ * 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.router.beanprocessor;
+
+import java.util.List;
+
+import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
+import com.tencent.cloud.common.util.BeanFactoryUtils;
+import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
+import com.tencent.cloud.polaris.router.scg.PolarisLoadBalancerClientFilter;
+import com.tencent.cloud.polaris.router.spi.RouterLabelResolver;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.BeanFactoryAware;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
+import org.springframework.cloud.gateway.config.LoadBalancerProperties;
+import org.springframework.cloud.gateway.filter.LoadBalancerClientFilter;
+
+/**
+ * Replace LoadBalancerClientFilter with PolarisLoadBalancerClientFilter.
+ *@author lepdou 2022-06-15
+ */
+public class LoadBalancerClientFilterBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {
+
+ private BeanFactory factory;
+
+ @Override
+ public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
+ this.factory = beanFactory;
+ }
+
+ @Override
+ public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
+ if (bean instanceof LoadBalancerClientFilter) {
+ // Support spring cloud gateway router.
+ // Replaces the default LoadBalancerClientFilter implementation and returns a custom PolarisLoadBalancerClientFilter
+ LoadBalancerClient loadBalancerClient = this.factory.getBean(LoadBalancerClient.class);
+ LoadBalancerProperties loadBalancerProperties = this.factory.getBean(LoadBalancerProperties.class);
+ List routerLabelResolvers = BeanFactoryUtils.getBeans(factory, RouterLabelResolver.class);
+ MetadataLocalProperties metadataLocalProperties = this.factory.getBean(MetadataLocalProperties.class);
+ RouterRuleLabelResolver routerRuleLabelResolver = this.factory.getBean(RouterRuleLabelResolver.class);
+
+ return new PolarisLoadBalancerClientFilter(loadBalancerClient, loadBalancerProperties,
+ metadataLocalProperties, routerRuleLabelResolver, routerLabelResolvers);
+ }
+ return bean;
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerBeanPostProcessor.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/beanprocessor/LoadBalancerInterceptorBeanPostProcessor.java
similarity index 87%
rename from spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerBeanPostProcessor.java
rename to spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/beanprocessor/LoadBalancerInterceptorBeanPostProcessor.java
index 5bafbd9fb..0b383a682 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerBeanPostProcessor.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/beanprocessor/LoadBalancerInterceptorBeanPostProcessor.java
@@ -16,13 +16,14 @@
*
*/
-package com.tencent.cloud.polaris.router.resttemplate;
+package com.tencent.cloud.polaris.router.beanprocessor;
import java.util.List;
import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
import com.tencent.cloud.common.util.BeanFactoryUtils;
import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
+import com.tencent.cloud.polaris.router.resttemplate.PolarisLoadBalancerInterceptor;
import com.tencent.cloud.polaris.router.spi.RouterLabelResolver;
import org.springframework.beans.BeansException;
@@ -36,10 +37,9 @@ import org.springframework.cloud.client.loadbalancer.LoadBalancerRequestFactory;
/**
* Replace LoadBalancerInterceptor with PolarisLoadBalancerInterceptor.
* PolarisLoadBalancerInterceptor can pass routing context information.
- *
*@author lepdou 2022-05-18
*/
-public class PolarisLoadBalancerBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {
+public class LoadBalancerInterceptorBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {
private BeanFactory factory;
@@ -51,6 +51,8 @@ public class PolarisLoadBalancerBeanPostProcessor implements BeanPostProcessor,
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof LoadBalancerInterceptor) {
+ // Support rest template router.
+ // Replaces the default LoadBalancerInterceptor implementation and returns a custom PolarisLoadBalancerInterceptor
LoadBalancerRequestFactory requestFactory = this.factory.getBean(LoadBalancerRequestFactory.class);
LoadBalancerClient loadBalancerClient = this.factory.getBean(LoadBalancerClient.class);
List routerLabelResolvers = BeanFactoryUtils.getBeans(factory, RouterLabelResolver.class);
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/FeignAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/FeignAutoConfiguration.java
new file mode 100644
index 000000000..5b87668ea
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/FeignAutoConfiguration.java
@@ -0,0 +1,58 @@
+/*
+ * 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.router.config;
+
+import java.util.List;
+
+import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
+import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
+import com.tencent.cloud.polaris.router.feign.PolarisCachingSpringLoadBalanceFactory;
+import com.tencent.cloud.polaris.router.feign.RouterLabelFeignInterceptor;
+import com.tencent.cloud.polaris.router.spi.RouterLabelResolver;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.cloud.netflix.ribbon.RibbonClients;
+import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.lang.Nullable;
+
+/**
+ * configuration for feign singleton components.
+ * Feign-related components need to be loaded only in the feign environment.
+ *@author lepdou 2022-06-10
+ */
+@Configuration
+@ConditionalOnClass(name = {"org.springframework.cloud.openfeign.ribbon.FeignLoadBalancer"})
+@RibbonClients(defaultConfiguration = {FeignLoadBalancerConfiguration.class})
+public class FeignAutoConfiguration {
+
+ @Bean
+ public RouterLabelFeignInterceptor routerLabelInterceptor(@Nullable List routerLabelResolvers,
+ MetadataLocalProperties metadataLocalProperties,
+ RouterRuleLabelResolver routerRuleLabelResolver) {
+ return new RouterLabelFeignInterceptor(routerLabelResolvers, metadataLocalProperties, routerRuleLabelResolver);
+ }
+
+ @Bean
+ public PolarisCachingSpringLoadBalanceFactory polarisCachingSpringLoadBalanceFactory(SpringClientFactory factory) {
+ return new PolarisCachingSpringLoadBalanceFactory(factory);
+ }
+
+}
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/FeignConfiguration.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/FeignLoadBalancerConfiguration.java
similarity index 87%
rename from spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/FeignConfiguration.java
rename to spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/FeignLoadBalancerConfiguration.java
index d5d22444e..e6368cc85 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/FeignConfiguration.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/FeignLoadBalancerConfiguration.java
@@ -25,15 +25,12 @@ import com.tencent.cloud.polaris.router.feign.PolarisFeignLoadBalancer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.netflix.ribbon.ServerIntrospector;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
/**
- * configuration for feign component.
- *
+ * configuration for feign load balance components. PolarisFeignLoadBalancer is not singleton bean, Each service corresponds to a PolarisFeignLoadBalancer.
*@author lepdou 2022-05-16
*/
-@Configuration
-public class FeignConfiguration {
+public class FeignLoadBalancerConfiguration {
@Bean
@ConditionalOnMissingBean
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RibbonConfiguration.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RibbonConfiguration.java
index b9c60fbfb..9bc17b276 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RibbonConfiguration.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RibbonConfiguration.java
@@ -22,16 +22,17 @@ import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.IRule;
import com.tencent.cloud.polaris.loadbalancer.config.PolarisLoadBalancerProperties;
import com.tencent.cloud.polaris.router.PolarisLoadBalancerCompositeRule;
+import com.tencent.cloud.polaris.router.config.properties.PolarisMetadataRouterProperties;
+import com.tencent.cloud.polaris.router.config.properties.PolarisNearByRouterProperties;
+import com.tencent.cloud.polaris.router.config.properties.PolarisRuleBasedRouterProperties;
import com.tencent.polaris.router.api.core.RouterAPI;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
/**
- * Auto configuration for ribbon components.
+ * Configuration for ribbon components. IRule is not singleton bean, Each service corresponds to an IRule.
* @author lepdou 2022-05-17
*/
-@Configuration
public class RibbonConfiguration {
@Bean
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RouterAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RouterAutoConfiguration.java
index 6d274bc1c..a57c16857 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RouterAutoConfiguration.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RouterAutoConfiguration.java
@@ -18,52 +18,47 @@
package com.tencent.cloud.polaris.router.config;
-import java.util.List;
-
-import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
import com.tencent.cloud.polaris.context.ServiceRuleManager;
import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
-import com.tencent.cloud.polaris.router.feign.PolarisCachingSpringLoadBalanceFactory;
-import com.tencent.cloud.polaris.router.feign.RouterLabelFeignInterceptor;
-import com.tencent.cloud.polaris.router.resttemplate.PolarisLoadBalancerBeanPostProcessor;
-import com.tencent.cloud.polaris.router.spi.RouterLabelResolver;
+import com.tencent.cloud.polaris.router.beanprocessor.LoadBalancerClientFilterBeanPostProcessor;
+import com.tencent.cloud.polaris.router.beanprocessor.LoadBalancerInterceptorBeanPostProcessor;
+import com.tencent.cloud.polaris.router.config.properties.PolarisMetadataRouterProperties;
+import com.tencent.cloud.polaris.router.config.properties.PolarisNearByRouterProperties;
+import com.tencent.cloud.polaris.router.config.properties.PolarisRuleBasedRouterProperties;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor;
+import org.springframework.cloud.gateway.filter.LoadBalancerClientFilter;
import org.springframework.cloud.netflix.ribbon.RibbonClients;
-import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.annotation.Order;
-import org.springframework.lang.Nullable;
import static org.springframework.core.Ordered.HIGHEST_PRECEDENCE;
/**
- * router module auto configuration.
+ * configuration for router module singleton beans.
*
*@author lepdou 2022-05-11
*/
@Configuration
-@RibbonClients(defaultConfiguration = {FeignConfiguration.class, RibbonConfiguration.class})
+@RibbonClients(defaultConfiguration = {RibbonConfiguration.class})
@Import({PolarisNearByRouterProperties.class, PolarisMetadataRouterProperties.class, PolarisRuleBasedRouterProperties.class})
public class RouterAutoConfiguration {
@Bean
- public RouterLabelFeignInterceptor routerLabelInterceptor(@Nullable List routerLabelResolvers,
- MetadataLocalProperties metadataLocalProperties,
- RouterRuleLabelResolver routerRuleLabelResolver) {
- return new RouterLabelFeignInterceptor(routerLabelResolvers, metadataLocalProperties, routerRuleLabelResolver);
- }
-
- @Bean
- public PolarisCachingSpringLoadBalanceFactory polarisCachingSpringLoadBalanceFactory(SpringClientFactory factory) {
- return new PolarisCachingSpringLoadBalanceFactory(factory);
+ @Order(HIGHEST_PRECEDENCE)
+ @ConditionalOnClass(LoadBalancerInterceptor.class)
+ public LoadBalancerInterceptorBeanPostProcessor loadBalancerInterceptorBeanPostProcessor() {
+ return new LoadBalancerInterceptorBeanPostProcessor();
}
@Bean
@Order(HIGHEST_PRECEDENCE)
- public PolarisLoadBalancerBeanPostProcessor polarisLoadBalancerBeanPostProcessor() {
- return new PolarisLoadBalancerBeanPostProcessor();
+ @ConditionalOnClass(LoadBalancerClientFilter.class)
+ public LoadBalancerClientFilterBeanPostProcessor loadBalancerClientFilterBeanPostProcessor() {
+ return new LoadBalancerClientFilterBeanPostProcessor();
}
@Bean
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/PolarisMetadataRouterProperties.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/properties/PolarisMetadataRouterProperties.java
similarity index 95%
rename from spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/PolarisMetadataRouterProperties.java
rename to spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/properties/PolarisMetadataRouterProperties.java
index 4a20e53f6..70ded3a8c 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/PolarisMetadataRouterProperties.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/properties/PolarisMetadataRouterProperties.java
@@ -16,7 +16,7 @@
*
*/
-package com.tencent.cloud.polaris.router.config;
+package com.tencent.cloud.polaris.router.config.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/PolarisNearByRouterProperties.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/properties/PolarisNearByRouterProperties.java
similarity index 95%
rename from spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/PolarisNearByRouterProperties.java
rename to spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/properties/PolarisNearByRouterProperties.java
index 3467b0587..3cd69ca12 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/PolarisNearByRouterProperties.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/properties/PolarisNearByRouterProperties.java
@@ -16,7 +16,7 @@
*
*/
-package com.tencent.cloud.polaris.router.config;
+package com.tencent.cloud.polaris.router.config.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/PolarisRuleBasedRouterProperties.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/properties/PolarisRuleBasedRouterProperties.java
similarity index 95%
rename from spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/PolarisRuleBasedRouterProperties.java
rename to spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/properties/PolarisRuleBasedRouterProperties.java
index 89b4bead5..67a17975f 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/PolarisRuleBasedRouterProperties.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/properties/PolarisRuleBasedRouterProperties.java
@@ -16,7 +16,7 @@
*
*/
-package com.tencent.cloud.polaris.router.config;
+package com.tencent.cloud.polaris.router.config.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/scg/PolarisLoadBalancerClientFilter.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/scg/PolarisLoadBalancerClientFilter.java
new file mode 100644
index 000000000..35de57737
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/scg/PolarisLoadBalancerClientFilter.java
@@ -0,0 +1,144 @@
+/*
+ * 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.router.scg;
+
+import java.net.URI;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.tencent.cloud.common.metadata.MetadataContext;
+import com.tencent.cloud.common.metadata.MetadataContextHolder;
+import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
+import com.tencent.cloud.common.util.ExpressionLabelUtils;
+import com.tencent.cloud.polaris.router.PolarisRouterContext;
+import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
+import com.tencent.cloud.polaris.router.spi.RouterLabelResolver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.springframework.cloud.client.ServiceInstance;
+import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
+import org.springframework.cloud.gateway.config.LoadBalancerProperties;
+import org.springframework.cloud.gateway.filter.LoadBalancerClientFilter;
+import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient;
+import org.springframework.core.Ordered;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.server.ServerWebExchange;
+
+import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR;
+
+/**
+ * Replaces the default LoadBalancerClientFilter implementation.
+ *@author lepdou 2022-06-10
+ */
+public class PolarisLoadBalancerClientFilter extends LoadBalancerClientFilter {
+ private final static Logger LOGGER = LoggerFactory.getLogger(PolarisLoadBalancerClientFilter.class);
+
+ private final MetadataLocalProperties metadataLocalProperties;
+ private final RouterRuleLabelResolver routerRuleLabelResolver;
+ private final List routerLabelResolvers;
+
+ private final boolean isRibbonLoadBalanceClient;
+
+ public PolarisLoadBalancerClientFilter(LoadBalancerClient loadBalancer, LoadBalancerProperties properties,
+ MetadataLocalProperties metadataLocalProperties,
+ RouterRuleLabelResolver routerRuleLabelResolver,
+ List routerLabelResolvers) {
+ super(loadBalancer, properties);
+ this.metadataLocalProperties = metadataLocalProperties;
+ this.routerRuleLabelResolver = routerRuleLabelResolver;
+
+ if (!CollectionUtils.isEmpty(routerLabelResolvers)) {
+ routerLabelResolvers.sort(Comparator.comparingInt(Ordered::getOrder));
+ this.routerLabelResolvers = routerLabelResolvers;
+ }
+ else {
+ this.routerLabelResolvers = null;
+ }
+
+ this.isRibbonLoadBalanceClient = loadBalancer instanceof RibbonLoadBalancerClient;
+ }
+
+ @Override
+ protected ServiceInstance choose(ServerWebExchange exchange) {
+ String peerServiceName = ((URI) exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR)).getHost();
+
+ if (isRibbonLoadBalanceClient) {
+ // Pass routing context to ribbon load balancer
+ PolarisRouterContext routerContext = genRouterContext(exchange, peerServiceName);
+ return ((RibbonLoadBalancerClient) loadBalancer).choose(peerServiceName, routerContext);
+ }
+ else {
+ return loadBalancer.choose(peerServiceName);
+ }
+ }
+
+ PolarisRouterContext genRouterContext(ServerWebExchange exchange, String peerServiceName) {
+ // local service labels
+ Map labels = new HashMap<>(metadataLocalProperties.getContent());
+
+ // labels from rule expression
+ Map ruleExpressionLabels = getExpressionLabels(exchange, peerServiceName);
+ if (!CollectionUtils.isEmpty(ruleExpressionLabels)) {
+ labels.putAll(ruleExpressionLabels);
+ }
+
+ // labels from request
+ if (!CollectionUtils.isEmpty(routerLabelResolvers)) {
+ routerLabelResolvers.forEach(resolver -> {
+ try {
+ Map customResolvedLabels = resolver.resolve(exchange);
+ if (!CollectionUtils.isEmpty(customResolvedLabels)) {
+ labels.putAll(customResolvedLabels);
+ }
+ }
+ catch (Throwable t) {
+ LOGGER.error("[SCT][Router] revoke RouterLabelResolver occur some exception. ", t);
+ }
+ });
+ }
+
+ // labels from downstream
+ Map transitiveLabels = MetadataContextHolder.get()
+ .getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE);
+ labels.putAll(transitiveLabels);
+
+ PolarisRouterContext routerContext = new PolarisRouterContext();
+
+ routerContext.setLabels(PolarisRouterContext.RULE_ROUTER_LABELS, labels);
+ routerContext.setLabels(PolarisRouterContext.TRANSITIVE_LABELS, transitiveLabels);
+
+ return routerContext;
+ }
+
+ private Map getExpressionLabels(ServerWebExchange exchange, String peerServiceName) {
+ Set labelKeys = routerRuleLabelResolver.getExpressionLabelKeys(MetadataContext.LOCAL_NAMESPACE,
+ MetadataContext.LOCAL_SERVICE, peerServiceName);
+
+ if (CollectionUtils.isEmpty(labelKeys)) {
+ return Collections.emptyMap();
+ }
+
+ return ExpressionLabelUtils.resolve(exchange, labelKeys);
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/spi/RouterLabelResolver.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/spi/RouterLabelResolver.java
index 49b9ccf4c..44dbbb471 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/spi/RouterLabelResolver.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/spi/RouterLabelResolver.java
@@ -24,6 +24,7 @@ import feign.RequestTemplate;
import org.springframework.core.Ordered;
import org.springframework.http.HttpRequest;
+import org.springframework.web.server.ServerWebExchange;
/**
* The spi for resolving labels from request.
@@ -46,4 +47,12 @@ public interface RouterLabelResolver extends Ordered {
* @return resolved labels
*/
Map resolve(HttpRequest request, byte[] body);
+
+
+ /**
+ * resolve labels from server web exchange.
+ * @param exchange the server web exchange.
+ * @return resolved labels
+ */
+ Map resolve(ServerWebExchange exchange);
}
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/resources/META-INF/spring.factories b/spring-cloud-starter-tencent-polaris-router/src/main/resources/META-INF/spring.factories
index d33dcea7f..3b20deb56 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/main/resources/META-INF/spring.factories
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/resources/META-INF/spring.factories
@@ -1,2 +1,3 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
- com.tencent.cloud.polaris.router.config.RouterAutoConfiguration
+ com.tencent.cloud.polaris.router.config.RouterAutoConfiguration,\
+ com.tencent.cloud.polaris.router.config.FeignAutoConfiguration
diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/PolarisLoadBalancerCompositeRuleTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/PolarisLoadBalancerCompositeRuleTest.java
index 1eccb542c..0d55e9cde 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/PolarisLoadBalancerCompositeRuleTest.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/PolarisLoadBalancerCompositeRuleTest.java
@@ -41,9 +41,9 @@ import com.tencent.cloud.common.pojo.PolarisServer;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.polaris.loadbalancer.PolarisWeightedRule;
import com.tencent.cloud.polaris.loadbalancer.config.PolarisLoadBalancerProperties;
-import com.tencent.cloud.polaris.router.config.PolarisMetadataRouterProperties;
-import com.tencent.cloud.polaris.router.config.PolarisNearByRouterProperties;
-import com.tencent.cloud.polaris.router.config.PolarisRuleBasedRouterProperties;
+import com.tencent.cloud.polaris.router.config.properties.PolarisMetadataRouterProperties;
+import com.tencent.cloud.polaris.router.config.properties.PolarisNearByRouterProperties;
+import com.tencent.cloud.polaris.router.config.properties.PolarisRuleBasedRouterProperties;
import com.tencent.polaris.api.pojo.DefaultInstance;
import com.tencent.polaris.api.pojo.DefaultServiceInstances;
import com.tencent.polaris.api.pojo.Instance;
diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerBeanPostProcessorTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerBeanPostProcessorTest.java
index e335e83fa..18229efa6 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerBeanPostProcessorTest.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerBeanPostProcessorTest.java
@@ -21,6 +21,7 @@ package com.tencent.cloud.polaris.router.resttemplate;
import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
import com.tencent.cloud.common.util.BeanFactoryUtils;
import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
+import com.tencent.cloud.polaris.router.beanprocessor.LoadBalancerInterceptorBeanPostProcessor;
import com.tencent.cloud.polaris.router.spi.RouterLabelResolver;
import org.junit.Assert;
import org.junit.Test;
@@ -38,7 +39,7 @@ import org.springframework.cloud.client.loadbalancer.LoadBalancerRequestFactory;
import static org.mockito.Mockito.when;
/**
- * Test for ${@link PolarisLoadBalancerBeanPostProcessor}
+ * Test for ${@link LoadBalancerInterceptorBeanPostProcessor}
* @author lepdou 2022-05-26
*/
@RunWith(MockitoJUnitRunner.class)
@@ -67,7 +68,7 @@ public class PolarisLoadBalancerBeanPostProcessorTest {
.thenReturn(null);
LoadBalancerInterceptor loadBalancerInterceptor = new LoadBalancerInterceptor(loadBalancerClient, loadBalancerRequestFactory);
- PolarisLoadBalancerBeanPostProcessor processor = new PolarisLoadBalancerBeanPostProcessor();
+ LoadBalancerInterceptorBeanPostProcessor processor = new LoadBalancerInterceptorBeanPostProcessor();
processor.setBeanFactory(beanFactory);
Object bean = processor.postProcessBeforeInitialization(loadBalancerInterceptor, "");
@@ -78,7 +79,7 @@ public class PolarisLoadBalancerBeanPostProcessorTest {
@Test
public void testNotWrapperLoadBalancerInterceptor() {
- PolarisLoadBalancerBeanPostProcessor processor = new PolarisLoadBalancerBeanPostProcessor();
+ LoadBalancerInterceptorBeanPostProcessor processor = new LoadBalancerInterceptorBeanPostProcessor();
processor.setBeanFactory(beanFactory);
OtherBean otherBean = new OtherBean();
diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/scg/PolarisLoadBalancerClientFilterTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/scg/PolarisLoadBalancerClientFilterTest.java
new file mode 100644
index 000000000..6010689af
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/scg/PolarisLoadBalancerClientFilterTest.java
@@ -0,0 +1,192 @@
+/*
+ * 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.router.scg;
+
+
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.tencent.cloud.common.metadata.MetadataContext;
+import com.tencent.cloud.common.metadata.MetadataContextHolder;
+import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
+import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
+import com.tencent.cloud.polaris.router.PolarisRouterContext;
+import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
+import com.tencent.cloud.polaris.router.spi.RouterLabelResolver;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
+import org.springframework.cloud.gateway.config.LoadBalancerProperties;
+import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient;
+import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
+import org.springframework.mock.web.server.MockServerWebExchange;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR;
+
+/**
+ * test for ${@link PolarisLoadBalancerClientFilter}
+ *@author lepdou 2022-06-13
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class PolarisLoadBalancerClientFilterTest {
+
+ @Mock
+ private MetadataLocalProperties metadataLocalProperties;
+ @Mock
+ private RouterRuleLabelResolver routerRuleLabelResolver;
+ @Mock
+ private RouterLabelResolver routerLabelResolver;
+ @Mock
+ private LoadBalancerClient loadBalancerClient;
+ @Mock
+ private LoadBalancerProperties loadBalancerProperties;
+
+ private static final String callerService = "callerService";
+ private static final String calleeService = "calleeService";
+
+ private static MockedStatic mockedApplicationContextAwareUtils;
+ private static MockedStatic mockedMetadataContextHolder;
+
+ @BeforeClass
+ public static void beforeClass() {
+ mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
+ mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
+ .thenReturn(callerService);
+
+ MetadataContext metadataContext = Mockito.mock(MetadataContext.class);
+
+ // mock transitive metadata
+ Map transitiveLabels = new HashMap<>();
+ transitiveLabels.put("t1", "v1");
+ transitiveLabels.put("t2", "v2");
+ when(metadataContext.getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE)).thenReturn(transitiveLabels);
+
+ mockedMetadataContextHolder = Mockito.mockStatic(MetadataContextHolder.class);
+ mockedMetadataContextHolder.when(MetadataContextHolder::get).thenReturn(metadataContext);
+ }
+
+ @AfterClass
+ public static void afterClass() {
+ mockedApplicationContextAwareUtils.close();
+ mockedMetadataContextHolder.close();
+ }
+
+ @Test
+ public void testGenRouterContext() {
+ PolarisLoadBalancerClientFilter polarisLoadBalancerClientFilter = new PolarisLoadBalancerClientFilter(
+ loadBalancerClient, loadBalancerProperties, metadataLocalProperties, routerRuleLabelResolver,
+ Lists.newArrayList(routerLabelResolver));
+
+ Map localMetadata = new HashMap<>();
+ localMetadata.put("env", "blue");
+ when(metadataLocalProperties.getContent()).thenReturn(localMetadata);
+
+ Set expressionLabelKeys = Sets.newHashSet("${http.header.k1}", "${http.query.userid}");
+ when(routerRuleLabelResolver.getExpressionLabelKeys(anyString(), anyString(), anyString())).thenReturn(expressionLabelKeys);
+
+ MockServerHttpRequest request = MockServerHttpRequest.get("/" + calleeService + "/users")
+ .header("k1", "v1")
+ .queryParam("userid", "zhangsan")
+ .build();
+ MockServerWebExchange webExchange = new MockServerWebExchange.Builder(request).build();
+
+ Map customMetadata = new HashMap<>();
+ customMetadata.put("k2", "v2");
+ when(routerLabelResolver.resolve(webExchange)).thenReturn(customMetadata);
+
+ PolarisRouterContext routerContext = polarisLoadBalancerClientFilter.genRouterContext(webExchange, calleeService);
+
+ Map routerLabels = routerContext.getLabels(PolarisRouterContext.RULE_ROUTER_LABELS);
+ Assert.assertEquals("v1", routerLabels.get("${http.header.k1}"));
+ Assert.assertEquals("zhangsan", routerLabels.get("${http.query.userid}"));
+ Assert.assertEquals("blue", routerLabels.get("env"));
+ Assert.assertEquals("v1", routerLabels.get("t1"));
+ Assert.assertEquals("v2", routerLabels.get("t2"));
+ }
+
+ @Test
+ public void testChooseInstanceWithoutRibbon() {
+ PolarisLoadBalancerClientFilter polarisLoadBalancerClientFilter = new PolarisLoadBalancerClientFilter(
+ loadBalancerClient, loadBalancerProperties, metadataLocalProperties, routerRuleLabelResolver,
+ Lists.newArrayList(routerLabelResolver));
+
+ String url = "/" + calleeService + "/users";
+ MockServerHttpRequest request = MockServerHttpRequest.get(url)
+ .header("k1", "v1")
+ .queryParam("userid", "zhangsan")
+ .build();
+ MockServerWebExchange webExchange = new MockServerWebExchange.Builder(request).build();
+ webExchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, URI.create("http://" + calleeService + "/users"));
+
+ polarisLoadBalancerClientFilter.choose(webExchange);
+
+ verify(loadBalancerClient).choose(calleeService);
+ verify(metadataLocalProperties, times(0)).getContent();
+ }
+
+ @Test
+ public void testChooseInstanceWithRibbon() {
+ RibbonLoadBalancerClient ribbonLoadBalancerClient = Mockito.mock(RibbonLoadBalancerClient.class);
+
+ PolarisLoadBalancerClientFilter polarisLoadBalancerClientFilter = new PolarisLoadBalancerClientFilter(
+ ribbonLoadBalancerClient, loadBalancerProperties, metadataLocalProperties, routerRuleLabelResolver,
+ Lists.newArrayList(routerLabelResolver));
+
+ Map localMetadata = new HashMap<>();
+ localMetadata.put("env", "blue");
+ when(metadataLocalProperties.getContent()).thenReturn(localMetadata);
+
+ Set expressionLabelKeys = Sets.newHashSet("${http.header.k1}", "${http.query.userid}");
+ when(routerRuleLabelResolver.getExpressionLabelKeys(anyString(), anyString(), anyString())).thenReturn(expressionLabelKeys);
+
+ String url = "/" + calleeService + "/users";
+ MockServerHttpRequest request = MockServerHttpRequest.get(url)
+ .header("k1", "v1")
+ .queryParam("userid", "zhangsan")
+ .build();
+ MockServerWebExchange webExchange = new MockServerWebExchange.Builder(request).build();
+ webExchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, URI.create("http://" + calleeService + "/users"));
+
+ Map customMetadata = new HashMap<>();
+ customMetadata.put("k2", "v2");
+ when(routerLabelResolver.resolve(webExchange)).thenReturn(customMetadata);
+
+ polarisLoadBalancerClientFilter.choose(webExchange);
+
+ verify(ribbonLoadBalancerClient).choose(anyString(), any());
+ verify(metadataLocalProperties, times(1)).getContent();
+ }
+}
diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/StaticMetadataManager.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/StaticMetadataManager.java
index 95557598c..575775bf7 100644
--- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/StaticMetadataManager.java
+++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/StaticMetadataManager.java
@@ -43,9 +43,18 @@ public class StaticMetadataManager {
private static final String ENV_METADATA_REGION = "SCT_METADATA_REGION";
private static final String ENV_METADATA_CAMPUS = "SCT_METADATA_CAMPUS";
- private static final String LOCATION_KEY_REGION = "region";
- private static final String LOCATION_KEY_ZONE = "zone";
- private static final String LOCATION_KEY_CAMPUS = "campus";
+ /**
+ * the metadata key of region.
+ */
+ public static final String LOCATION_KEY_REGION = "region";
+ /**
+ * the metadata key of zone.
+ */
+ public static final String LOCATION_KEY_ZONE = "zone";
+ /**
+ * the metadata key of campus/datacenter.
+ */
+ public static final String LOCATION_KEY_CAMPUS = "campus";
private Map envMetadata;
private Map envTransitiveMetadata;
diff --git a/spring-cloud-tencent-coverage/pom.xml b/spring-cloud-tencent-coverage/pom.xml
index 1c8ba0ed4..37903c143 100644
--- a/spring-cloud-tencent-coverage/pom.xml
+++ b/spring-cloud-tencent-coverage/pom.xml
@@ -24,6 +24,16 @@
spring-cloud-tencent-commons
+
+ com.tencent.cloud
+ spring-cloud-tencent-polaris-context
+
+
+
+ com.tencent.cloud
+ spring-cloud-tencent-polaris-loadbalancer
+
+
com.tencent.cloud
spring-cloud-starter-tencent-polaris-discovery
@@ -49,10 +59,10 @@
spring-cloud-starter-tencent-polaris-router
-
- com.tencent.cloud
- spring-cloud-tencent-polaris-context
-
+
+ com.tencent.cloud
+ spring-cloud-starter-tencent-polaris-config
+
@@ -75,4 +85,4 @@
-
\ No newline at end of file
+
diff --git a/spring-cloud-tencent-dependencies/pom.xml b/spring-cloud-tencent-dependencies/pom.xml
index 3fefad0e7..528f1ba88 100644
--- a/spring-cloud-tencent-dependencies/pom.xml
+++ b/spring-cloud-tencent-dependencies/pom.xml
@@ -78,6 +78,7 @@
2.12.7
3.16.1
1.69
+ 31.0.1-jre
3.2.0
@@ -150,6 +151,27 @@
${revision}
+
+
+ com.google.guava
+ guava
+ ${guava.version}
+
+
+ jsr305
+ com.google.code.findbugs
+
+
+ animal-sniffer-annotations
+ org.codehaus.mojo
+
+
+ error_prone_annotations
+ com.google.errorprone
+
+
+
+
ch.qos.logback
logback-core
diff --git a/spring-cloud-tencent-examples/polaris-discovery-example/discovery-callee-service/src/main/java/com/tencent/cloud/polaris/discovery/service/callee/CustomMetadata.java b/spring-cloud-tencent-examples/polaris-discovery-example/discovery-callee-service/src/main/java/com/tencent/cloud/polaris/discovery/service/callee/CustomMetadata.java
new file mode 100644
index 000000000..efe3f8167
--- /dev/null
+++ b/spring-cloud-tencent-examples/polaris-discovery-example/discovery-callee-service/src/main/java/com/tencent/cloud/polaris/discovery/service/callee/CustomMetadata.java
@@ -0,0 +1,56 @@
+/*
+ * 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.discovery.service.callee;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.tencent.cloud.polaris.context.spi.InstanceMetadataProvider;
+
+import org.springframework.stereotype.Component;
+
+/**
+ * custom metadata for instance.
+ *@author lepdou 2022-06-16
+ */
+@Component
+public class CustomMetadata implements InstanceMetadataProvider {
+
+ @Override
+ public Map getMetadata() {
+ Map metadata = new HashMap<>();
+ metadata.put("k1", "v1");
+ return metadata;
+ }
+
+ @Override
+ public String getRegion() {
+ return "shanghai";
+ }
+
+ @Override
+ public String getZone() {
+ return null;
+ }
+
+ @Override
+ public String getCampus() {
+ return null;
+ }
+}
diff --git a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service/src/main/resources/bootstrap.yml
index 2d0d75a41..c6d40440f 100644
--- a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service/src/main/resources/bootstrap.yml
+++ b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service/src/main/resources/bootstrap.yml
@@ -5,6 +5,10 @@ spring:
application:
name: GatewayCalleeService
cloud:
+ tencent:
+ metadata:
+ content:
+ env: blue
polaris:
address: grpc://183.47.111.80:8091
namespace: default
diff --git a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/pom.xml b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/pom.xml
new file mode 100644
index 000000000..6454f43d7
--- /dev/null
+++ b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/pom.xml
@@ -0,0 +1,26 @@
+
+
+
+ polaris-gateway-example
+ com.tencent.cloud
+ ${revision}
+ ../pom.xml
+
+ 4.0.0
+
+ gateway-callee-service2
+
+
+
+ com.tencent.cloud
+ spring-cloud-starter-tencent-polaris-discovery
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
diff --git a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/GatewayCalleeApplication2.java b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/GatewayCalleeApplication2.java
new file mode 100644
index 000000000..5d261d56f
--- /dev/null
+++ b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/GatewayCalleeApplication2.java
@@ -0,0 +1,35 @@
+/*
+ * 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.gateway.example.callee;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * Gateway callee application.
+ *
+ * @author Haotian Zhang
+ */
+@SpringBootApplication
+public class GatewayCalleeApplication2 {
+
+ public static void main(String[] args) {
+ SpringApplication.run(GatewayCalleeApplication2.class, args);
+ }
+
+}
diff --git a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/GatewayCalleeController.java b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/GatewayCalleeController.java
new file mode 100644
index 000000000..40ddeb240
--- /dev/null
+++ b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/GatewayCalleeController.java
@@ -0,0 +1,71 @@
+/*
+ * 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.gateway.example.callee;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+
+import com.tencent.cloud.common.constant.MetadataConstant;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * Gateway callee controller.
+ *
+ * @author Haotian Zhang
+ */
+@RestController
+@RequestMapping("/gateway/example/callee")
+public class GatewayCalleeController {
+
+ private static Logger LOG = LoggerFactory.getLogger(GatewayCalleeController.class);
+
+ @Value("${server.port:0}")
+ private int port;
+
+ /**
+ * Get information of callee.
+ * @return information of callee
+ */
+ @RequestMapping("/info")
+ public String info() {
+ LOG.info("Gateway Example Callee [{}] is called.", port);
+ return String.format("Gateway Example Callee [%s] is called.", port);
+ }
+
+ /**
+ * Get metadata in HTTP header.
+ *
+ * @param metadataStr metadata string
+ * @return metadata in HTTP header
+ * @throws UnsupportedEncodingException encoding exception
+ */
+ @RequestMapping("/echo")
+ public String echoHeader(
+ @RequestHeader(MetadataConstant.HeaderName.CUSTOM_METADATA) String metadataStr)
+ throws UnsupportedEncodingException {
+ LOG.info(URLDecoder.decode(metadataStr, "UTF-8"));
+ return URLDecoder.decode(metadataStr, "UTF-8");
+ }
+
+}
diff --git a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/resources/bootstrap.yml
new file mode 100644
index 000000000..a0cf12581
--- /dev/null
+++ b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/resources/bootstrap.yml
@@ -0,0 +1,14 @@
+server:
+ session-timeout: 1800
+ port: 48082
+spring:
+ application:
+ name: GatewayCalleeService
+ cloud:
+ tencent:
+ metadata:
+ content:
+ env: green
+ polaris:
+ address: grpc://183.47.111.80:8091
+ namespace: default
diff --git a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-scg-service/pom.xml b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-scg-service/pom.xml
index 5e02ccb43..755b04d63 100644
--- a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-scg-service/pom.xml
+++ b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-scg-service/pom.xml
@@ -26,7 +26,7 @@
com.tencent.cloud
- spring-cloud-starter-tencent-metadata-transfer
+ spring-cloud-starter-tencent-polaris-router
@@ -34,4 +34,4 @@
spring-cloud-starter-gateway
-
\ No newline at end of file
+
diff --git a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-scg-service/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-scg-service/src/main/resources/bootstrap.yml
index 5d949573b..f50100264 100644
--- a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-scg-service/src/main/resources/bootstrap.yml
+++ b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-scg-service/src/main/resources/bootstrap.yml
@@ -8,15 +8,13 @@ spring:
tencent:
metadata:
content:
- a: 1
+ env: blue
transitive:
- - a
+ - env
polaris:
address: grpc://183.47.111.80:8091
namespace: default
enabled: true
- discovery:
- service-list-refresh-interval: 1000
gateway:
discovery:
locator:
@@ -52,13 +50,13 @@ spring:
maxBackoff: '''500ms'''
factor: 2
basedOnPreviousValue: false
-# routes:
-# - id: GatewayCalleeService
-# uri: lb://GatewayCalleeService
-# predicates:
-# - Path=/GatewayCalleeService/**
-# filters:
-# - StripPrefix=1
+ routes:
+ - id: GatewayCalleeService
+ uri: lb://GatewayCalleeService
+ predicates:
+ - Path=/GatewayCalleeService/**
+ filters:
+ - StripPrefix=1
logging:
level:
diff --git a/spring-cloud-tencent-examples/polaris-gateway-example/pom.xml b/spring-cloud-tencent-examples/polaris-gateway-example/pom.xml
index 2645ccc62..fb7a97f2c 100644
--- a/spring-cloud-tencent-examples/polaris-gateway-example/pom.xml
+++ b/spring-cloud-tencent-examples/polaris-gateway-example/pom.xml
@@ -18,6 +18,7 @@
gateway-zuul-service
gateway-scg-service
gateway-callee-service
+ gateway-callee-service2
@@ -35,4 +36,4 @@
-
\ No newline at end of file
+
diff --git a/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/java/com/tencent/cloud/polaris/router/example/CustomRouterLabelResolver.java b/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/java/com/tencent/cloud/polaris/router/example/CustomRouterLabelResolver.java
index bd289abb9..ea8c2ceb0 100644
--- a/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/java/com/tencent/cloud/polaris/router/example/CustomRouterLabelResolver.java
+++ b/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/java/com/tencent/cloud/polaris/router/example/CustomRouterLabelResolver.java
@@ -27,6 +27,7 @@ import feign.RequestTemplate;
import org.springframework.http.HttpRequest;
import org.springframework.stereotype.Component;
+import org.springframework.web.server.ServerWebExchange;
/**
*
@@ -58,6 +59,11 @@ public class CustomRouterLabelResolver implements RouterLabelResolver {
return labels;
}
+ @Override
+ public Map resolve(ServerWebExchange exchange) {
+ return null;
+ }
+
@Override
public int getOrder() {
return 0;
diff --git a/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/spi/InstanceMetadataProvider.java b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/spi/InstanceMetadataProvider.java
new file mode 100644
index 000000000..6b2b73a6b
--- /dev/null
+++ b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/spi/InstanceMetadataProvider.java
@@ -0,0 +1,55 @@
+/*
+ * 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.context.spi;
+
+import java.util.Map;
+
+/**
+ *
+ * Instance's custom metadata, metadata will be register to polaris server.
+ * @author lepdou 2022-06-16
+ */
+public interface InstanceMetadataProvider {
+
+ /**
+ * @return the metadata of instance.
+ */
+ Map getMetadata();
+
+ /**
+ * The region of current instance.
+ *
+ * @return the region info.
+ */
+ String getRegion();
+
+ /**
+ * The zone of current instance.
+ *
+ * @return the zone info.
+ */
+ String getZone();
+
+ /**
+ * The campus/datacenter of current instance.
+ *
+ * @return the campus or datacenter info.
+ */
+ String getCampus();
+}