Merge branch 'main' into optimization_fefreshScope

pull/326/head
weihubeats 2 years ago committed by GitHub
commit cfe8a449bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -5,12 +5,17 @@ name: Codecov
on: on:
push: push:
branches: [ main ] branches:
- main
- 2021.0
- 2020.0
- greenwich
pull_request: pull_request:
branches: [ main ] branches:
- main
permissions: - 2021.0
contents: write - 2020.0
- greenwich
jobs: jobs:
build: build:

@ -22,7 +22,7 @@ jobs:
strategy: strategy:
matrix: matrix:
java: [ 8, 11, 17 ] java: [ 8, 11, 17 ]
os: [ 'windows-latest', 'macos-latest', 'ubuntu-latest' ] os: [ 'windows-latest', 'ubuntu-latest' ]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}

@ -21,8 +21,12 @@
- [Fix the current limiting effect is that other requests cannot be processed when queuing at a constant speed](https://github.com/Tencent/spring-cloud-tencent/pull/316) - [Fix the current limiting effect is that other requests cannot be processed when queuing at a constant speed](https://github.com/Tencent/spring-cloud-tencent/pull/316)
- [Fix config file format misspell](https://github.com/Tencent/spring-cloud-tencent/pull/319) - [Fix config file format misspell](https://github.com/Tencent/spring-cloud-tencent/pull/319)
- [UT: improve test coverage for load balancer unit test](https://github.com/Tencent/spring-cloud-tencent/pull/325) - [UT: improve test coverage for load balancer unit test](https://github.com/Tencent/spring-cloud-tencent/pull/325)
- [Feature: Optimize polaris load balancer test code format](https://github.com/Tencent/spring-cloud-tencent/pull/333) - [optimize polaris load balancer test code format](https://github.com/Tencent/spring-cloud-tencent/pull/333)
- [feat:Add GitHub action of codecov.yml.](https://github.com/Tencent/spring-cloud-tencent/pull/328) - [feat:Add GitHub action of codecov.yml.](https://github.com/Tencent/spring-cloud-tencent/pull/328)
- [Feature: add spring cloud tencent logo](https://github.com/Tencent/spring-cloud-tencent/pull/329) - [Feature: add spring cloud tencent logo](https://github.com/Tencent/spring-cloud-tencent/pull/329)
- [Feature: Optimize static metadata manager](https://github.com/Tencent/spring-cloud-tencent/pull/327) - [Feature: Optimize static metadata manager](https://github.com/Tencent/spring-cloud-tencent/pull/327)
- [Feature: optimization refreshScope](https://github.com/Tencent/spring-cloud-tencent/pull/326) - [Feature: optimization refreshScope](https://github.com/Tencent/spring-cloud-tencent/pull/326)
- [test:update junit of metadata.](https://github.com/Tencent/spring-cloud-tencent/pull/340)
- [Optimize code style & unit test case](https://github.com/Tencent/spring-cloud-tencent/pull/336)
- [rm code: Condition 'null != interceptors' is always 'true' ](https://github.com/Tencent/spring-cloud-tencent/pull/342)
- [fix: shutdown thread pool before the container closes](https://github.com/Tencent/spring-cloud-tencent/pull/353)

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="424px" height="82px" viewBox="0 0 424 82" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>长款的 svg格式透明</title>
<g id="长款的-svg格式透明" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<rect id="矩形" x="0" y="0" width="424" height="82"></rect>
<text id="Spring-Cloud-Tencent" font-family="TencentSansW7, TencentSans" font-size="34" font-weight="bold" letter-spacing="-0.50303" fill="#000000">
<tspan x="83.8428418" y="49.8255109">Spring Cloud Tencent</tspan>
</text>
<polygon id="路径-2备份-10" fill="#95D2F7" points="43.9206195 11.8255109 43.9206195 21.8255109 52.6095084 16.8255109"></polygon>
<polygon id="矩形备份-25" fill="#7F98FF" points="24.9833459 32.3489782 48.8428418 46.1744891 48.8428418 73.8255109 24.9833459 60"></polygon>
<polygon id="矩形备份-26" fill="#7F98FF" transform="translate(55.772590, 29.412755) scale(-1, 1) translate(-55.772590, -29.412755) " points="43.8428418 8 67.7023376 21.8255109 67.7023376 50.8255109 43.8428418 37"></polygon>
<polygon id="矩形备份-27" fill="#95D2F7" transform="translate(24.983346, 21.523467) scale(-1, 1) translate(-24.983346, -21.523467) " points="24.9833459 10.5234673 43.9666917 21.5234673 24.9833459 32.5234673 6 21.5234673"></polygon>
<polygon id="路径-3" fill="#4065FF" points="43.8428418 43.2977777 43.8428418 50.8255109 48.8428418 47.9799656 48.8428418 46.1744891"></polygon>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="424px" height="82px" viewBox="0 0 424 82" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>长款的 svg 格式的白底</title>
<g id="长款的-svg-格式的白底" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<rect id="矩形" fill="#FFFFFF" x="0" y="0" width="424" height="82"></rect>
<rect id="矩形" fill="#FFFFFF" x="6" y="8" width="412" height="66"></rect>
<text id="Spring-Cloud-Tencent" font-family="TencentSansW7, TencentSans" font-size="34" font-weight="bold" letter-spacing="-0.50303" fill="#000000">
<tspan x="83.8428418" y="49.8255109">Spring Cloud Tencent</tspan>
</text>
<polygon id="路径-2备份-10" fill="#95D2F7" points="43.9206195 11.8255109 43.9206195 21.8255109 52.6095084 16.8255109"></polygon>
<polygon id="矩形备份-25" fill="#7F98FF" points="24.9833459 32.3489782 48.8428418 46.1744891 48.8428418 73.8255109 24.9833459 60"></polygon>
<polygon id="矩形备份-26" fill="#7F98FF" transform="translate(55.772590, 29.412755) scale(-1, 1) translate(-55.772590, -29.412755) " points="43.8428418 8 67.7023376 21.8255109 67.7023376 50.8255109 43.8428418 37"></polygon>
<polygon id="矩形备份-27" fill="#95D2F7" transform="translate(24.983346, 21.523467) scale(-1, 1) translate(-24.983346, -21.523467) " points="24.9833459 10.5234673 43.9666917 21.5234673 24.9833459 32.5234673 6 21.5234673"></polygon>
<polygon id="路径-3" fill="#4065FF" points="43.8428418 43.2977777 43.8428418 50.8255109 48.8428418 47.9799656 48.8428418 46.1744891"></polygon>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

@ -168,8 +168,7 @@ public class MetadataTransferAutoConfiguration {
List<ClientHttpRequestInterceptor> interceptors = restTemplate List<ClientHttpRequestInterceptor> interceptors = restTemplate
.getInterceptors(); .getInterceptors();
// Avoid setting interceptor repeatedly. // Avoid setting interceptor repeatedly.
if (null != interceptors && !interceptors if (!interceptors.contains(encodeTransferMedataRestTemplateInterceptor)) {
.contains(encodeTransferMedataRestTemplateInterceptor)) {
interceptors.add(encodeTransferMedataRestTemplateInterceptor); interceptors.add(encodeTransferMedataRestTemplateInterceptor);
restTemplate.setInterceptors(interceptors); restTemplate.setInterceptors(interceptors);
} }
@ -207,10 +206,8 @@ public class MetadataTransferAutoConfiguration {
List<ClientHttpRequestInterceptor> interceptors = restTemplate List<ClientHttpRequestInterceptor> interceptors = restTemplate
.getInterceptors(); .getInterceptors();
// Avoid setting interceptor repeatedly. // Avoid setting interceptor repeatedly.
if (null != interceptors && !interceptors if (!interceptors.contains(encodeTransferMedataRestTemplateInterceptor)) {
.contains(encodeTransferMedataRestTemplateInterceptor)) { interceptors.add(this.encodeTransferMedataRestTemplateInterceptor);
interceptors
.add(this.encodeTransferMedataRestTemplateInterceptor);
restTemplate.setInterceptors(interceptors); restTemplate.setInterceptors(interceptors);
} }
} }

@ -32,8 +32,8 @@ import org.springframework.util.CollectionUtils;
import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.ServerWebExchange;
/** /**
* resolve custom transitive metadata from request. * Resolve custom transitive metadata from request.
*@author lepdou 2022-05-20 * @author lepdou 2022-05-20
*/ */
public class CustomTransitiveMetadataResolver { public class CustomTransitiveMetadataResolver {

@ -13,14 +13,12 @@
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * 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 * CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*
*/ */
package com.tencent.cloud.metadata; package com.tencent.cloud.metadata.core;
import java.util.Map; import java.util.Map;
import com.tencent.cloud.metadata.core.CustomTransitiveMetadataResolver;
import org.assertj.core.api.Assertions; import org.assertj.core.api.Assertions;
import org.junit.Test; import org.junit.Test;
@ -29,6 +27,8 @@ import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.server.MockServerWebExchange; import org.springframework.mock.web.server.MockServerWebExchange;
/** /**
* Test for {@link CustomTransitiveMetadataResolver}.
*
* @author quan * @author quan
*/ */
public class CustomTransitiveMetadataResolverTest { public class CustomTransitiveMetadataResolverTest {

@ -13,14 +13,12 @@
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * 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 * CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*
*/ */
package com.tencent.cloud.metadata; package com.tencent.cloud.metadata.core;
import com.tencent.cloud.common.constant.MetadataConstant; import com.tencent.cloud.common.constant.MetadataConstant;
import com.tencent.cloud.common.metadata.config.MetadataLocalProperties; import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
import com.tencent.cloud.metadata.core.DecodeTransferMetadataReactiveFilter;
import org.assertj.core.api.Assertions; import org.assertj.core.api.Assertions;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -38,6 +36,8 @@ import org.springframework.web.server.WebFilterChain;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.MOCK; import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.MOCK;
/** /**
* Test for {@link DecodeTransferMetadataReactiveFilter}.
*
* @author Haotian Zhang * @author Haotian Zhang
*/ */
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)

@ -13,10 +13,9 @@
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * 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 * CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*
*/ */
package com.tencent.cloud.metadata; package com.tencent.cloud.metadata.core;
import java.io.IOException; import java.io.IOException;
@ -25,7 +24,6 @@ import javax.servlet.ServletException;
import com.tencent.cloud.common.constant.MetadataConstant; import com.tencent.cloud.common.constant.MetadataConstant;
import com.tencent.cloud.common.metadata.config.MetadataLocalProperties; import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
import com.tencent.cloud.metadata.core.DecodeTransferMetadataServletFilter;
import org.assertj.core.api.Assertions; import org.assertj.core.api.Assertions;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -40,6 +38,8 @@ import org.springframework.test.context.junit4.SpringRunner;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
/** /**
* Test for {@link DecodeTransferMetadataServletFilter}.
*
* @author Haotian Zhang * @author Haotian Zhang
*/ */
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)

@ -13,10 +13,9 @@
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * 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 * CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*
*/ */
package com.tencent.cloud.metadata.core.intercepter; package com.tencent.cloud.metadata.core;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
@ -24,7 +23,6 @@ import com.tencent.cloud.common.constant.MetadataConstant;
import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder; import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.metadata.config.MetadataLocalProperties; import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
import com.tencent.cloud.metadata.core.EncodeTransferMedataFeignInterceptor;
import feign.RequestInterceptor; import feign.RequestInterceptor;
import feign.RequestTemplate; import feign.RequestTemplate;
import org.assertj.core.api.Assertions; import org.assertj.core.api.Assertions;

@ -13,17 +13,15 @@
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * 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 * CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*
*/ */
package com.tencent.cloud.metadata.core.intercepter; package com.tencent.cloud.metadata.core;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import com.tencent.cloud.common.constant.MetadataConstant; import com.tencent.cloud.common.constant.MetadataConstant;
import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder; import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.metadata.core.EncodeTransferMedataRestTemplateInterceptor;
import org.assertj.core.api.Assertions; import org.assertj.core.api.Assertions;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;

@ -13,10 +13,9 @@
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * 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 * CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*
*/ */
package com.tencent.cloud.metadata.core.filter; package com.tencent.cloud.metadata.core;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URLDecoder; import java.net.URLDecoder;
@ -25,9 +24,7 @@ import java.util.Map;
import com.tencent.cloud.common.constant.MetadataConstant; import com.tencent.cloud.common.constant.MetadataConstant;
import com.tencent.cloud.common.util.JacksonUtils; import com.tencent.cloud.common.util.JacksonUtils;
import com.tencent.cloud.metadata.core.EncodeTransferMedataScgFilter;
import org.assertj.core.api.Assertions; import org.assertj.core.api.Assertions;
import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
@ -44,12 +41,14 @@ import org.springframework.test.context.junit4.SpringRunner;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
/** /**
* Test for {@link EncodeTransferMedataScgFilter}.
*
* @author quan * @author quan
*/ */
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = RANDOM_PORT, @SpringBootTest(webEnvironment = RANDOM_PORT,
classes = EncodeTransferMedataScgFilterTest.TestApplication.class, classes = EncodeTransferMedataScgFilterTest.TestApplication.class,
properties = { "spring.config.location = classpath:application-test.yml", "spring.main.web-application-type = reactive" }) properties = {"spring.config.location = classpath:application-test.yml", "spring.main.web-application-type = reactive"})
public class EncodeTransferMedataScgFilterTest { public class EncodeTransferMedataScgFilterTest {
@Autowired @Autowired
@ -61,14 +60,20 @@ public class EncodeTransferMedataScgFilterTest {
@Test @Test
public void testTransitiveMetadataFromApplicationConfig() throws UnsupportedEncodingException { public void testTransitiveMetadataFromApplicationConfig() throws UnsupportedEncodingException {
EncodeTransferMedataScgFilter filter = applicationContext.getBean(EncodeTransferMedataScgFilter.class); EncodeTransferMedataScgFilter filter = applicationContext.getBean(EncodeTransferMedataScgFilter.class);
// Mock Server Http Request
MockServerHttpRequest.BaseBuilder<?> builder = MockServerHttpRequest.get(""); MockServerHttpRequest.BaseBuilder<?> builder = MockServerHttpRequest.get("");
MockServerWebExchange exchange = MockServerWebExchange.from(builder); MockServerWebExchange exchange = MockServerWebExchange.from(builder);
filter.filter(exchange, chain); filter.filter(exchange, chain);
String metadataStr = exchange.getRequest().getHeaders().getFirst(MetadataConstant.HeaderName.CUSTOM_METADATA);
String decode = URLDecoder.decode(metadataStr, StandardCharsets.UTF_8.name()); // Check metadata str
String metadata = exchange.getRequest().getHeaders().getFirst(MetadataConstant.HeaderName.CUSTOM_METADATA);
Assertions.assertThat(metadata).isNotNull();
String decode = URLDecoder.decode(metadata, StandardCharsets.UTF_8.name());
Map<String, String> transitiveMap = JacksonUtils.deserialize2Map(decode); Map<String, String> transitiveMap = JacksonUtils.deserialize2Map(decode);
Assertions.assertThat(transitiveMap.size()).isEqualTo(1); Assertions.assertThat(transitiveMap.size()).isEqualTo(1);
Assert.assertEquals(transitiveMap.get("b"), "2"); Assertions.assertThat(transitiveMap.get("b")).isEqualTo("2");
} }
@SpringBootApplication @SpringBootApplication

@ -16,7 +16,7 @@
* *
*/ */
package com.tencent.cloud.metadata.core.filter; package com.tencent.cloud.metadata.core;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URLDecoder; import java.net.URLDecoder;
@ -26,9 +26,7 @@ import java.util.Map;
import com.netflix.zuul.context.RequestContext; import com.netflix.zuul.context.RequestContext;
import com.tencent.cloud.common.constant.MetadataConstant; import com.tencent.cloud.common.constant.MetadataConstant;
import com.tencent.cloud.common.util.JacksonUtils; import com.tencent.cloud.common.util.JacksonUtils;
import com.tencent.cloud.metadata.core.EncodeTransferMetadataZuulFilter;
import org.assertj.core.api.Assertions; import org.assertj.core.api.Assertions;
import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -43,19 +41,21 @@ import org.springframework.test.context.junit4.SpringRunner;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
/** /**
* Test for {@link EncodeTransferMetadataZuulFilter}.
*
* @author quan * @author quan
*/ */
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = RANDOM_PORT, @SpringBootTest(webEnvironment = RANDOM_PORT,
classes = EncodeTransferMetadataZuulFilterTest.TestApplication.class, classes = EncodeTransferMetadataZuulFilterTest.TestApplication.class,
properties = { "spring.config.location = classpath:application-test.yml", "spring.main.web-application-type = reactive" }) properties = {"spring.config.location = classpath:application-test.yml", "spring.main.web-application-type = reactive"})
public class EncodeTransferMetadataZuulFilterTest { public class EncodeTransferMetadataZuulFilterTest {
@Autowired @Autowired
private ApplicationContext applicationContext; private ApplicationContext applicationContext;
private MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest(); private final MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest();
@Before @Before
public void init() { public void init() {
@ -70,11 +70,13 @@ public class EncodeTransferMetadataZuulFilterTest {
filter.run(); filter.run();
final RequestContext ctx = RequestContext.getCurrentContext(); final RequestContext ctx = RequestContext.getCurrentContext();
Map<String, String> zuulRequestHeaders = ctx.getZuulRequestHeaders(); Map<String, String> zuulRequestHeaders = ctx.getZuulRequestHeaders();
String metaData = zuulRequestHeaders.get(MetadataConstant.HeaderName.CUSTOM_METADATA.toLowerCase()); String metadata = zuulRequestHeaders.get(MetadataConstant.HeaderName.CUSTOM_METADATA.toLowerCase());
String decode = URLDecoder.decode(metaData, StandardCharsets.UTF_8.name()); Assertions.assertThat(metadata).isNotNull();
String decode = URLDecoder.decode(metadata, StandardCharsets.UTF_8.name());
Map<String, String> transitiveMap = JacksonUtils.deserialize2Map(decode); Map<String, String> transitiveMap = JacksonUtils.deserialize2Map(decode);
Assertions.assertThat(transitiveMap.size()).isEqualTo(1); Assertions.assertThat(transitiveMap.size()).isEqualTo(1);
Assert.assertEquals(transitiveMap.get("b"), "2"); Assertions.assertThat(transitiveMap.get("b")).isEqualTo("2");
} }
@SpringBootApplication @SpringBootApplication

@ -102,6 +102,12 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>

@ -32,9 +32,9 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
/** /**
* @author : wh * Auto configuration PolarisRestTemplateAutoConfiguration .
* @date : 2022/6/21 21:34 *
* @description: Auto configuration PolarisRestTemplateAutoConfiguration * @author wh 2022/6/21
*/ */
@ConditionalOnProperty(value = "spring.cloud.polaris.circuitbreaker.enabled", @ConditionalOnProperty(value = "spring.cloud.polaris.circuitbreaker.enabled",
havingValue = "true", matchIfMissing = true) havingValue = "true", matchIfMissing = true)
@ -44,13 +44,16 @@ public class PolarisRestTemplateAutoConfiguration {
@Bean @Bean
@ConditionalOnBean(RestTemplate.class) @ConditionalOnBean(RestTemplate.class)
public PolarisRestTemplateResponseErrorHandler polarisRestTemplateResponseErrorHandler(ConsumerAPI consumerAPI, @Autowired(required = false) PolarisResponseErrorHandler polarisResponseErrorHandler) { public PolarisRestTemplateResponseErrorHandler polarisRestTemplateResponseErrorHandler(
ConsumerAPI consumerAPI, @Autowired(required = false) PolarisResponseErrorHandler polarisResponseErrorHandler) {
return new PolarisRestTemplateResponseErrorHandler(consumerAPI, polarisResponseErrorHandler); return new PolarisRestTemplateResponseErrorHandler(consumerAPI, polarisResponseErrorHandler);
} }
@Bean @Bean
@ConditionalOnBean(RestTemplate.class) @ConditionalOnBean(RestTemplate.class)
public PolarisRestTemplateModifier polarisRestTemplateBeanPostProcessor(PolarisRestTemplateResponseErrorHandler restTemplateResponseErrorHandler) { public PolarisRestTemplateModifier polarisRestTemplateBeanPostProcessor(
PolarisRestTemplateResponseErrorHandler restTemplateResponseErrorHandler) {
return new PolarisRestTemplateModifier(restTemplateResponseErrorHandler); return new PolarisRestTemplateModifier(restTemplateResponseErrorHandler);
} }
} }

@ -20,9 +20,9 @@ package com.tencent.cloud.polaris.circuitbreaker.resttemplate;
import org.springframework.web.client.ResponseErrorHandler; import org.springframework.web.client.ResponseErrorHandler;
/** /**
* @author : wh * Polaris Response Error Handler Definition Of {@link ResponseErrorHandler}.
* @date : 2022/6/21 19:12 *
* @description: errorHandler {@link ResponseErrorHandler} * @author wh 2022/6/21
*/ */
public interface PolarisResponseErrorHandler extends ResponseErrorHandler { public interface PolarisResponseErrorHandler extends ResponseErrorHandler {

@ -28,10 +28,10 @@ import org.springframework.util.ObjectUtils;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
/** /**
* @author : wh * Auto configuration RestTemplate, Find the RestTemplate bean annotated with {@link LoadBalanced},
* @date : 2022/6/21 21:20 * then replace {@link org.springframework.web.client.ResponseErrorHandler} with {@link PolarisRestTemplateResponseErrorHandler} .
* @description: auto configuration RestTemplate Find the RestTemplate bean annotated with {@link LoadBalanced} and replace {@link org.springframework.web.client.ResponseErrorHandler} *
* with {@link PolarisRestTemplateResponseErrorHandler} * @author wh 2022/6/21
*/ */
public class PolarisRestTemplateModifier implements ApplicationContextAware, SmartInitializingSingleton { public class PolarisRestTemplateModifier implements ApplicationContextAware, SmartInitializingSingleton {

@ -29,24 +29,25 @@ import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.api.pojo.RetStatus; import com.tencent.polaris.api.pojo.RetStatus;
import com.tencent.polaris.api.pojo.ServiceKey; import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.api.rpc.ServiceCallResult; import com.tencent.polaris.api.rpc.ServiceCallResult;
import com.tencent.polaris.api.utils.StringUtils; import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpResponse; import org.springframework.http.client.ClientHttpResponse;
import org.springframework.lang.NonNull;
import org.springframework.web.client.ResponseErrorHandler; import org.springframework.web.client.ResponseErrorHandler;
/** /**
* @author : wh * Extend ResponseErrorHandler to get request information.
* @date : 2022/6/21 17:25 *
* @description: Extend ResponseErrorHandler to get request information * @author wh 2022/6/21
*/ */
public class PolarisRestTemplateResponseErrorHandler implements ResponseErrorHandler { public class PolarisRestTemplateResponseErrorHandler implements ResponseErrorHandler {
private static final Logger LOG = LoggerFactory.getLogger(PolarisRestTemplateResponseErrorHandler.class); private static final Logger LOG = LoggerFactory.getLogger(PolarisRestTemplateResponseErrorHandler.class);
private static final String FileName = "connection"; private static final String FIELD_NAME = "connection";
private final ConsumerAPI consumerAPI; private final ConsumerAPI consumerAPI;
@ -59,12 +60,12 @@ public class PolarisRestTemplateResponseErrorHandler implements ResponseErrorHan
} }
@Override @Override
public boolean hasError(ClientHttpResponse response) { public boolean hasError(@NonNull ClientHttpResponse response) {
return true; return true;
} }
@Override @Override
public void handleError(ClientHttpResponse response) throws IOException { public void handleError(@NonNull ClientHttpResponse response) throws IOException {
if (Objects.nonNull(polarisResponseErrorHandler)) { if (Objects.nonNull(polarisResponseErrorHandler)) {
if (polarisResponseErrorHandler.hasError(response)) { if (polarisResponseErrorHandler.hasError(response)) {
polarisResponseErrorHandler.handleError(response); polarisResponseErrorHandler.handleError(response);
@ -72,12 +73,22 @@ public class PolarisRestTemplateResponseErrorHandler implements ResponseErrorHan
} }
} }
public void handleError(URI url, HttpMethod method, ClientHttpResponse response) throws IOException { @Override
ServiceCallResult resultRequest = null; public void handleError(@NonNull URI url, @NonNull HttpMethod method, @NonNull ClientHttpResponse response) throws IOException {
ServiceCallResult resultRequest = createServiceCallResult(url);
try { try {
resultRequest = builderServiceCallResult(url, response); HttpURLConnection connection = (HttpURLConnection) ReflectionUtils.getFieldValue(response, FIELD_NAME);
if (connection != null) {
URL realURL = connection.getURL();
resultRequest.setHost(realURL.getHost());
resultRequest.setPort(realURL.getPort());
}
if (response.getStatusCode().value() > 500) {
resultRequest.setRetStatus(RetStatus.RetFail);
}
} }
catch (IOException e) { catch (Exception e) {
LOG.error("Will report response of {} url {}", response, url, e); LOG.error("Will report response of {} url {}", response, url, e);
throw e; throw e;
} }
@ -86,7 +97,7 @@ public class PolarisRestTemplateResponseErrorHandler implements ResponseErrorHan
} }
} }
private ServiceCallResult builderServiceCallResult(URI uri, ClientHttpResponse response) throws IOException { private ServiceCallResult createServiceCallResult(URI uri) {
ServiceCallResult resultRequest = new ServiceCallResult(); ServiceCallResult resultRequest = new ServiceCallResult();
String serviceName = uri.getHost(); String serviceName = uri.getHost();
resultRequest.setService(serviceName); resultRequest.setService(serviceName);
@ -98,13 +109,6 @@ public class PolarisRestTemplateResponseErrorHandler implements ResponseErrorHan
if (StringUtils.isNotBlank(sourceNamespace) && StringUtils.isNotBlank(sourceService)) { if (StringUtils.isNotBlank(sourceNamespace) && StringUtils.isNotBlank(sourceService)) {
resultRequest.setCallerService(new ServiceKey(sourceNamespace, sourceService)); resultRequest.setCallerService(new ServiceKey(sourceNamespace, sourceService));
} }
HttpURLConnection connection = (HttpURLConnection) ReflectionUtils.getFieldValue(response, FileName);
URL url = connection.getURL();
resultRequest.setHost(url.getHost());
resultRequest.setPort(url.getPort());
if (response.getStatusCode().value() > 500) {
resultRequest.setRetStatus(RetStatus.RetFail);
}
return resultRequest; return resultRequest;
} }

@ -0,0 +1,72 @@
/*
* 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.circuitbreaker;
import com.tencent.cloud.polaris.circuitbreaker.config.PolarisRestTemplateAutoConfiguration;
import com.tencent.cloud.polaris.circuitbreaker.resttemplate.PolarisRestTemplateModifier;
import com.tencent.cloud.polaris.circuitbreaker.resttemplate.PolarisRestTemplateResponseErrorHandler;
import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration;
import org.junit.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Test For {@link PolarisRestTemplateAutoConfiguration} .
*
* @author <a href="mailto:iskp.me@gmail.com">Palmer Xu</a> 2022-06-28
*/
public class PolarisRestTemplateAutoConfigurationTest {
private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
.withConfiguration(
AutoConfigurations.of(
PolarisRestTemplateAutoConfigurationTester.class,
PolarisContextAutoConfiguration.class,
PolarisRestTemplateAutoConfiguration.class))
.withPropertyValues("spring.cloud.polaris.circuitbreaker.enabled=true");
@Test
public void testInitialization() {
this.contextRunner
.run(context -> {
assertThat(context).hasSingleBean(PolarisRestTemplateModifier.class);
assertThat(context).hasSingleBean(PolarisRestTemplateResponseErrorHandler.class);
});
}
@Configuration
@EnableAutoConfiguration
@AutoConfigureBefore(PolarisRestTemplateAutoConfiguration.class)
static class PolarisRestTemplateAutoConfigurationTester {
@Bean
RestTemplate restTemplate() {
return new RestTemplate();
}
}
}

@ -15,14 +15,13 @@
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*/ */
package com.tencent.cloud.polaris.circuitbreaker; package com.tencent.cloud.polaris.circuitbreaker.resttemplate;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URI; import java.net.URI;
import java.net.URL; import java.net.URL;
import com.tencent.cloud.polaris.circuitbreaker.resttemplate.PolarisRestTemplateResponseErrorHandler;
import com.tencent.polaris.api.core.ConsumerAPI; import com.tencent.polaris.api.core.ConsumerAPI;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -36,9 +35,9 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
/** /**
* @author : wh * Test For {@link PolarisRestTemplateResponseErrorHandler}.
* @date : 2022/6/22 09:00 *
* @description: Test for {@link PolarisRestTemplateResponseErrorHandler}. * @author wh 2022/6/22
*/ */
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@SpringBootTest(classes = PolarisRestTemplateResponseErrorHandlerTest.TestApplication.class, @SpringBootTest(classes = PolarisRestTemplateResponseErrorHandlerTest.TestApplication.class,

@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License. * specific language governing permissions and limitations under the License.
*/ */
package com.tencent.cloud.polaris.circuitbreaker; package com.tencent.cloud.polaris.circuitbreaker.resttemplate;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -29,9 +29,9 @@ import org.springframework.util.StringUtils;
/** /**
* @author : wh * Mock Test for {@link AbstractClientHttpResponse}.
* @date : 2022/6/22 09:00 *
* @description: mock {@link org.springframework.http.client.SimpleClientHttpResponse} * @author wh 2022/6/22
*/ */
public class SimpleClientHttpResponseTest extends AbstractClientHttpResponse { public class SimpleClientHttpResponseTest extends AbstractClientHttpResponse {

@ -25,6 +25,7 @@ import com.tencent.polaris.client.util.NamedThreadFactory;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.cloud.client.discovery.event.HeartbeatEvent; import org.springframework.cloud.client.discovery.event.HeartbeatEvent;
import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisher;
@ -38,7 +39,7 @@ import static com.tencent.cloud.polaris.discovery.refresh.PolarisServiceStatusCh
* *
* @author Haotian Zhang * @author Haotian Zhang
*/ */
public class PolarisRefreshApplicationReadyEventListener implements ApplicationListener<ApplicationReadyEvent>, ApplicationEventPublisherAware { public class PolarisRefreshApplicationReadyEventListener implements ApplicationListener<ApplicationReadyEvent>, ApplicationEventPublisherAware, DisposableBean {
private static final Logger LOG = LoggerFactory.getLogger(PolarisRefreshApplicationReadyEventListener.class); private static final Logger LOG = LoggerFactory.getLogger(PolarisRefreshApplicationReadyEventListener.class);
private static final int DELAY = 60; private static final int DELAY = 60;
@ -83,4 +84,9 @@ public class PolarisRefreshApplicationReadyEventListener implements ApplicationL
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher; this.publisher = applicationEventPublisher;
} }
@Override
public void destroy() throws Exception {
refreshExecutor.shutdown();
}
} }

Loading…
Cancel
Save