feat:add spring-cloud-starter-tencent-all and quickstart examples. (#569)

pull/578/head
Haotian Zhang 2 years ago committed by GitHub
parent 8c9d0decb7
commit 62fecd49ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -33,4 +33,5 @@
- [Report the labels in request when report the result of invocation by Feign](https://github.com/Tencent/spring-cloud-tencent/pull/556)
- [fix:fix heartbeat interval different configuration from polaris-java SDK.](https://github.com/Tencent/spring-cloud-tencent/pull/559)
- [Optimize: optimize report call result for restTemplate.](https://github.com/Tencent/spring-cloud-tencent/pull/565)
- [feat:add spring-cloud-starter-tencent-all and quickstart examples.](https://github.com/Tencent/spring-cloud-tencent/pull/569)
- [refactor:optimize project and code.](https://github.com/Tencent/spring-cloud-tencent/pull/571)

@ -50,6 +50,7 @@
<module>spring-cloud-starter-tencent-polaris-router</module>
<module>spring-cloud-tencent-plugin-starters</module>
<module>spring-cloud-tencent-dependencies</module>
<module>spring-cloud-starter-tencent-all</module>
<module>spring-cloud-tencent-examples</module>
<module>spring-cloud-tencent-coverage</module>
</modules>

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-tencent</artifactId>
<groupId>com.tencent.cloud</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-starter-tencent-all</artifactId>
<name>Spring Cloud Starter Tencent ALL In One</name>
<packaging>pom</packaging>
<dependencies>
<!-- Spring Cloud Tencent -->
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-config</artifactId>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-ratelimit</artifactId>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-circuitbreaker</artifactId>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-router</artifactId>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-metadata-transfer</artifactId>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-pushgateway-plugin</artifactId>
</dependency>
<!-- Spring Cloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
</project>

@ -149,7 +149,7 @@ public class SpringValueProcessor extends PolarisProcessor implements BeanFactor
return;
}
springValueRegistry.register(beanFactory, key, springValue);
LOGGER.info("Monitoring {}", springValue);
LOGGER.debug("Monitoring {}", springValue);
}
}

@ -60,7 +60,7 @@ public class ConditionalOnReflectRefreshTypeTest {
serverSocket.accept();
}
catch (IOException e) {
//ignore
e.printStackTrace();
}
}).start();
}

@ -62,7 +62,7 @@ public class SpringValueProcessorTest {
serverSocket.accept();
}
catch (IOException e) {
//ignore
e.printStackTrace();
}
}).start();
}
@ -156,11 +156,10 @@ public class SpringValueProcessorTest {
@Component
private static class ValueTest {
private static String name;
@Value("${timeout:1000}")
private int timeout;
private static String name;
public int getTimeout() {
return timeout;
}

@ -98,7 +98,7 @@ public class QuotaCheckReactiveFilter implements WebFilter, Ordered {
String localService = MetadataContext.LOCAL_SERVICE;
Map<String, String> labels = getRequestLabels(exchange, localNamespace, localService);
long waitMs = -1;
try {
String path = exchange.getRequest().getURI().getPath();
QuotaResponse quotaResponse = QuotaCheckUtils.getQuota(
@ -115,7 +115,7 @@ public class QuotaCheckReactiveFilter implements WebFilter, Ordered {
// Unirate
if (quotaResponse.getCode() == QuotaResultCode.QuotaResultOk && quotaResponse.getWaitMs() > 0) {
LOGGER.debug("The request of [{}] will waiting for {}ms.", path, quotaResponse.getWaitMs());
return Mono.delay(Duration.ofMillis(quotaResponse.getWaitMs())).flatMap(e -> chain.filter(exchange));
waitMs = quotaResponse.getWaitMs();
}
}
catch (Throwable t) {
@ -124,7 +124,12 @@ public class QuotaCheckReactiveFilter implements WebFilter, Ordered {
LOGGER.error("fail to invoke getQuota, service is " + localService, t);
}
return chain.filter(exchange);
if (waitMs > 0) {
return Mono.delay(Duration.ofMillis(waitMs)).flatMap(e -> chain.filter(exchange));
}
else {
return chain.filter(exchange);
}
}
private Map<String, String> getRequestLabels(ServerWebExchange exchange, String localNamespace, String localService) {

@ -114,14 +114,14 @@ public class QuotaCheckServletFilter extends OncePerRequestFilter {
Thread.sleep(quotaResponse.getWaitMs());
}
filterChain.doFilter(request, response);
}
catch (Throwable t) {
// An exception occurs in the rate limiting API call,
// which should not affect the call of the business process.
LOG.error("fail to invoke getQuota, service is " + localService, t);
filterChain.doFilter(request, response);
}
filterChain.doFilter(request, response);
}
private Map<String, String> getRequestLabels(HttpServletRequest request, String localNamespace, String localService) {

@ -70,8 +70,8 @@ public class StaticMetadataManager {
private Map<String, String> mergedStaticMetadata;
private Map<String, String> mergedStaticTransitiveMetadata;
private Map<String, String> mergedStaticDisposableMetadata;
private String zone;
private String region;
private String zone;
private String campus;
public StaticMetadataManager(MetadataLocalProperties metadataLocalProperties,
@ -232,17 +232,6 @@ public class StaticMetadataManager {
private void parseLocationMetadata(MetadataLocalProperties metadataLocalProperties,
InstanceMetadataProvider instanceMetadataProvider) {
// resolve zone info
if (instanceMetadataProvider != null) {
zone = instanceMetadataProvider.getZone();
}
if (StringUtils.isBlank(zone)) {
zone = System.getenv(ENV_METADATA_ZONE);
}
if (StringUtils.isBlank(zone)) {
zone = metadataLocalProperties.getContent().get(LOCATION_KEY_ZONE);
}
// resolve region info
if (instanceMetadataProvider != null) {
region = instanceMetadataProvider.getRegion();
@ -254,6 +243,17 @@ public class StaticMetadataManager {
region = metadataLocalProperties.getContent().get(LOCATION_KEY_REGION);
}
// resolve zone info
if (instanceMetadataProvider != null) {
zone = instanceMetadataProvider.getZone();
}
if (StringUtils.isBlank(zone)) {
zone = System.getenv(ENV_METADATA_ZONE);
}
if (StringUtils.isBlank(zone)) {
zone = metadataLocalProperties.getContent().get(LOCATION_KEY_ZONE);
}
// resolve campus info
if (instanceMetadataProvider != null) {
campus = instanceMetadataProvider.getCampus();

@ -73,14 +73,13 @@
<revision>1.7.0-2021.0.3-SNAPSHOT</revision>
<!-- Dependencies -->
<polaris.version>1.7.3</polaris.version>
<polaris.version>1.7.4-SNAPSHOT</polaris.version>
<guava.version>31.0.1-jre</guava.version>
<logback.version>1.2.11</logback.version>
<mocktio.version>4.5.1</mocktio.version>
<byte-buddy.version>1.12.10</byte-buddy.version>
<protobuf-java.version>3.16.1</protobuf-java.version>
<bcprov-jdk15on.version>1.69</bcprov-jdk15on.version>
<prometheus.version>0.11.0</prometheus.version>
<!-- Maven Plugin Versions -->
<maven-source-plugin.version>3.2.0</maven-source-plugin.version>
@ -159,6 +158,13 @@
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-all</artifactId>
<type>pom</type>
<version>${revision}</version>
</dependency>
<!-- spring cloud tencent plugins -->
<dependency>
<groupId>com.tencent.cloud</groupId>
@ -229,12 +235,6 @@
<version>${byte-buddy.version}</version>
</dependency>
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient_pushgateway</artifactId>
<version>${prometheus.version}</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>

@ -11,6 +11,9 @@ spring:
discovery:
enabled: true
register: true
rpc-enhancement:
reporter:
enabled: true
stat:
enabled: true
port: 28082

@ -22,6 +22,10 @@ spring:
stat:
enabled: true
port: 28081
tencent:
rpc-enhancement:
reporter:
enabled: true
# pushgateway:
# enabled: true
# address: 127.0.0.1:9091

@ -11,7 +11,7 @@ spring:
ratelimit:
enabled: true
rejectRequestTipsFilePath: reject-tips.html
maxQueuingTime: 1000
maxQueuingTime: 500
management:
endpoints:

@ -26,6 +26,7 @@
<module>polaris-router-grayrelease-example</module>
<module>polaris-router-featureenv-example</module>
<module>polaris-config-data-example</module>
<module>quickstart-example</module>
</modules>
<properties>

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-tencent-examples</artifactId>
<groupId>com.tencent.cloud</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>quickstart-example</artifactId>
<packaging>pom</packaging>
<name>Spring Cloud Starter Tencent Quickstart Example</name>
<modules>
<module>quickstart-gateway-service</module>
<module>quickstart-caller-service</module>
<module>quickstart-callee-service-a</module>
<module>quickstart-callee-service-b</module>
</modules>
</project>

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>quickstart-example</artifactId>
<groupId>com.tencent.cloud</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>quickstart-callee-service-a</artifactId>
<name>Quickstart Callee Service A</name>
<dependencies>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-all</artifactId>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,47 @@
/*
* 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.quickstart.callee;
import java.util.Set;
import com.tencent.cloud.polaris.config.annotation.PolarisConfigKVFileChangeListener;
import com.tencent.cloud.polaris.config.listener.ConfigChangeEvent;
import org.springframework.stereotype.Component;
/**
* Custom Config Listener Example .
*
* @author Haotian Zhang
*/
@Component
public final class CustomConfigChangeListener {
/**
* PolarisConfigKVFileChangeListener Example .
* @param event instance of {@link ConfigChangeEvent}
*/
@PolarisConfigKVFileChangeListener(interestedKeyPrefixes = "appName")
public void onChange(ConfigChangeEvent event) {
Set<String> changedKeys = event.changedKeys();
for (String changedKey : changedKeys) {
System.out.printf("%s = %s \n", changedKey, event.getChange(changedKey));
}
}
}

@ -0,0 +1,46 @@
/*
* 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.quickstart.callee;
import java.util.HashMap;
import java.util.Map;
import com.tencent.cloud.common.spi.InstanceMetadataProvider;
import org.springframework.stereotype.Component;
/**
* Custom metadata for instance.
*
* @author Haotian Zhang
*/
@Component
public class CustomMetadata implements InstanceMetadataProvider {
@Override
public Map<String, String> getMetadata() {
Map<String, String> metadata = new HashMap<>();
metadata.put("k1", "v1");
return metadata;
}
@Override
public String getZone() {
return "shenzhen-zone-1";
}
}

@ -0,0 +1,78 @@
/*
* 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.quickstart.callee;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* Quickstart callee controller.
*
* @author Haotian Zhang
*/
@RestController
@RequestMapping("/quickstart/callee")
public class QuickstartCalleeController {
private static final Logger LOG = LoggerFactory.getLogger(QuickstartCalleeController.class);
@Value("${server.port:0}")
private int port;
@Value("${appName:Callee}")
private String appName;
/**
* Get sum of two value.
* @param value1 value 1
* @param value2 value 2
* @return sum
*/
@GetMapping("/sum")
public int sum(@RequestParam int value1, @RequestParam int value2) {
LOG.info("Quickstart Callee Service is called and sum is {}.", value1 + value2);
return value1 + value2;
}
/**
* Get information of callee.
* @return information of callee
*/
@GetMapping("/info")
public String info() {
LOG.info("Quickstart [{}] Service [{}] is called.", appName, port);
return String.format("Quickstart [%s] Service [%s] is called.", appName, port);
}
/**
* Check circuit break.
*
* @return circuit break info
*/
@GetMapping("/circuitBreak")
public String circuitBreak() {
LOG.info("Quickstart Callee Service is called right.");
return "Quickstart Callee Service is called right.";
}
}

@ -0,0 +1,34 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.quickstart.callee;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* Quickstart callee application.
*
* @author Haotian Zhang
*/
@SpringBootApplication
public class QuickstartCalleeServiceA {
public static void main(String[] args) {
SpringApplication.run(QuickstartCalleeServiceA.class, args);
}
}

@ -0,0 +1,27 @@
server:
port: 48083
spring:
application:
name: QuickstartCalleeService
cloud:
polaris:
address: grpc://183.47.111.80:8091
namespace: default
enabled: true
discovery:
enabled: true
register: true
config:
address: grpc://183.47.111.80:8093
auto-refresh: true
groups:
- name: ${spring.application.name}
files: [ "config/callee.properties" ]
refresh-type: reflect
ratelimit:
enabled: true
maxQueuingTime: 500
tencent:
metadata:
content:
region: huanan

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>quickstart-example</artifactId>
<groupId>com.tencent.cloud</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>quickstart-callee-service-b</artifactId>
<name>Quickstart Callee Service B</name>
<dependencies>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-all</artifactId>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,48 @@
/*
* 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.quickstart.callee;
import java.util.Set;
import com.tencent.cloud.polaris.config.annotation.PolarisConfigKVFileChangeListener;
import com.tencent.cloud.polaris.config.listener.ConfigChangeEvent;
import org.springframework.stereotype.Component;
/**
* Custom Config Listener Example .
*
* @author Haotian Zhang
*/
@Component
public final class CustomConfigChangeListener {
/**
* PolarisConfigKVFileChangeListener Example .
* @param event instance of {@link ConfigChangeEvent}
*/
@PolarisConfigKVFileChangeListener(interestedKeyPrefixes = "appName")
public void onChange(ConfigChangeEvent event) {
Set<String> changedKeys = event.changedKeys();
for (String changedKey : changedKeys) {
System.out.printf("%s = %s \n", changedKey, event.getChange(changedKey));
}
}
}

@ -0,0 +1,46 @@
/*
* 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.quickstart.callee;
import java.util.HashMap;
import java.util.Map;
import com.tencent.cloud.common.spi.InstanceMetadataProvider;
import org.springframework.stereotype.Component;
/**
* Custom metadata for instance.
*
* @author Haotian Zhang
*/
@Component
public class CustomMetadata implements InstanceMetadataProvider {
@Override
public Map<String, String> getMetadata() {
Map<String, String> metadata = new HashMap<>();
metadata.put("k1", "v2");
return metadata;
}
@Override
public String getZone() {
return "shenzhen-zone-2";
}
}

@ -0,0 +1,81 @@
/*
* 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.quickstart.callee;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
/**
* Quickstart callee controller.
*
* @author Haotian Zhang
*/
@RestController
@RequestMapping("/quickstart/callee")
public class QuickstartCalleeController {
private static final Logger LOG = LoggerFactory.getLogger(QuickstartCalleeController.class);
@Value("${server.port:0}")
private int port;
@Value("${appName:Callee}")
private String appName;
/**
* Get sum of two value.
* @param value1 value 1
* @param value2 value 2
* @return sum
*/
@GetMapping("/sum")
public int sum(@RequestParam int value1, @RequestParam int value2) {
LOG.info("Quickstart Callee Service is called and sum is {}.", value1 + value2);
return value1 + value2;
}
/**
* Get information of callee.
* @return information of callee
*/
@GetMapping("/info")
public String info() {
LOG.info("Quickstart [{}] Service [{}] is called.", appName, port);
return String.format("Quickstart [%s] Service [%s] is called.", appName, port);
}
/**
* Check circuit break.
*
* @return circuit break info
*/
@GetMapping("/circuitBreak")
@ResponseStatus(value = HttpStatus.BAD_GATEWAY, reason = "failed for call quickstart callee service")
public String circuitBreak() {
LOG.info("Quickstart Callee Service [{}] is called wrong.", port);
return String.format("Quickstart Callee Service [%s] is called wrong.", port);
}
}

@ -0,0 +1,34 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.quickstart.callee;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* Quickstart callee application.
*
* @author Haotian Zhang
*/
@SpringBootApplication
public class QuickstartCalleeServiceB {
public static void main(String[] args) {
SpringApplication.run(QuickstartCalleeServiceB.class, args);
}
}

@ -0,0 +1,27 @@
server:
port: 48084
spring:
application:
name: QuickstartCalleeService
cloud:
polaris:
address: grpc://183.47.111.80:8091
namespace: default
enabled: true
discovery:
enabled: true
register: true
config:
address: grpc://183.47.111.80:8093
auto-refresh: true
groups:
- name: ${spring.application.name}
files: [ "config/callee.properties" ]
refresh-type: reflect
ratelimit:
enabled: true
maxQueuingTime: 500
tencent:
metadata:
content:
region: huanan

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>quickstart-example</artifactId>
<groupId>com.tencent.cloud</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>quickstart-caller-service</artifactId>
<name>Quickstart Caller Service</name>
<dependencies>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-all</artifactId>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,49 @@
/*
* 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.quickstart.caller;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
/**
* Quickstart callee feign client.
*
* @author Haotian Zhang
*/
@FeignClient(value = "QuickstartCalleeService", fallback = QuickstartCalleeServiceFallback.class)
public interface QuickstartCalleeService {
/**
* Get sum of two value.
*
* @param value1 value 1
* @param value2 value 2
* @return sum
*/
@GetMapping("/quickstart/callee/sum")
int sum(@RequestParam("value1") int value1, @RequestParam("value2") int value2);
/**
* Check circuit break.
*
* @return circuit break info
*/
@GetMapping("/quickstart/callee/circuitBreak")
String circuitBreak();
}

@ -0,0 +1,39 @@
/*
* 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.quickstart.caller;
import org.springframework.stereotype.Component;
/**
* Quickstart callee feign client fallback.
*
* @author Haotian Zhang
*/
@Component
public class QuickstartCalleeServiceFallback implements QuickstartCalleeService {
@Override
public int sum(int value1, int value2) {
return 0;
}
@Override
public String circuitBreak() {
return "CircuitBreak is triggered.";
}
}

@ -0,0 +1,45 @@
/*
* 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.quickstart.caller;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
/**
* Quickstart caller application.
*
* @author Haotian Zhang
*/
@SpringBootApplication
@EnableFeignClients
public class QuickstartCallerApplication {
public static void main(String[] args) {
SpringApplication.run(QuickstartCallerApplication.class, args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}

@ -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.quickstart.caller;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
/**
* Quickstart caller controller.
*
* @author Haotian Zhang
*/
@RestController
@RequestMapping("/quickstart/caller")
public class QuickstartCallerController {
private static final Logger LOG = LoggerFactory.getLogger(QuickstartCallerController.class);
@Autowired
private RestTemplate restTemplate;
@Autowired
private QuickstartCalleeService quickstartCalleeService;
/**
* Get sum of two value.
* @param value1 value 1
* @param value2 value 2
* @return sum
*/
@GetMapping("/feign")
public int feign(@RequestParam int value1, @RequestParam int value2) {
return quickstartCalleeService.sum(value1, value2);
}
/**
* Get information of callee.
* @return information of callee
*/
@GetMapping("/rest")
public String rest() {
return restTemplate.getForObject("http://QuickstartCalleeService/quickstart/callee/info", String.class);
}
/**
* Get information of callee.
* @return information of callee
*/
@GetMapping("/circuitBreak")
public String circuitBreak() {
return quickstartCalleeService.circuitBreak();
}
/**
* Get information 30 times per 1 second.
*
* @return result of 30 calls.
* @throws InterruptedException exception
*/
@GetMapping("/ratelimit")
public String invokeInfo() throws InterruptedException {
StringBuffer builder = new StringBuffer();
CountDownLatch count = new CountDownLatch(30);
AtomicInteger index = new AtomicInteger(0);
for (int i = 0; i < 30; i++) {
new Thread(() -> {
try {
ResponseEntity<String> entity = restTemplate.getForEntity(
"http://QuickstartCalleeService/quickstart/callee/info", String.class);
builder.append(entity.getBody() + "\n");
}
catch (RestClientException e) {
if (e instanceof HttpClientErrorException.TooManyRequests) {
builder.append("TooManyRequests " + index.incrementAndGet() + "\n");
}
else {
throw e;
}
}
count.countDown();
}).start();
}
count.await();
return builder.toString();
}
/**
* Get information with unirate.
*
* @return information
*/
@GetMapping("/unirate")
public String unirate() throws InterruptedException {
StringBuffer builder = new StringBuffer();
CountDownLatch count = new CountDownLatch(30);
AtomicInteger index = new AtomicInteger(0);
long currentTimestamp = System.currentTimeMillis();
for (int i = 0; i < 30; i++) {
new Thread(() -> {
try {
long startTimestamp = System.currentTimeMillis();
ResponseEntity<String> entity = restTemplate.getForEntity(
"http://QuickstartCalleeService/quickstart/callee/info", String.class);
long endTimestamp = System.currentTimeMillis();
builder.append("Start timestamp:" + startTimestamp + ". End timestamp: " + endTimestamp +
". diff interval:" + (endTimestamp - startTimestamp) + "\n");
}
catch (RestClientException e) {
if (e instanceof HttpClientErrorException.TooManyRequests) {
builder.append("TooManyRequests " + index.incrementAndGet() + "\n");
}
else {
throw e;
}
}
count.countDown();
}).start();
}
count.await();
long lastTimestamp = System.currentTimeMillis();
builder.append("Unirate request from " + currentTimestamp + " to " + lastTimestamp + " with interval " + (lastTimestamp - currentTimestamp) + "ms.");
return builder.toString();
}
/**
* Get information of callee.
* @return information of callee
*/
@GetMapping("/info")
public String info() {
LOG.info("Quickstart Callee Service is called.");
return "Quickstart Callee Service is called.";
}
/**
* health check.
* @return health check info
*/
@GetMapping("/healthCheck")
public String healthCheck() {
return "ok";
}
}

@ -0,0 +1,41 @@
server:
port: 48082
spring:
application:
name: QuickstartCallerService
cloud:
polaris:
address: grpc://183.47.111.80:8091
namespace: default
enabled: true
discovery:
enabled: true
register: true
heartbeat:
enabled: true
health-check-url: /quickstart/caller/healthCheck
circuitbreaker:
enabled: true
stat:
enabled: true
port: 28081
# pushgateway:
# enabled: true
# address: 127.0.0.1:9091
tencent:
rpc-enhancement:
enabled: true
reporter:
enabled: true
ignore-internal-server-error: true
series: server_error
statuses: gateway_timeout, bad_gateway, service_unavailable
feign:
hystrix:
enabled: true
management:
endpoints:
web:
exposure:
include:
- polaris-discovery

@ -0,0 +1,14 @@
consumer:
circuitBreaker:
checkPeriod: 100ms
chain:
- errorCount
- errorRate
plugin:
errorCount:
continuousErrorThreshold: 1
metricNumBuckets: 1
errorRate:
errorRateThreshold: 100
metricStatTimeWindow: 1s
requestVolumeThreshold: 1

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>quickstart-example</artifactId>
<groupId>com.tencent.cloud</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>quickstart-gateway-service</artifactId>
<name>Quickstart Gateway Service</name>
<dependencies>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-all</artifactId>
<type>pom</type>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-gateway-plugin</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

@ -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.quickstart.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* Quickstart SCG application.
*
* @author Haotian Zhang
*/
@SpringBootApplication
public class QuickstartGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(QuickstartGatewayApplication.class, args);
}
}

@ -0,0 +1,28 @@
server:
port: 48081
spring:
application:
name: QuickStartGatewayService
cloud:
tencent:
plugin:
scg:
staining:
enabled: true
rule-staining:
enabled: true
router:
feature-env:
enabled: true
polaris:
address: grpc://183.47.111.80:8091
namespace: default
enabled: true
gateway:
routes:
- id: QuickstartCallerService
uri: lb://QuickstartCallerService
predicates:
- Path=/QuickstartCallerService/**
filters:
- StripPrefix=1

@ -33,6 +33,7 @@ import com.tencent.polaris.api.core.ConsumerAPI;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
@ -42,6 +43,8 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Role;
import org.springframework.web.client.RestTemplate;
/**
@ -65,6 +68,7 @@ public class RpcEnhancementAutoConfiguration {
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(name = "org.springframework.cloud.openfeign.FeignAutoConfiguration")
@AutoConfigureBefore(name = "org.springframework.cloud.openfeign.FeignAutoConfiguration")
@Role(RootBeanDefinition.ROLE_INFRASTRUCTURE)
protected static class PolarisFeignClientAutoConfiguration {
@Bean
@ -74,7 +78,7 @@ public class RpcEnhancementAutoConfiguration {
}
@Bean
public EnhancedFeignBeanPostProcessor polarisFeignBeanPostProcessor(EnhancedFeignPluginRunner pluginRunner) {
public EnhancedFeignBeanPostProcessor polarisFeignBeanPostProcessor(@Lazy EnhancedFeignPluginRunner pluginRunner) {
return new EnhancedFeignBeanPostProcessor(pluginRunner);
}

@ -42,12 +42,10 @@ import org.springframework.core.Ordered;
public class ExceptionPolarisReporter implements EnhancedFeignPlugin {
private static final Logger LOG = LoggerFactory.getLogger(ExceptionPolarisReporter.class);
private final RpcEnhancementReporterProperties reporterProperties;
@Autowired(required = false)
private ConsumerAPI consumerAPI;
private RpcEnhancementReporterProperties reporterProperties;
public ExceptionPolarisReporter(RpcEnhancementReporterProperties reporterProperties) {
this.reporterProperties = reporterProperties;
}
@ -79,6 +77,9 @@ public class ExceptionPolarisReporter implements EnhancedFeignPlugin {
LOG.debug("Will report result of {}. Request=[{}]. Response=[{}].", retStatus.name(), request, response);
ServiceCallResult resultRequest = ReporterUtils.createServiceCallResult(request, retStatus);
consumerAPI.updateServiceCallResult(resultRequest);
// update result without method for service circuit break.
resultRequest.setMethod("");
consumerAPI.updateServiceCallResult(resultRequest);
}
}

@ -75,6 +75,9 @@ public class SuccessPolarisReporter extends AbstractPolarisReporterAdapter imple
LOG.debug("Will report result of {}. Request=[{}]. Response=[{}].", retStatus.name(), request, response);
ServiceCallResult resultRequest = ReporterUtils.createServiceCallResult(request, retStatus);
consumerAPI.updateServiceCallResult(resultRequest);
// update result without method for service circuit break.
resultRequest.setMethod("");
consumerAPI.updateServiceCallResult(resultRequest);
}
}

@ -133,6 +133,9 @@ public class EnhancedRestTemplateReporter extends AbstractPolarisReporterAdapter
LOGGER.debug("Will report result of {}. URL=[{}]. Response=[{}].", resultRequest.getRetStatus().name(),
url, response);
consumerAPI.updateServiceCallResult(resultRequest);
// update result without method for service circuit break.
resultRequest.setMethod("");
consumerAPI.updateServiceCallResult(resultRequest);
}
catch (Exception e) {
LOGGER.error("RestTemplate response reporter execute failed of {} url {}", response, url, e);

@ -121,7 +121,7 @@ public class EnhancedRestTemplateReporterTest {
URI uri = mock(URI.class);
enhancedRestTemplateReporter.handleError(uri, HttpMethod.GET, response);
verify(consumerAPI).updateServiceCallResult(any());
verify(consumerAPI, times(2)).updateServiceCallResult(any());
verify(delegate).handleError(uri, HttpMethod.GET, response);
}
@ -136,7 +136,7 @@ public class EnhancedRestTemplateReporterTest {
URI uri = mock(URI.class);
enhancedRestTemplateReporter.handleError(uri, HttpMethod.GET, response);
verify(consumerAPI).updateServiceCallResult(any());
verify(consumerAPI, times(2)).updateServiceCallResult(any());
verify(delegate, times(0)).handleError(uri, HttpMethod.GET, response);
}

Loading…
Cancel
Save