feat:first commit

pull/1/head
SkyeBeFreeman 3 years ago
parent e0868b2193
commit 9b68f05752

56
.gitignore vendored

@ -0,0 +1,56 @@
# Eclipse project files
.project
.classpath
.settings
# IntelliJ IDEA project files and directories
*.iml
*.ipr
*.iws
.idea/
# Build targets
/target
*/target
target
/applog
*/applog
applog
# Mac-specific directory that no other operating system needs.
.DS_Store
# JVM crash logs
hs_err_pid*.log
dependency-reduced-pom.xml
*/.unison.*
# exclude docker-sync stuff
.docker-sync
*/.docker-sync
# exclude vscode files
.vscode/
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.factorypath
# misc
*classes
*.class
.svn
logs/
lib/
applog/
# Maven ignore
.flattened-pom.xml
# Polaris
*/backup
/backup
backup

@ -0,0 +1,117 @@
/*
* Copyright 2007-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.
*/
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import java.util.Properties;
public class MavenWrapperDownloader {
private static final String WRAPPER_VERSION = "0.5.6";
/**
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
*/
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
/**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
* use instead of the default one.
*/
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
".mvn/wrapper/maven-wrapper.properties";
/**
* Path where the maven-wrapper.jar will be saved to.
*/
private static final String MAVEN_WRAPPER_JAR_PATH =
".mvn/wrapper/maven-wrapper.jar";
/**
* Name of the property which should be used to override the default download url for the wrapper.
*/
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
public static void main(String args[]) {
System.out.println("- Downloader started");
File baseDirectory = new File(args[0]);
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
// If the maven-wrapper.properties exists, read it and check if it contains a custom
// wrapperUrl parameter.
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
String url = DEFAULT_DOWNLOAD_URL;
if(mavenWrapperPropertyFile.exists()) {
FileInputStream mavenWrapperPropertyFileInputStream = null;
try {
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
Properties mavenWrapperProperties = new Properties();
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
} catch (IOException e) {
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
} finally {
try {
if(mavenWrapperPropertyFileInputStream != null) {
mavenWrapperPropertyFileInputStream.close();
}
} catch (IOException e) {
// Ignore ...
}
}
}
System.out.println("- Downloading from: " + url);
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
if(!outputFile.getParentFile().exists()) {
if(!outputFile.getParentFile().mkdirs()) {
System.out.println(
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
}
}
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
try {
downloadFileFromURL(url, outputFile);
System.out.println("Done");
System.exit(0);
} catch (Throwable e) {
System.out.println("- Error downloading");
e.printStackTrace();
System.exit(1);
}
}
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
String username = System.getenv("MVNW_USERNAME");
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
}
URL website = new URL(urlString);
ReadableByteChannel rbc;
rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(destination);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
rbc.close();
}
}

Binary file not shown.

@ -0,0 +1,2 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar

@ -0,0 +1,26 @@
# Contributing
---
If you have good comments or suggestions, welcome to create [Issues](https://github.com/Tencent/spring-cloud-tencent/issues) or [Pull Requests](https://github.com/Tencent/spring-cloud-tencent/pulls)contribute to the Spring Cloud Tencent open source community. Spring Cloud Tencent continues to recruit contributors, even if it is answering questions in the issue, or doing some simple bugfixes, it will be of great help to Spring Cloud Tencent.
[Tencent Open Source Incentive Program](https://opensource.tencent.com/contribution) Encourage developers to participate and contribute, and look forward to your joining.
## Issue
#### For contributors
Please ensure that the following conditions are met before submitting an issue:
* Must be a bug or new feature
* Have searched in the issue, and did not find a similar issue or solution
* When creating a new issue, please provide a detailed description, screenshot or short video to help us locate the problem
## Pull Request
We welcome everyone to contribute code to make our product more powerful. The code team will monitor all pull requests, and we will do the corresponding code inspection and testing. After the test passes, we will accept the PR, but will not immediately merge into the master branch.
Please confirm before completing a PR:
1. Fork your own branch from the master branch.
2. Please modify the corresponding documents and comments after modifying the code.
3. Please add License and Copyright declarations in the newly created file.
4. Ensure a consistent code style.
5. Do adequate testing.
6. Then, you can submit your code to the dev branch.

@ -0,0 +1,6 @@
# Spring Cloud Tencent Community Code of Conduct
Spring Cloud Tencent follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the Spring Cloud Tencent Code of Conduct Committee via email: SpringCloudTencent_Community@qq.com

@ -0,0 +1,105 @@
Tencent is pleased to support the open source community by making spring-cloud-tencent available.
Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
A spring-cloud-tencent is licensed under the BSD 3-Clause License. A copy of the BSD 3-Clause License is included in this file.
Terms of BSD 3-Clause License
---------------------------------------------------
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Other dependencies and licenses:
Open Source Software Licensed under the Apache License Version 2.0:
--------------------------------------------------------------------
1. spring-boot
Copyright (c) spring-boot authors and contributors.
2. spring-framework
Copyright (c) spring-framework authors and contributors.
3. spring-cloud-netflix
Copyright (c) spring-cloud-netflix authors and contributors.
4. spring-cloud config
Copyright (c) spring-cloud-config authors and contributors.
5. guava
Copyright (c) guava authors and contributors.
6. reactor
Copyright (c) reactor authors and contributors.
7. powermock
Copyright 2007-2017 PowerMock Contributors
Terms of the Apache v2.0 License:
--------------------------------------------------------------------
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
You must give any other recipients of the Work or Derivative Works a copy of this License; and
You must cause any modified files to carry prominent notices stating that You changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

@ -0,0 +1,73 @@
# Spring Cloud Tencent
Spring Cloud Tencent包含了分布式应用微服务开发过程中所需的组件基于 Spring Cloud 框架的开发者可以使用这些组件快速进行分布式应用的开发
在Spring Cloud Tencent的基础上您只需要添加少量配置就可以将 Spring Cloud 应用接入腾讯云微服务解决方案,通过腾讯云中间件来迅速搭建分布式应用系统。
## 主要功能
* **服务注册与发现**:基于 Spring Cloud Common的标准进行微服务的注册与发现
* **服务路由与负载均衡**:基于 Ribbon 的接口标准,提供场景更丰富的动态路由以及负载均衡的能力
* **故障节点熔断**:提供故障节点的熔断剔除以及主/被动探测恢复的能力,保证分布式服务的可靠性
* **服务限流**:支持工作于微服务被调接入层的限流功能,保证后台微服务稳定性,可通过控制台动态配置规则,及查看流量监控数据
## 组件
**[Polaris](https://github.com/polarismesh)**:北极星云原生的服务治理平台,解决远程调用的服务注册发现、动态路由、负载均衡和容错问题。
## 如何构建
* master 分支对应的是 Spring Cloud Hoxton最低支持 JDK 1.8。
Spring Cloud Tencent 使用 Maven 来构建,最快的使用方式是将本项目 clone 到本地,然后执行以下命令:
```bash
./mvnw install
```
执行完毕后,项目将被安装到本地 Maven 仓库。
## 如何使用
### 如何引入依赖
在 dependencyManagement 中添加如下配置,然后在 dependencies 中添加自己所需使用的依赖即可使用。
````
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-dependencies</artifactId>
<!--版本号需修改成实际依赖的版本号-->
<version>${version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
````
### 示例
Spring Cloud Tencent 项目包含了一个子模块spring-cloud-tencent-examples。此模块中提供了体验接入用的 example ,您可以阅读对应的 example 工程下的 readme 文档,根据里面的步骤来体验。
Example 列表:
- [Polaris Discovery Example](spring-cloud-tencent-examples/polaris-discovery-example/README.md)
- [Polaris CircuitBreaker Example](spring-cloud-tencent-examples/polaris-circuitbreaker-example/README.md)
- [Polaris RateLimit Example](spring-cloud-tencent-examples/polaris-ratelimit-example/README.md)
## 版本号规范
采取与Spring Cloud大版本号相关的版本策略。
项目的版本号格式为 ```大版本号.小版本号.补丁版本号.对应Spring Cloud版本号.发布类型``` 的形式。
大版本号、小版本号、补丁版本号的类型为数字,从 0 开始取值。项目处于孵化器阶段时,大版本号固定使用 0 。
对应Spring Cloud版本号为Spring Cloud提供的英文版本号例如Hoxton、Greenwich等。
发布类型包括正式发布RELEASE、最终测试版RC、测试版BETA
示例0.1.0.Hoxton.BETA
## License
The spring-cloud-tencent is licensed under the BSD 3-Clause License. Copyright and license information can be found in the file [LICENSE](LICENSE)

@ -1 +1,75 @@
# Spring Cloud Tencent
Spring Cloud Tencent contains components distributed micro-service applications need during developing phase, developers that built their key architectures based on Spring Cloud can use these components
Based on Spring Cloud Tencent, you only need a small configuration to launch Spring Cloud and micro-service's joint solutions.
## Key Features
* **Service Registration and Discovery**Based on Spring Cloud's discovery and registration standard.
* **Service Routing and LoadBalancer**Based on ribbon's API port, provide dynamic routing and load balancing use cases.
* **CircuitBreaker Node**Support circuitbreak's auto-reset ability, ensure the reliability of distributed server
* **Rate Limiter**Support rate limit between microservice and access layer, ensure the stability of backend, one can configure policies and traffic data from the control panel
## component
**[Polaris](https://github.com/polarismesh)**Polaris Spring Cloud operation centre, provide solutions to registration, dynamic routing, load balancing and circuitbreaker.
## How to build
* master's branch matches Spring Cloud Hoxton, support lowest at JDK 1.8.
Spring Cloud Tencent uses Maven to construct, the fastest way is to cone project to local files, then execute the following orders:
```bash
./mvnw install
```
When all the steps are finished, the project will be installed in local Maven repository.
## How to Use
### How to Introduce Dependency
Add the following configurations n dependencyManagement, then add the dependencies you need.
````
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-dependencies</artifactId>
<!--version number-->
<version>${version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
````
### Example
Spring Cloud Tencent project contains a sub-module spring-cloud-tencent-examples. This module provides examples for users to experience, you can read the README.md in each example, and follow the instructions there.
Example List:
- [Polaris Discovery Example](spring-cloud-tencent-examples/polaris-discovery-example/README.md)
- [Polaris CircuitBreaker Example](spring-cloud-tencent-examples/polaris-circuitbreaker-example/README.md)
- [Polaris RateLimit Example](spring-cloud-tencent-examples/polaris-ratelimit-example/README.md)
### Version Standard
Adopt a version policy related to Spring Cloud's major version number
Project version includes major version. minor version. patch version. Correspond with the version of Spring Cloud release.
major version. minor version. patch version are in numbers, start from 0. This project is in the incubating phase, major version number is set to 0.
Spring Cloud's version number is the same as the English version number, like Hoxton, Greenwich.
Release type will include RELEASE, RC, BETA.
For example: 0.1.0.Hoxton.BETA
## License
The spring-cloud-tencent is licensed under the BSD 3-Clause License. Copyright and license information can be found in the file [LICENSE](LICENSE)

310
mvnw vendored

@ -0,0 +1,310 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# 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.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Maven Start Up Batch script
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# M2_HOME - location of maven2's installed home dir
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "`uname`" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
export JAVA_HOME="`/usr/libexec/java_home`"
else
export JAVA_HOME="/Library/Java/Home"
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=`java-config --jre-home`
fi
fi
if [ -z "$M2_HOME" ] ; then
## resolve links - $0 may be a link to maven's home
PRG="$0"
# need this for relative symlinks
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG="`dirname "$PRG"`/$link"
fi
done
saveddir=`pwd`
M2_HOME=`dirname "$PRG"`/..
# make it fully qualified
M2_HOME=`cd "$M2_HOME" && pwd`
cd "$saveddir"
# echo Using m2 at $M2_HOME
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --unix "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
[ -n "$M2_HOME" ] &&
M2_HOME="`(cd "$M2_HOME"; pwd)`"
[ -n "$JAVA_HOME" ] &&
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="`which javac`"
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=`which readlink`
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
if $darwin ; then
javaHome="`dirname \"$javaExecutable\"`"
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
else
javaExecutable="`readlink -f \"$javaExecutable\"`"
fi
javaHome="`dirname \"$javaExecutable\"`"
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="`which java`"
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=`cd "$wdir/.."; pwd`
fi
# end of workaround
done
echo "${basedir}"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
echo "$(tr -s '\n' ' ' < "$1")"
fi
}
BASE_DIR=`find_maven_basedir "$(pwd)"`
if [ -z "$BASE_DIR" ]; then
exit 1;
fi
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found .mvn/wrapper/maven-wrapper.jar"
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
fi
if [ -n "$MVNW_REPOURL" ]; then
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
else
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
fi
while IFS="=" read key value; do
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
esac
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
if [ "$MVNW_VERBOSE" = true ]; then
echo "Downloading from: $jarUrl"
fi
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
if $cygwin; then
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
fi
if command -v wget > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found wget ... using wget"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget "$jarUrl" -O "$wrapperJarPath"
else
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found curl ... using curl"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl -o "$wrapperJarPath" "$jarUrl" -f
else
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Falling back to using Java to download"
fi
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaClass=`cygpath --path --windows "$javaClass"`
fi
if [ -e "$javaClass" ]; then
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Compiling MavenWrapperDownloader.java ..."
fi
# Compiling the Java class
("$JAVA_HOME/bin/javac" "$javaClass")
fi
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
# Running the downloader
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Running MavenWrapperDownloader.java ..."
fi
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
fi
fi
fi
fi
##########################################################################################
# End of extension
##########################################################################################
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
if [ "$MVNW_VERBOSE" = true ]; then
echo $MAVEN_PROJECTBASEDIR
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --path --windows "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \
$MAVEN_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

182
mvnw.cmd vendored

@ -0,0 +1,182 @@
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM http://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %DOWNLOAD_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%" == "on" pause
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
exit /B %ERROR_CODE%

@ -0,0 +1,167 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-build</artifactId>
<version>2.3.4.RELEASE</version>
<relativePath/>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent</artifactId>
<packaging>pom</packaging>
<version>${revision}</version>
<name>Spring Cloud Tencent</name>
<description>Spring Cloud Tencent</description>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>
<modules>
<module>spring-cloud-tencent-dependencies</module>
<module>spring-cloud-tencent-starters</module>
<module>spring-cloud-tencent-examples</module>
<module>spring-cloud-tencent-docs</module>
<module>spring-cloud-tencent-converage</module>
</modules>
<developers>
<developer>
<id>SkyeBeFreeman</id>
<name>Haotian Zhang</name>
<email>928016560@qq.com</email>
<organization>Tencent</organization>
<url>https://github.com/SkyeBeFreeman/</url>
</developer>
</developers>
<properties>
<!-- Project revision -->
<revision>0.1.0.Hoxton.BETA</revision>
<!-- Spring Cloud -->
<spring.cloud.version>Hoxton.SR9</spring.cloud.version>
<!-- Polaris -->
<polaris.cient.version>0.8.0-SNAPSHOT</polaris.cient.version>
<!-- Maven Plugin Versions -->
<maven-compiler-plugin.version>3.7.0</maven-compiler-plugin.version>
<maven-surefire-plugin.version>2.21.0</maven-surefire-plugin.version>
<maven-source-plugin.version>3.2.0</maven-source-plugin.version>
<flatten-maven-plugin.version>1.1.0</flatten-maven-plugin.version>
<jacoco.version>0.8.3</jacoco.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- Spring Boot Dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Spring Cloud Dependencies -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Spring Cloud Tencent Dependencies -->
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-dependencies</artifactId>
<version>${revision}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<inherited>true</inherited>
<configuration>
<source>1.8</source>
<target>1.8</target>
<parameters>true</parameters>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<inherited>true</inherited>
<configuration>
<forkCount>1</forkCount>
<reuseForks>false</reuseForks>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>${maven-source-plugin.version}</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>flatten-maven-plugin</artifactId>
<version>${flatten-maven-plugin.version}</version>
<configuration>
<updatePomFile>true</updatePomFile>
<flattenMode>resolveCiFriendliesOnly</flattenMode>
</configuration>
<executions>
<execution>
<id>flatten</id>
<phase>process-resources</phase>
<goals>
<goal>flatten</goal>
</goals>
</execution>
<execution>
<id>flatten.clean</id>
<phase>clean</phase>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>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-tencent-converage</artifactId>
<name>Spring Cloud Tencent Converage</name>
<dependencies>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-commons</artifactId>
</dependency>
<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-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-tencent-metadata</artifactId>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-feign</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-tencent-polaris-context</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<executions>
<execution>
<id>report-aggregate</id>
<phase>test</phase>
<goals>
<goal>report-aggregate</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/../target/site/jacoco</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,167 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies-parent</artifactId>
<version>2.3.1.RELEASE</version>
<relativePath/>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-dependencies</artifactId>
<version>0.1.0.Hoxton.BETA</version>
<packaging>pom</packaging>
<name>Spring Cloud Tencent Dependencies</name>
<description>Spring Cloud Tencent Dependencies</description>
<properties>
<revision>0.0.1-SNAPSHOT</revision>
<polaris.version>0.8.0-SNAPSHOT</polaris.version>
<tomcat.version>10.0.0-M6</tomcat.version>
<powermock.version>2.0.0</powermock.version>
<!-- Maven Plugin Versions -->
<maven-source-plugin.version>3.2.0</maven-source-plugin.version>
<maven-javadoc-plugin.version>3.1.1</maven-javadoc-plugin.version>
<flatten-maven-plugin.version>1.1.0</flatten-maven-plugin.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<artifactId>polaris-dependencies</artifactId>
<groupId>com.tencent.nameservice</groupId>
<version>${polaris.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-websocket</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-commons</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-ratelimit</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-circuitbreaker</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-router</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-polaris-context</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-metadata</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-feign</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-discovery</artifactId>
<version>${revision}</version>
</dependency>
<!-- powermock-module-junit4 -->
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>${powermock.version}</version>
</dependency>
<!-- powermock-api-mockito -->
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>${powermock.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>${maven-source-plugin.version}</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>${maven-javadoc-plugin.version}</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>flatten-maven-plugin</artifactId>
<version>${flatten-maven-plugin.version}</version>
<configuration>
<updatePomFile>true</updatePomFile>
<flattenMode>resolveCiFriendliesOnly</flattenMode>
</configuration>
<executions>
<execution>
<id>flatten</id>
<phase>process-resources</phase>
<goals>
<goal>flatten</goal>
</goals>
</execution>
<execution>
<id>flatten.clean</id>
<phase>clean</phase>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>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-tencent-docs</artifactId>
<name>Spring Cloud Tencent Documentation</name>
<packaging>pom</packaging>
</project>

@ -0,0 +1,17 @@
# 依赖管理
如果您想使用Spring Cloud Tencent微服务开发套件您可以直接依赖以下bom即在pom.xml的<dependencyManagement>中添加如下代码。后续使用bom下的依赖无需带版本号即可引入。
```xml
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-dependencies</artifactId>
<version>0.1.0.Hoxton.BETA</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
```

@ -0,0 +1,59 @@
# Spring Cloud Tencent Metadata
## 使用方式
### 可传递的自定义metadata
> 可以从主调方传递给被调方的metadata
- 获取只读的所有可传递的自定义metadata的映射表
```
Map<String, String> customMetadataMap = MetadataContextHolder.get().getAllTransitiveCustomMetadata();
```
- 根据key获取可传递的自定义metadata
```
String value = MetadataContextHolder.get().getTransitiveCustomMetadata(KEY);
```
- 以key-value形式保存可传递的自定义metadata
```
MetadataContextHolder.get().putTransitiveCustomMetadata(KEY, VALUE);
```
- 从一个映射表中读取并保存到可传递的自定义metadata映射表中
```
MetadataContextHolder.get().putAllTransitiveCustomMetadata(ANOTHER_MAP);
```
### 系统metadata
> 系统metadata不可被传递。
- 获取只读的所有系统metadata的映射表
```
Map<String, String> systemMetadataMap = MetadataContextHolder.get().getAllSystemMetadata();
```
- 根据key获取系统metadata
```
String value = MetadataContextHolder.get().getSystemMetadata(KEY);
```
- 以key-value形式保存系统metadata
```
MetadataContextHolder.get().putSystemMetadata(KEY, VALUE);
```
- 从一个映射表中读取并保存到系统metadata映射表中
```
MetadataContextHolder.get().putAllSystemMetadata(ANOTHER_MAP);
```
- 系统metadata映射表的key如下所示
- LOCAL_NAMESPACE
- LOCAL_SERVICE
- LOCAL_PATH
- PEER_NAMESPACE
- PEER_SERVICE
- PEER_PATH

@ -0,0 +1,43 @@
# Polaris CircuitBreaker
## 模块简介
```spring-cloud-starter-tencent-polaris-circuitbreaker```是用于Spring
Cloud项目对接服务治理平台[Polaris](https://github.com/polarismesh)的故障熔断模块。
您可以通过引入依赖即可获得对微服务架构的服务限流能力。建议与```spring-cloud-starter-tencent-polaris-discovery```配合使用。
## 功能介绍
### 故障节点熔断
故障实例熔断能实现主调方迅速自动屏蔽错误率高或故障的服务实例,并启动定时任务对熔断实例进行探活。在达到恢复条件后对其进行半开恢复。在半开恢复后,释放少量请求去进行真实业务探测。并根据真实业务探测结果去判断是否完全恢复正常。
### 熔断策略
- 故障比例熔断当服务实例在上一个时间窗默认1分钟通过的请求量达到或超过最小请求阈值默认10个且错误率达到或超过故障比率阈值默认50%),实例会进入隔离状态。故障比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。
- 连续故障熔断当实例在上一个时间窗默认1分钟连续失败的请求数达到或者超过连续故障阈值默认10个实例会进入隔离状态。
- 熔断隔离时间默认隔离30s支持可配置。
相关配置请参考[Polaris故障熔断相关文档](https://github.com/polarismesh)
## 快速入门
本章节将介绍如何最简单地在Spring Cloud项目中使用Polaris
CircuitBreaker的功能。启动微服务之前需要启动Polaris具体启动方式参考[Polaris](https://github.com/polarismesh)。
1. 您可以在项目中加入```spring-cloud-starter-tencent-polaris-circuitbreaker```依赖即可使用故障熔断的特性。如Maven项目中在pom中添加如下配置
```XML
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-circuitbreaker</artifactId>
</dependency>
```
2. 更加详细的使用方法参考 [Polaris CircuitBreaker Example](../../../../spring-cloud-tencent-examples/polaris-circuitbreaker-example/README-zh.md)。
## 配置列表
| 配置项Key | 默认值 |是否必填| 配置项说明 |
| ----------------------------------------------- | -----------------------| --------- | ---------------------------- |
| spring.cloud.polaris.circuitbreaker.enabled | true |否| 是否开启故障熔断 |

@ -0,0 +1,88 @@
# Polaris Discovery
## 模块简介
```spring-cloud-starter-tencent-polaris-discovery```是用于Spring
Cloud项目对接服务治理平台[Polaris](https://github.com/polarismesh)的服务发现模块。您可以通过引入依赖即可完成微服务注册到服务治理平台Polaris获得对整个微服务架构的服务治理能力。
## 功能介绍
### 服务注册与发现
基于Spring Cloud的标准接口实现服务注册与发现。
### 服务路由
基于Ribbon的标准接口实现的支持多种场景的动态服务路由是北极星提供规则路由的能力通过规则来动态控制消息的分配转发。通过该功能您者可以轻松实现多环境路由、分SET路由、灰度发布、集群容灾降级、金丝雀测试等功能。
同时,用户也可以利用独立于服务发现模块的自定义元数据功能来形成路由规则进行规则路由,进一步提升服务路由的灵活性。
### 负载均衡
负载均衡支持从满足本次转发要求的服务实例集中, 通过一定的均衡策略,选取一个实例返回给主调方,供主调方进行服务请求发送。负载均衡规则包括权重随机策略、权重响应时间策略和一致性哈希算法。
## 快速入门
本章节将介绍如何最简单地在Spring Cloud项目中使用Polaris
Discovery的功能。启动微服务之前需要启动Polaris具体启动方式参考[Polaris](https://github.com/polarismesh)。
1. 您可以在项目中加入```spring-cloud-starter-tencent-polaris-discovery```依赖即可使用Polaris的服务注册与发现功能。如Maven项目中在pom中添加如下配置
```XML
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-discovery</artifactId>
</dependency>
```
2. 在配置文件中主要添加如下配置即可完成服务注册与发现在Spring Cloud Edgware之后无需使用```@EnableDiscoveryClient```即可进行服务注册与发现):
```yaml
spring:
application:
name: ${application.name}
cloud:
polaris:
address: ${protocol}://${ip}:${port}
```
更加详细的使用方法参考 [Polaris Discovery Example](../../../../spring-cloud-tencent-examples/polaris-discovery-example/README-zh.md)。
## 拓展使用
### 服务路由
- 您可以在Polaris控制台页面上配置路由规则即可使用服务路由的功能。
- 您也可以在配置文件application.yml中添加自定义元数据然后再Polaris控制台页面上配置路由规则也可使用服务路由的功能。样例配置如下所示在应用运行时将读为Map的数据格式。
```
spring:
cloud:
tencent:
content:
a: 1
b: 2
```
### 负载均衡
以权重随机策略为例您可以在Polaris控制台页面上或者配置文件application.yml中添加权重值即可使用负载均衡的功能。
## 配置列表
| 配置项Key | 默认值 |是否必填| 配置项说明 |
| ----------------------------------------------- | -----------------------| --------- | ---------------------------- |
| spring.cloud.polaris.server-addr | 无 |是| Polaris后端地址 |
| spring.cloud.polaris.discovery.service | ${spring.application.name} |否| 服务名称 |
| spring.cloud.polaris.discovery.enabled | true |否| 是否开启服务注册与发现 |
| spring.cloud.polaris.discovery.instance-enabled | true |否| 当前微服务实例是否可以被访问 |
| spring.cloud.polaris.discovery.token | 无 |否| 鉴权Token |
| spring.cloud.polaris.discovery.version | null |否| 微服务版本 |
| spring.cloud.polaris.protocol | null |否| 微服务协议类型 |
| spring.cloud.polaris.weight | 100 |否| 微服务权重 |
| spring.cloud.loadbalancer.polaris.enabled | true |否| 是否开启负载均衡 |
| spring.cloud.loadbalancer.polaris.strategy | weighted_random |否| 负载均衡策略 |
| spring.cloud.tencent.metadata.content | 无 |否| 自定义元数据为Map结构 |
| spring.cloud.tencent.metadata.transitive | 无 |否| 需要传递的自定义元数据的key列表为List结构 |

@ -0,0 +1,48 @@
# Polaris RateLimit
## 模块简介
```spring-cloud-starter-tencent-polaris-ratelimit```是用于Spring
Cloud项目对接服务治理平台[Polaris](https://github.com/polarismesh)的服务限流模块。
您可以通过引入依赖即可获得对微服务架构的服务限流能力。建议与```spring-cloud-starter-tencent-polaris-discovery```配合使用。
## 功能介绍
### 服务级限流
支持为所有的HTTP服务提供限流功能。
默认引入spring-cloud-starter-tencent-polaris-ratelimit依赖即可对所有的HTTP服务执行限流检查。
### 接口级限流
支持为所有的HTTP调用根据path级别的提供限流功能。
默认引入spring-cloud-starter-tencent-polaris-ratelimit依赖即可对所有的HTTP path调用执行限流检查。
## 快速入门
本章节将介绍如何最简单地在Spring Cloud项目中使用Polaris
RateLimit的功能。启动微服务之前需要启动Polaris具体启动方式参考[Polaris](https://github.com/polarismesh)。
1. 您可以在项目中加入```spring-cloud-starter-tencent-polaris-ratelimit```依赖即可使用服务限流的特性。如Maven项目中在pom中添加如下配置
```XML
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-ratelimit</artifactId>
</dependency>
```
2. 添加限流规则配置
北极星提供了三种添加限流配置的方式包括控制台操作、HTTP接口上传和本地文件配置具体请参考[北极星服务限流使用文档](https://github.com/polarismesh)
更加详细的使用方法参考 [Polaris RateLimit Example](../../../../spring-cloud-tencent-examples/polaris-ratelimit-example/README-zh.md)。
## 配置列表
| 配置项Key | 默认值 |是否必填| 配置项说明 |
| ----------------------------------------------- | -----------------------| --------- | ---------------------------- |
| spring.cloud.polaris.ratelimit.enabled | true |否| 是否开启服务限流 |

@ -0,0 +1,18 @@
# dependencyManagement
if you want to use Spring Cloud Tencent micro-service software development kit, you can depend on the bom as below, add code as below at ```<dependencyManagement>``` in pom.xml. Going forward, continue using dependencies in bom no longer needs version number.
```xml
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-dependencies</artifactId>
<version>0.1.0.Hoxton.BETA</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
```

@ -0,0 +1,59 @@
# Spring Cloud Tencent Metadata
## Usage
### Transitive Custom Metadata
> Transitive custom metadata can be transferred from caller to callee.
- Get all transitive custom metadata with read-only.
```
Map<String, String> customMetadataMap = MetadataContextHolder.get().getAllTransitiveCustomMetadata();
```
- Get transitive custom metadata with key.
```
String value = MetadataContextHolder.get().getTransitiveCustomMetadata(KEY);
```
- Put transitive custom metadata with key-value.
```
MetadataContextHolder.get().putTransitiveCustomMetadata(KEY, VALUE);
```
- Put transitive custom metadata with another map.
```
MetadataContextHolder.get().putAllTransitiveCustomMetadata(ANOTHER_MAP);
```
### System Metadata
> System metadata cannot be transferred.
- Get all system metadata with read-only.
```
Map<String, String> systemMetadataMap = MetadataContextHolder.get().getAllSystemMetadata();
```
- Get system metadata with key.
```
String value = MetadataContextHolder.get().getSystemMetadata(KEY);
```
- Put system metadata with key-value.
```
MetadataContextHolder.get().putSystemMetadata(KEY, VALUE);
```
- Put system metadata with another map.
```
MetadataContextHolder.get().putAllSystemMetadata(ANOTHER_MAP);
```
- Map key list:
- LOCAL_NAMESPACE
- LOCAL_SERVICE
- LOCAL_PATH
- PEER_NAMESPACE
- PEER_SERVICE
- PEER_PATH

@ -0,0 +1,43 @@
# Polaris CircuitBreaker
## Module Intro
```spring-cloud-starter-tencent-polaris-circuitbreaker```is applied to Spring
Cloud project joint with [Polaris](https://github.com/polarismesh)'s CircuitBreaker module you can get cloud service engine's rate limit ability by introducing dependency. Recommended using with ```spring-cloud-starter-tencent-polaris-discovery```.
## Key Features
### Failed Node CircuitBreaker
Failed instance circuitbreak can achieve caller service's immediate auto-block high failure rate command instance, and set timed task to conduct live probing. When the recover status is achieved, one can start half recovery. After half recovery, release a few request to test probing. Identify the recovery status from the probing result.
### CircuitBreaker Strategy
- Failed ratio circuitbreak: when command instance at a service window (default one minute) request rate has reached or passed the minimum request threshold (default 10), and failure rate reached or passed failure ratio threshold (default 50%), instance will enter insolation state. Failure rate threshold range is [0.0, 1.0] , represent 0% - 100%.
- continuous failure circuitbreak: when command instance at a service window (default), continuous failure request reached or exceeded failure threshold (default 10), instance will inter insolation state.
- circuitbreak insolation time: default 30 seconds, support configuration
For configuration, please refer to [Polaris CircuitBreaker](https://github.com/polarismesh)
## User Guide
This chapter will explain how to use Polaris in Spring Cloud project in the simplest way.
CircuitBreaker's feature. Before starting MicroService, one needs to activate Polaris, activation details please refer to [Polaris](https://github.com/polarismesh).
1. you can add ```spring-cloud-starter-tencent-polaris-circuitbreaker``` 's dependencies in your project to use CircuitBreaker features. For example, in Maven's project, add listed configurations in pom:
```XML
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-circuitbreaker</artifactId>
</dependency>
```
2. For further instructions, please refer to [Polaris CircuitBreaker Example](../../../../spring-cloud-tencent-examples/polaris-circuitbreaker-example/README.md).
## Configuration List
| Configuration Key | default | Must Fill | Configuration Instruction |
| ------------------------------------------- | ------- | --------- | ---------------------------- |
| spring.cloud.polaris.circuitbreaker.enabled | true | false | Whether turn on CircuitBreak |

@ -0,0 +1,85 @@
# Polaris Discovery
## Module Intro
```spring-cloud-starter-tencent-polaris-discovery``` is used in Spring Cloud project joint with [Polaris](https://github.com/polarismesh)'s Polaris Discovery component. You can complete Microservice registration at Polaris through dependencies, get visibility and control to the entire Cloud Service Engine.
## Features Instruction
### Service Registration and Discovery
Spring Cloud API to achieve service registration and discovery.
### Service Route
Foundation built on Ribbon's API allows multiple application's dynamic service route, provided by Polaris's policy route feature. One can assign and control tasks through this feature. Through this feature, one can easily adapt different applications, SET routing, greyscale release, disaster recovery degrade, and canary test etc.
Meanwhile, users can use independent discovery component's custom data feature to program routing, further improve its agility and performance.
### CLoud Load Balance
CLB supports qualified packet forwarding in the service instance. Through set balancing, send a selected instance to the caller service, to support caller's service request. CLB rule includes random weight policy, weight response time and coordinated Hash.
## User Guide
This chapter will explain how to use Polaris Discovery's features in the Spring Cloud project. Before starting MicroService, one needs to activate Polaris, activation details please refer to [Polaris](https://github.com/polarismesh).
1. you can add ```spring-cloud-starter-tencent-polaris-discovery```'s 's dependencies in your project to use Polaris's service registration and discovery feature. For example, in Maven's project, add listed configurations in pom:
```XML
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-discovery</artifactId>
</dependency>
```
2. Add listed configurations in the document, one can complete service registration and discovery (after Spring Cloud Edgware, ```@EnableDiscoveryClient``` is no longer needed to run service registration and discovery):
```yaml
spring:
application:
name: ${application.name}
cloud:
polaris:
server-addr: ${ip}:${port}
```
For further instructions, please refer to [Polaris Discovery Example](../../../../spring-cloud-tencent-examples/polaris-discovery-example/README.md).
## Extended Application
### Service Route
- you can configure routing policy at Polaris control panel, and use the features.
- you can add custom metadata at configure documentations (application.yml), Then configure routing policy at Polaris control panel, one can also use the features. Example listed below, this will be read as Metadata Map.
```
spring:
cloud:
tencent:
content:
a: 1
b: 2
```
### Cloud Load Balancing
Taking examples like random weight policy, you can add weight at Polaris control panel or configure documentations (application.yml) to access CLB features.
## Configuration LIst
| ConfigurationKey | default | Yes/No required | Configuration Instruction |
| ----------------------------------------------- | -------------------------- | --------------- | ---------------------------------------------------- |
| spring.cloud.polaris.server-addr | false | yes | Polaris backend address |
| spring.cloud.polaris.discovery.service | ${spring.application.name} | null | service name |
| spring.cloud.polaris.discovery.enabled | true | false | whether to active service registration and discovery |
| spring.cloud.polaris.discovery.instance-enabled | true | false | can current Microservice be visited |
| spring.cloud.polaris.discovery.token | false | false | Authentication Token |
| spring.cloud.polaris.discovery.version | null | false | Microservice Version |
| spring.cloud.polaris.protocol | null | false | Microservice agreement type |
| spring.cloud.polaris.weight | 100 | false | Microservice weight |
| spring.cloud.loadbalancer.polaris.enabled | true | false | whether to open CLB |
| spring.cloud.loadbalancer.polaris.strategy | weighted_random | false | CLB policy |
| spring.cloud.tencent.metadata.content | null | false | custom metadata Map |
| spring.cloud.tencent.metadata.transitive | null | false | need custom metadata key list |

@ -0,0 +1,47 @@
# Polaris RateLimit
## Module Introduction
```spring-cloud-starter-tencent-polaris-ratelimit``` is used in Spring
Cloud project joint with [Polaris](https://github.com/polarismesh)'s rate limit component.
You can access Microservice's rate limit through dependencies. Recommended using with ```spring-cloud-starter-tencent-polaris-discovery```
## Features Introduction
### Service Rate Limit
Provide rate limit feature to all HTTP server.
Default introduce spring-cloud-starter-tencent-polaris-ratelimit dependencies can apply rate limit check to all HTTP server.
### API Rate Limit
Provide rate limit feature to all HTTP server depending on the path level
Default introduce spring-cloud-starter-tencent-polaris-ratelimit dependencies can apply rate limit check to all HTTP server path.
## User Guide
This chapter will explain how to use Polaris RateLimit in Spring Cloud project with the easiest way. Before starting MicroService, one needs to activate Polaris, activation details please refer to [Polaris](https://github.com/polarismesh).
1. you can add ```spring-cloud-starter-tencent-polaris-ratelimit```s dependencies in your project to use the rate limit feature. For example, in Maven's project, add listed:
```XML
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-ratelimit</artifactId>
</dependency>
```
2. Add rate limit configuration
Polaris provides three different configuration methods, control panel operation, HTTP API upload and local files configuration, further information please refer to [Polaris service rate limit operation guide](https://github.com/polarismesh)
For more details, please refer to [Polaris RateLimit Example](../../../../spring-cloud-tencent-examples/polaris-ratelimit-example/README.md)
## Configuration list
| Configuration Key | default | yes/no required | Configuration Instruction |
| -------------------------------------- | ------- | --------------- | ----------------------------- |
| spring.cloud.polaris.ratelimit.enabled | true | false | whether to turn on rate limit |

@ -0,0 +1,78 @@
# Spring Cloud Polaris CircuitBreaker Example
## 样例简介
本样例将介绍如何在Spring Cloud项目中使用```spring-cloud-starter-tencent-polaris-circuitbreaker```以使用其各项功能。
该样例分为两个微服务即polaris-circuitbreaker-example-a和polaris-circuitbreaker-example-b。其中polaris-circuitbreaker-example-a对polaris-circuitbreaker-example-b发生调用。
## 使用说明
### 修改配置
在两个微服务的```src/main/resources```下的```bootstrap.yml```文件中添加如下配置。其中,${ip}和${port}为Polaris后端服务的IP地址与端口号。
```yaml
spring:
application:
name: ${application.name}
cloud:
polaris:
server-addr: ${ip}:${port}
```
### 启动样例
#### 启动Polaris后端服务
参考[Polaris](https://github.com/polarismesh)。
#### 启动应用
注意,由于需要验证熔断功能,因此需要部署两个及以上的被调服务(样例中部署两个即可)。
- IDEA启动
分别启动```spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-example-a```下的```ServiceA```和```spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-example-b```下的```ServiceB```。
注意ServiceB需要启动两个。同机器上可以修改端口号来实现。
两个ServiceB的com.tencent.cloud.polaris.circuitbreaker.example.ServiceBController.info的逻辑需不同即一个正常返回一个抛出异常。
- Maven打包启动
在```spring-cloud-tencent-examples/polaris-discovery-example```下执行
注意ServiceB需要启动两个。同机器上可以修改端口号来实现。
两个ServiceB的com.tencent.cloud.polaris.circuitbreaker.example.ServiceBController.info的逻辑需不同即一个正常返回一个抛出异常。
```sh
mvn clean package
```
然后在```polaris-circuitbreaker-example-a```和```polaris-circuitbreaker-example-b```下找到生成的jar包运行
```
java -jar ${app.jar}
```
启动应用,其中${app.jar}替换为对应的jar包名。
### 验证
#### Feign调用
执行以下命令发起Feign调用其逻辑为```ServiceB```抛出一个异常
```shell
curl -L -X GET 'localhost:48080/example/service/a/getBServiceInfo'
```
预期返回情况:
在出现
```
trigger the refuse for service b
```
表示请求到有异常的ServiceB需要熔断这个实例。后面的所有请求都会得到正常返回。

@ -0,0 +1,79 @@
# Spring Cloud Polaris CircuitBreaker Example
## Example Introduction
The examples will explain how to use```spring-cloud-starter-tencent-polaris-circuitbreaker``` in Spring Cloud project and other features
This example is divided to two microservice, ```polaris-circuitbreaker-example-a``` and ```polaris-circuitbreaker-example-b```. In these two microservices, ```polaris-circuitbreaker-example-a``` invokes ```polaris-circuitbreaker-example-b```.
## Instruction
### Configuration
```src/main/resources``` and ```bootstrap.yml``` of two micro-services add the following instructions. ${ip} and ${port} are Polaris backend IP address and port number.
```yaml
spring:
application:
name: ${application.name}
cloud:
polaris:
server-addr: ${ip}:${port}
```
###Launching Example
###Launching Polaris Backend Service
Reference to [Polaris](https://github.com/polarismesh)
####Launching Application
Note, because verification is needed for circuit-break feature, therefore, one needs to deploy more than two invoked services (two deployment in this example)
Launching```spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-example-a```'s ServiceA and ```spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-example-b```'s ServiceB
note, Service B needs to launch two. One can adjust the port on the same machine.
Two Services B's ```com.tencent.cloud.polaris.circuitbreaker.example.ServiceBController.info``` logics are different. One returns normally, one is abnormal.
- Maven Package Launching
Execute under ``spring-cloud-tencent-examples/polaris-discovery-example```
note, Service B needs to launch two. One can adjust the port on the same machine.
Two Services B's com.tencent.cloud.polaris.circuitbreaker.example.ServiceBController.info logics are different. One returns normally, one is abnormal.
```sh
mvn clean package
```
Then under ``polaris-circuitbreaker-example-a``` and ``polaris-circuitbreaker-example-b``` find the package that generated jar, and run it
```
java -jar ${app.jar}
```
Launch application, change ${app.jar} to jar's package name
##Verify
####Feign Invoke
Execute the following orders to invoke Feign, the logic is ```ServiceB``` has an abnormal signal
```shell
curl -L -X GET 'localhost:48080/example/service/a/getBServiceInfo'
```
Expected return condition:
when appear
```
trigger the refuse for service b
```
it means the request signals abnormal ServiceB, and will ciruitbreak this instance, the later requests will return normally.

@ -0,0 +1,118 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>polaris-circuitbreaker-example</artifactId>
<groupId>com.tencent.cloud</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>polaris-circuitbreaker-example-a</artifactId>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<artifactId>spring-cloud-starter-tencent-polaris-discovery</artifactId>
<groupId>com.tencent.cloud</groupId>
</dependency>
<dependency>
<artifactId>spring-cloud-starter-tencent-polaris-circuitbreaker</artifactId>
<groupId>com.tencent.cloud</groupId>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-polaris-context</artifactId>
</dependency>
<!-- feign客户端依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency>
<!-- 负载均衡依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<!-- 熔断超时后,重试机制依赖-->
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<!-- import spring boot dependencies management-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<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,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.polaris.circuitbreaker.example;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
/**
* service b provider.
*
* @author Haotian Zhang
*/
@FeignClient(name = "polaris-circuitbreaker-example-b", fallback = ProviderBFallback.class)
public interface ProviderB {
/**
* B
*
* @return
*/
@GetMapping("/example/service/b/info")
String info();
}

@ -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.circuitbreaker.example;
import org.springframework.stereotype.Component;
/**
* provider b fallback
*
* @author Haotian Zhang
*/
@Component
public class ProviderBFallback implements ProviderB {
@Override
public String info() {
return "trigger the refuse for service b";
}
}

@ -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.polaris.circuitbreaker.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
/**
* circuitbraker example.
*
* @author Haotian Zhang
*/
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class ServiceA {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(ServiceA.class);
}
}

@ -0,0 +1,73 @@
/*
* 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.example;
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.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
/**
* Service A Controller
*
* @author Haotian Zhang
*/
@RestController
@RequestMapping("/example/service/a")
public class ServiceAController {
private final ProviderB polarisServiceB;
private final RestTemplate restTemplate;
public ServiceAController(ProviderB polarisServiceB, RestTemplate restTemplate) {
this.polarisServiceB = polarisServiceB;
this.restTemplate = restTemplate;
}
/**
*
*
* @return
* @throws Exception
*/
@GetMapping("/info")
public String info() throws Exception {
return "hello world ! I'am a service";
}
/**
* B
*
* @return B
* @throws Exception
*/
@GetMapping("/getBServiceInfo")
public String getBServiceInfo() throws Exception {
return polarisServiceB.info();
}
@RequestMapping(value = "/testRest", method = RequestMethod.GET)
public String testRest() {
ResponseEntity<String> entity = restTemplate.getForEntity("http://polaris-circuitbreaker-example-b/example/service/b/info", String.class);
return entity.getBody();
}
}

@ -0,0 +1,40 @@
server:
session-timeout: 1800
port: 48080
spring:
application:
name: polaris-circuitbreaker-example-a
cloud:
polaris:
address: grpc://127.0.0.1:8091
global:
api:
timeout: 5s
feign:
hystrix:
enabled: true #在Feign中开启Hystrix
compression:
request:
enabled: false #是否对请求进行GZIP压缩
mime-types: text/xml,application/xml,application/json #指定压缩的请求数据类型
min-request-size: 2048 #超过该大小的请求会被压缩
response:
enabled: false #是否对响应进行GZIP压缩
ribbon:
polaris:
enabled: true
# 同一实例最大重试次数,不包括首次调用
MaxAutoRetries: 1
# 重试其他实例的最大重试次数不包括首次所选的server
MaxAutoRetriesNextServer: 2
# 是否所有操作都进行重试
OkToRetryOnAllOperations: false
ConnectionTimeout: 1000
ReadTimeout: 1000
eager-load:
enabled: on
serivceB:
url: http://localhost:48081

@ -0,0 +1,287 @@
#描述:全局配置项
global:
#描述系统相关配置
system:
#描述:SDK运行模式
#类型:enum
#范围:0直连模式SDK直接对接server; 1代理模式SDK只对接agent, 通过agent进行server的对接
#默认值:0
mode: 0
#服务发现集群
discoverCluster:
namespace: Polaris
service: polaris.discover
#可选:服务刷新间隔
refreshInterval: 10m
#健康检查集群
healthCheckCluster:
namespace: Polaris
service: polaris.healthcheck
#可选:服务刷新间隔
refreshInterval: 10m
#监控上报集群
monitorCluster:
namespace: Polaris
service: polaris.monitor
#可选:服务刷新间隔
refreshInterval: 10m
api:
#描述:api超时时间
#类型:string
#格式:^\d+(ms|s|m|h)$
#范围:[1ms:...]
#默认值:1s
timeout: 5s
#描述:上报间隔
#类型:string
#格式:^\d+(ms|s|m|h)$
#范围:[1ms:...]
#默认值:10m
reportInterval: 10m
#描述:API因为网络原因调用失败后的重试次数
#类型:int
#范围:[0:...]
#默认值:5
maxRetryTimes: 5
#描述:重试间隔
#类型:string
#格式:^\d+(ms|s|m|h)$
#范围:[1s:...]
#默认值:1s
retryInterval: 1s
#描述:对接polaris server的相关配置
serverConnector:
#描述:访问server的连接协议SDK会根据协议名称会加载对应的插件
#类型:string
#范围:已注册的连接器插件名
#默认值:grpc
protocol: grpc
#描述:发起连接后的连接超时时间
#类型:string
#格式:^\d+(ms|s|m|h)$
#范围:[1ms:...]
#默认值:200ms
connectTimeout: 500ms
#描述:远程请求超时时间
#类型:string
#格式:^\d+(ms|s|m|h)$
#范围:[1ms:...]
#默认值:1s
messageTimeout: 5s
#描述:连接空闲时间长连接模式下当连接空闲超过一定时间后SDK会主动释放连接
#类型:string
#格式:^\d+(ms|s|m|h)$
#范围:[1ms:...]
#默认值:1s
connectionIdleTimeout: 1s
#描述:首次请求的任务队列长度当用户发起首次服务访问请求时SDK会对任务进行队列调度并连接server当积压的任务数超过队列长度后SDK会直接拒绝首次请求的发起。
#类型:int
#范围:[0:...]
#默认值:1000
requestQueueSize: 1000
#描述:server节点的切换周期为了使得server的压力能够均衡SDK会定期针对最新的节点列表进行重新计算自己当前应该连接的节点假如和当前不一致则进行切换
#类型:string
#格式:^\d+(ms|s|m|h)$
#范围:[1m:...]
#默认值:10m
serverSwitchInterval: 10m
plugin:
grpc:
#描述:GRPC客户端单次最大链路接收报文
#类型:int
#范围:(0:524288000]
maxCallRecvMsgSize: 52428800
#统计上报设置
statReporter:
#描述是否将统计信息上报至monitor
#类型bool
#默认值true
enable: true
#描述:启用的统计上报插件类型
#类型list
#范围:已经注册的统计上报插件的名字
#默认值stat2Monitor(将信息上报至monitor服务)
chain:
- stat2Monitor
- serviceCache
#描述:统计上报插件配置
plugin:
stat2Monitor:
#描述:每次上报多长一段时间的统计信息
#类型:string
#格式:^\d+(ms|s|m|h)$
#范围:[1m:...]
metricsReportWindow: 1m
#描述:将一段时间内的统计信息分为多少个基本单元收集
#类型:int
#范围:[1:...]
#默认值:12
metricsNumBuckets: 12
serviceCache:
#描述:上报缓存信息的周期
reportInterval: 3m
#描述:主调端配置
consumer:
#描述:本地缓存相关配置
localCache:
#描述:缓存类型
#类型:string
#范围:已注册的本地缓存插件名
#默认值:inmemory基于本机内存的缓存策略
type: inmemory
#描述:服务过期淘汰时间
#类型:string
#格式:^\d+(ms|s|m|h)$
#范围:[1m:...]
#默认值:24h
serviceExpireTime: 24h
#描述:服务定期刷新周期
#类型:string
#格式:^\d+(ms|s|m|h)$
#范围:[1s:...]
#默认值:2s
serviceRefreshInterval: 2s
#描述:服务缓存持久化目录SDK在实例数据更新后按照服务维度将数据持久化到磁盘
#类型:string
#格式:本机磁盘目录路径,支持$HOME变量
#默认值:$HOME/polaris/backup
persistDir: ./polaris/backup
#描述:缓存写盘失败的最大重试次数
#类型:int
#范围:[1:...]
#默认值:5
persistMaxWriteRetry: 5
#描述:缓存从磁盘读取失败的最大重试次数
#类型:int
#范围:[1:...]
#默认值:1
persistMaxReadRetry: 1
#描述:缓存读写磁盘的重试间隔
#类型:string
#格式:^\d+(ms|s|m|h)$
#范围:[1ms:...]
#默认值:1s
persistRetryInterval: 1s
#描述:服务路由相关配置
serviceRouter:
# 服务路由链
chain:
# 基于主调和被调服务规则的路由策略(默认的路由策略)
- ruleBasedRouter
# 就近路由策略
- nearbyBasedRouter
#描述:服务路由插件的配置
plugin:
nearbyBasedRouter:
#描述:就近路由的最小匹配级别
#类型:string
#范围:region(大区)、zone(区域)、campus(园区)
#默认值:zone
matchLevel: zone
ruleBasedRouter: { }
recoverRouter:
#至少应该返回多少比率的实例如果不填默认0%,即全死全活
percentOfMinInstances: 0
#是否开启全死全活,默认开启
enableRecoverAll: true
#描述:负载均衡相关配置
loadbalancer:
#描述:负载均衡类型
#范围:已注册的负载均衡插件名
#默认值:权重随机负载均衡
type: weightedRandom
plugin:
#描述:虚拟节点的数量
#类型:int
#默认值:500
ringHash:
vnodeCount: 500
#描述:节点熔断相关配置
circuitBreaker:
#描述:是否启用节点熔断功能
#类型:bool
#默认值:true
enable: true
#描述:实例定时熔断检测周期
#类型:string
#格式:^\d+(ms|s|m|h)$
#范围:[100ms:...]
#默认值:30s
checkPeriod: 100ms
#描述:熔断器半开后最大允许的请求数
#类型:int
#范围:[3:...]
#默认值:10
requestCountAfterHalfOpen: 10
#描述:熔断器打开后,多久后转换为半开状态
#类型:string
#格式:^\d+(ms|s|m|h)$
#范围:[1s:...]
#默认值:30s
sleepWindow: 60s
#描述:熔断器半开到关闭所必须的最少成功请求数
#类型:int
#范围:[1:requestCountAfterHalfOpen]
#默认值:8
successCountAfterHalfOpen: 8
#描述:熔断器半开到关闭的统计周期
#类型:string
#范围:[10s:...]
#默认值:60s
recoverWindow: 60s
#描述:熔断器半开到关闭的统计滑桶数
#类型:int
#范围:[1:...]
#默认值:10
recoverNumBuckets: 10
#描述:熔断策略SDK会根据策略名称加载对应的熔断器插件
#类型:list
#范围:已注册的熔断器插件名
#默认值基于周期连续错误数熔断errorCount、以及基于周期错误率的熔断策略errorRate
chain:
- errorCount
- errorRate
#描述:熔断插件配置
plugin:
#描述:基于周期连续错误数熔断策略配置
errorCount:
#描述:触发连续错误熔断的阈值
#类型:int
#范围:[1:...]
#默认值:10
continuousErrorThreshold: 1
#描述:连续错误数的最小统计单元数量
#类型:int
#范围:[1:...]
#默认值:10
metricNumBuckets: 1
#描述:连续失败的统计周期
#类型:string
#格式:^\d+(ms|s|m|h)$
#范围:[10ms:...]
#默认值:1m
metricStatTimeWindow: 100ms
#描述:基于周期错误率的熔断策略配置
errorRate:
#描述:触发错误率熔断的阈值
#类型:double
#范围:(0:1]
#默认值:0.5
errorRateThreshold: 0.01
#描述:错误率熔断的最小统计单元数量
#类型:int
#范围:[1:...]
#默认值:5
metricNumBuckets: 5
#描述:错误率熔断的统计周期
#类型:string
#格式:^\d+(ms|s|m|h)$
#范围:[1s:...]
#默认值:1m
metricStatTimeWindow: 1s
#描述:触发错误率熔断的最低请求阈值
#类型:int
#范围:(0:...]
#默认值:10
requestVolumeThreshold: 1

@ -0,0 +1,116 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>polaris-circuitbreaker-example</artifactId>
<groupId>com.tencent.cloud</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>polaris-circuitbreaker-example-b</artifactId>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<artifactId>spring-cloud-starter-tencent-polaris-discovery</artifactId>
<groupId>com.tencent.cloud</groupId>
</dependency>
<dependency>
<artifactId>spring-cloud-starter-tencent-polaris-circuitbreaker</artifactId>
<groupId>com.tencent.cloud</groupId>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-polaris-context</artifactId>
</dependency>
<!-- feign客户端依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency>
<!-- 负载均衡依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<!-- 熔断超时后,重试机制依赖-->
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<!-- import spring boot dependencies management-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<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,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.polaris.circuitbreaker.example;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
/**
* service a provider.
*
* @author Haotian Zhang
*/
@FeignClient(name = "polaris-circuitbreaker-example-a", fallback = ProviderAFallback.class)
public interface ProviderA {
/**
* B
*
* @return
*/
@GetMapping("/example/service/a/info")
String info();
}

@ -0,0 +1,34 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.polaris.circuitbreaker.example;
import org.springframework.stereotype.Component;
/**
* provider a fallback
*
* @author Haotian Zhang
*/
@Component
public class ProviderAFallback implements ProviderA {
@Override
public String info() {
return "trigger the refuse for service a";
}
}

@ -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.polaris.circuitbreaker.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
/**
* circuitbraker example.
*
* @author Haotian Zhang
*/
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class ServiceB {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(ServiceB.class);
}
}

@ -0,0 +1,75 @@
/*
* 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.example;
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.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
/**
* Service B Controller
*
* @author Haotian Zhang
*/
@RestController
@RequestMapping("/example/service/b")
public class ServiceBController {
private final ProviderA polarisServiceA;
private final RestTemplate restTemplate;
public ServiceBController(ProviderA polarisServiceA, RestTemplate restTemplate) {
this.polarisServiceA = polarisServiceA;
this.restTemplate = restTemplate;
}
/**
*
*
* @return
* @throws Exception
*/
@GetMapping("/info")
public String info() throws Exception {
// return "hello world ! I'am a service";
throw new RuntimeException("failed for call my service");
}
/**
* B
*
* @return B
* @throws Exception
*/
@GetMapping("/getAServiceInfo")
public String getAServiceInfo() throws Exception {
return polarisServiceA.info();
}
@RequestMapping(value = "/testRest", method = RequestMethod.GET)
public String testRest() {
ResponseEntity<String> entity = restTemplate.getForEntity("http://polaris-circuitbreaker-example-a/example/service/b/info", String.class);
return entity.getBody();
}
}

@ -0,0 +1,40 @@
server:
session-timeout: 1800
port: 48081
spring:
application:
name: polaris-circuitbreaker-example-b
cloud:
polaris:
address: grpc://127.0.0.1:8091
global:
api:
timeout: 5s
feign:
hystrix:
enabled: true #在Feign中开启Hystrix
compression:
request:
enabled: false #是否对请求进行GZIP压缩
mime-types: text/xml,application/xml,application/json #指定压缩的请求数据类型
min-request-size: 2048 #超过该大小的请求会被压缩
response:
enabled: false #是否对响应进行GZIP压缩
ribbon:
polaris:
enabled: true
# 同一实例最大重试次数,不包括首次调用
MaxAutoRetries: 1
# 重试其他实例的最大重试次数不包括首次所选的server
MaxAutoRetriesNextServer: 2
# 是否所有操作都进行重试
OkToRetryOnAllOperations: false
ConnectionTimeout: 1000
ReadTimeout: 1000
eager-load:
enabled: on
serivceB:
url: http://localhost:48081

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-tencent-examples</artifactId>
<groupId>com.tencent.cloud</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>polaris-circuitbreaker-example</artifactId>
<packaging>pom</packaging>
<modules>
<module>polaris-circuitbreaker-example-a</module>
<module>polaris-circuitbreaker-example-b</module>
</modules>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- 系统服务监控依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- feign客户端依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- 熔断依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<!-- 负载均衡依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<!-- 熔断超时后,重试机制依赖-->
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
</dependencies>
</project>

@ -0,0 +1,81 @@
# Polaris Discovery example
## 样例简介
本样例将介绍如何在Spring Cloud项目中使用```spring-cloud-starter-tencent-polaris-discovery```以使用其各项功能。
该样例分为两个微服务即discovery-caller-service和discovery-callee-service。其中discovery-caller-service对discovery-callee-service发生调用。
## 使用说明
### 修改配置
在两个微服务的```src/main/resources```下的```bootstrap.yml```文件中添加如下配置。其中,${ip}和${port}为Polaris后端服务的IP地址与端口号。
```yaml
spring:
application:
name: ${application.name}
cloud:
polaris:
server-addr: ${ip}:${port}
```
### 启动样例
#### 启动Polaris后端服务
参考[Polaris](https://github.com/polarismesh)。
#### 启动应用
- IDEA启动
分别启动```spring-cloud-tencent-examples/polaris-discovery-example/discovery-caller-service```下的```DiscoveryCallerService```和```spring-cloud-tencent-examples/polaris-discovery-example/discovery-callee-service```下的```DiscoveryCalleeService```。
- Maven打包启动
在```spring-cloud-tencent-examples/polaris-discovery-example```下执行
```sh
mvn clean package
```
然后在```discovery-caller-service```和```discovery-callee-service```下找到生成的jar包运行
```
java -jar ${app.jar}
```
启动应用,其中${app.jar}替换为对应的jar包名。
### 验证
#### Feign调用
执行以下命令发起Feign调用其逻辑为```DiscoveryCalleeService```返回value1+value2的和
```shell
curl -L -X GET 'http://localhost:48080/discovery/service/caller/feign?value1=1&value2=2'
```
预期返回值
```
3
```
#### RestTemplate调用
执行以下命令发起RestTemplate调用其逻辑为```DiscoveryCalleeService```返回一段字符串
```shell
curl -L -X GET 'http://localhost:48080/discovery/service/caller/rest'
```
预期返回值
```
Discovery Service Callee
```

@ -0,0 +1,81 @@
# Polaris Discovery example
## Example Introduction
The examples will explain how to use ```spring-cloud-starter-tencent-polaris-discovery`` in Spring Cloud project for its features.
This example is divided to two microservice, discovery-caller-service and discovery-callee-service. In these two microservices, discovery-caller-service invokes discovery-callee-service.
## Instruction
### Configuration
```src/main/resources``` and ```bootstrap.yml``` of two micro-services add the following instructions. ${ip} and ${port} are Polaris backend IP address and port number.
```yaml
spring:
application:
name: ${application.name}
cloud:
polaris:
server-addr: ${ip}:${port}
```
### Launching Example
#### Launching Polaris Backend Service
Reference to [Polaris](https://github.com/polarismesh)
#### Launching Application
- IDEA Launching
Launching ```spring-cloud-tencent-examples/polaris-discovery-example/discovery-caller-service```'s ``DiscoveryCallerService``` and ``spring-cloud-tencent-examples/polaris-discovery-example/discovery-callee-service```'s ```DiscoveryCalleeService``
- Maven Package Launching
Execute under ```spring-cloud-tencent-examples/polaris-discovery-example```
```sh
mvn clean package
```
Then at ```discovery-caller-service``` and ```discovery-callee-service``` find the package that generates jar, and run it
```
java -jar ${app.jar}
```
Launch application, change ${app.jar} to jar's package name
### Verify
#### Feign Invoke
Execute the following orders to invoke Feign, ```DiscoveryCalleeService``` goes bank to the sum of value1+value2
```shell
curl -L -X GET 'http://localhost:48080/discovery/service/caller/feign?value1=1&value2=2'
```
Expected return rate
```
3
```
#### RestTemplate Invoke
Execute the following orders to invoke RestTemplate, ```DiscoveryCalleeService``` goes back to string characters
```shell
curl -L -X GET 'http://localhost:48080/discovery/service/caller/rest'
```
Expected return rate
```
Discovery Service Callee
```

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>polaris-discovery-example</artifactId>
<groupId>com.tencent.cloud</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>discovery-callee-service</artifactId>
<name>Polaris Discovery Callee Service</name>
<dependencies>
<dependency>
<artifactId>spring-cloud-starter-tencent-polaris-discovery</artifactId>
<groupId>com.tencent.cloud</groupId>
</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,54 @@
/*
* 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 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;
/**
* @author Haotian Zhang
*/
@RestController
@RequestMapping("/discovery/service/callee")
public class DiscoveryCalleeController {
/**
*
*
* @return
*/
@GetMapping("/info")
public String info() {
return "Discovery Service Callee";
}
/**
*
*
* @param value1 1
* @param value2 2
* @return
*/
@GetMapping("/sum")
public int sum(@RequestParam int value1, @RequestParam int value2) {
return value1 + value2;
}
}

@ -0,0 +1,32 @@
/*
* 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 org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author Haotian Zhang
*/
@SpringBootApplication
public class DiscoveryCalleeService {
public static void main(String[] args) {
SpringApplication.run(DiscoveryCalleeService.class, args);
}
}

@ -0,0 +1,9 @@
server:
session-timeout: 1800
port: 48081
spring:
application:
name: DiscoveryCalleeService
cloud:
polaris:
address: grpc://127.0.0.1:8091

@ -0,0 +1,15 @@
log4j.rootLogger=DEBUG,console,FILE
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.threshold=INFO
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH\:mm\:ss} [%5p] - %c -%F(%L) -%m%n
log4j.appender.FILE=org.apache.log4j.RollingFileAppender
log4j.appender.FILE.Append=true
log4j.appender.FILE.File=applog/%d{yyyy-MM-dd}/%d{yyyy-MM-dd}.log
log4j.appender.FILE.Threshold=INFO
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern=%d{yyyy-MM-dd HH\:mm\:ss} [%5p] - %c -%F(%L) -%m%n
log4j.appender.FILE.MaxFileSize=10MB

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<contextName>logback</contextName>
<!--输出到控制台-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!--按天生成日志-->
<appender name="logFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<Prudent>true</Prudent>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>
applog/%d{yyyy-MM-dd}/%d{yyyy-MM-dd}.log
</FileNamePattern>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>
%d{yyyy-MM-dd HH:mm:ss} -%msg%n
</Pattern>
</layout>
</appender>
<root level="info">
<appender-ref ref="console"/>
<appender-ref ref="logFile"/>
</root>
</configuration>

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>polaris-discovery-example</artifactId>
<groupId>com.tencent.cloud</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>discovery-caller-service</artifactId>
<name>Polaris Discovery Caller Service</name>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<artifactId>spring-cloud-starter-tencent-polaris-discovery</artifactId>
<groupId>com.tencent.cloud</groupId>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-router</artifactId>
</dependency>
<!-- feign客户端依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</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,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.polaris.discovery.service.caller;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
/**
* @author Haotian Zhang
*/
@FeignClient("DiscoveryCalleeService")
public interface DiscoveryCalleeService {
/**
*
*
* @param value1 1
* @param value2 2
* @return
*/
@GetMapping("/discovery/service/callee/sum")
int sum(@RequestParam("value1") final int value1, @RequestParam("value2") final int value2);
}

@ -0,0 +1,32 @@
/*
* 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.caller;
import org.springframework.stereotype.Component;
/**
* @author Haotian Zhang
*/
@Component
public class DiscoveryCalleeServiceCallback implements DiscoveryCalleeService {
@Override
public int sum(int value1, int value2) {
return 0;
}
}

@ -0,0 +1,62 @@
/*
* 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.caller;
import org.springframework.beans.factory.annotation.Autowired;
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.RestTemplate;
/**
* @author Haotian Zhang
*/
@RestController
@RequestMapping("/discovery/service/caller")
public class DiscoveryCallerController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private DiscoveryCalleeService discoveryCalleeService;
/**
*
*
* @param value1 1
* @param value2 2
* @return
*/
@GetMapping("/feign")
public int feign(@RequestParam int value1, @RequestParam int value2) {
return discoveryCalleeService.sum(value1, value2);
}
/**
*
*
* @return
*/
@GetMapping("/rest")
public String rest() {
return restTemplate.getForObject("http://DiscoveryCalleeService/discovery/service/callee/info", String.class);
}
}

@ -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.polaris.discovery.service.caller;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
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;
/**
* @author Haotian Zhang
*/
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class DiscoveryCallerService {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(DiscoveryCallerService.class, args);
}
}

@ -0,0 +1,9 @@
server:
session-timeout: 1800
port: 48080
spring:
application:
name: DiscoveryCallerService
cloud:
polaris:
address: grpc://127.0.0.1:8091

@ -0,0 +1,15 @@
log4j.rootLogger=DEBUG,console,FILE
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.threshold=INFO
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH\:mm\:ss} [%5p] - %c -%F(%L) -%m%n
log4j.appender.FILE=org.apache.log4j.RollingFileAppender
log4j.appender.FILE.Append=true
log4j.appender.FILE.File=applog/%d{yyyy-MM-dd}/%d{yyyy-MM-dd}.log
log4j.appender.FILE.Threshold=INFO
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern=%d{yyyy-MM-dd HH\:mm\:ss} [%5p] - %c -%F(%L) -%m%n
log4j.appender.FILE.MaxFileSize=10MB

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<contextName>logback</contextName>
<!--输出到控制台-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!--按天生成日志-->
<appender name="logFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<Prudent>true</Prudent>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>
applog/%d{yyyy-MM-dd}/%d{yyyy-MM-dd}.log
</FileNamePattern>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>
%d{yyyy-MM-dd HH:mm:ss} -%msg%n
</Pattern>
</layout>
</appender>
<root level="info">
<appender-ref ref="console"/>
<appender-ref ref="logFile"/>
</root>
</configuration>

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-tencent-examples</artifactId>
<groupId>com.tencent.cloud</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>polaris-discovery-example</artifactId>
<packaging>pom</packaging>
<name>Spring Cloud Starter Tencent Polaris Discovery Example</name>
<modules>
<module>discovery-callee-service</module>
<module>discovery-caller-service</module>
</modules>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- 系统服务监控依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- feign客户端依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- 熔断依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<!-- 负载均衡依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<!-- 熔断超时后,重试机制依赖-->
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
</dependencies>
</project>

@ -0,0 +1,61 @@
# Polaris RateLimit Example
## 项目说明
本项目演示如何使用 Polaris ratelimit starter 完成 Spring Cloud 应用的限流管理。
[Polaris](https://github.com/polarismesh):北极星是腾讯开源的云原生的服务治理平台及组件,提供多维度的服务限流功能,防护应用系统的可靠性。
## 示例
### 如何接入
在启动示例进行演示之前,我们先了解一下如何接入 Polaris 限流组件。
> **注意:本章节只是为了便于您理解接入方式,本示例代码中已经完成接入工作,您无需再进行修改。**
1. 首先,修改 `pom.xml` 文件,引入 Polaris ratelimit starter。
```xml
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-ratelimit</artifactId>
</dependency>
```
2. 启动应用
北极星提供的example都支持在IDE中直接运行或者编译打包后通过命令行方式进行运行。
- 在本地启动Polaris服务端。
- 在北极星服务端可以通过控制台在命名空间Production下添加服务RateLimitCalleeService。
- 启动服务被调方:
1. IDE直接启动找到主类 `RateLimitCalleeService`,执行 main 方法启动应用。
2. 打包编译后启动:首先执行 `mvn clean package` 将工程编译打包,然后执行 `java -jar ratelimit-callee-sevice-${verion}.jar`启动应用。
- 启动后,可以在北极星控制台上看到注册上来的服务实例信息。
3. 调用服务
通过浏览器访问http://127.0.0.1:48081/business/invoke可以看到以下输出信息
````
hello world for ratelimit service 1
hello world for ratelimit service 2
hello world for ratelimit service 3
...
````
4. 配置限流规则并验证
北极星提供了三个方式进行限流规则的配置控制台、HTTP接口以及本地文件
本示例使用的方式为通过HTTP接口进行配置。通过以下命令来配置
````
curl -X POST -H "Content-Type:application/json" 127.0.0.1:8090/naming/v1/ratelimits -d @rule.json
````
5. 验证限流效果
继续访问http://127.0.0.1:48081/business/invoke可以看到10次调用后就开始被限流
````
hello world for ratelimit service 1
hello world for ratelimit service 2
...
hello world for ratelimit service 10
request has been limited, service is RateLimitCalleeService, path is /business/invoke, 11
````

@ -0,0 +1,68 @@
# Polaris RateLimit Example
## Project Explanation
This project shows how to use ratelimit feature of Polaris to complete Spring Cloud application's rate limit
[Polaris](https://github.com/polarismesh): Polaris is Tencent open source cloud-native's operation centre and component, provide multi dimensional rate limit service and reliability of application firewall
## Example
### How to access
Before showcasing the project, let's get to know how to access Polaris rate limit component
> ** note: this chapter is to help you understand different ways to access, the codes in the example has been executed, you don't need to re-edit.**
1, first, change document `pom.xml`, introduce Polaris ratelimit starter
```xml
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-ratelimit</artifactId>
</dependency>
```
2. Launch Application
Examples provided by Polaris all support to run at IDE, or compile and run with orders
- Launch Polaris locally
- at Polaris end, through control panel, under namespace Product, add RateLimitCalleeService
- Launch callee server:
1. Launch IDE directly: First find `RateLimitCalleeService`, execute main then launch application
2. compile package then launch: first execute `mvn clean package` compile the package, then execute `java -jar ratelimit-callee-sevice-${verion}.jar` execute the application
- After launching, one can watch server instance from Polaris control panel
3. Invoke Service
After visiting http://127.0.0.1:48081/business/invoke, one can see the following information:
````
hello world for ratelimit service 1
hello world for ratelimit service 2
hello world for ratelimit service 3
...
````
4. Configuration rate limit and verification
Polaris provide three wats to conduct rate limit configuration (control panel, HTTP port and local files)
this example is HTTP configuration. One can figure with the following steps:
````
curl -X POST -H "Content-Type:application/json" 127.0.0.1:8090/naming/v1/ratelimits -d @rule.json
````
5. Verify rate limit result
continue visit http://127.0.0.1:48081/business/invoke, one can see, after 10 invokes, rate limit will start:
````
hello world for ratelimit service 1
hello world for ratelimit service 2
````

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

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>polaris-ratelimit-example</artifactId>
<groupId>com.tencent.cloud</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ratelimit-callee-service</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<artifactId>spring-cloud-starter-tencent-polaris-discovery</artifactId>
<groupId>com.tencent.cloud</groupId>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-ratelimit</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator-autoconfigure</artifactId>
</dependency>
</dependencies>
</project>

@ -0,0 +1,76 @@
/*
* 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.ratelimit.example.service.callee;
import java.util.concurrent.atomic.AtomicInteger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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.RestController;
import org.springframework.web.client.HttpClientErrorException.TooManyRequests;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
/**
* @author Haotian Zhang
*/
@RestController
@RequestMapping("/business")
public class BusinessController {
@Autowired
private RestTemplate restTemplate;
private final AtomicInteger index = new AtomicInteger(0);
@Value("${spring.application.name}")
private String appName;
/**
*
*
* @return
*/
@GetMapping("/info")
public String info() {
return "hello world for ratelimit service " + index.incrementAndGet();
}
@GetMapping("/invoke")
public String invokeInfo() throws Exception {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < 30; i++) {
try {
ResponseEntity<String> entity = restTemplate
.getForEntity("http://" + appName + "/business/info", String.class);
builder.append(entity.getBody()).append("<br/>");
} catch (RestClientException e) {
if (e instanceof TooManyRequests) {
builder.append(((TooManyRequests) e).getResponseBodyAsString()).append(index.incrementAndGet())
.append("<br/>");
} else {
throw e;
}
}
}
return builder.toString();
}
}

@ -0,0 +1,43 @@
/*
* 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.ratelimit.example.service.callee;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
/**
* @author Haotian Zhang
*/
@SpringBootApplication
@EnableAutoConfiguration
public class RateLimitCalleeService {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(RateLimitCalleeService.class, args);
}
}

@ -0,0 +1,11 @@
server:
session-timeout: 1800
port: 48081
spring:
application:
name: RateLimitCalleeService
cloud:
polaris:
address: grpc://127.0.0.1:8091
discovery:
namespace: Test

@ -0,0 +1,15 @@
log4j.rootLogger=DEBUG,console,FILE
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.threshold=INFO
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH\:mm\:ss} [%5p] - %c -%F(%L) -%m%n
log4j.appender.FILE=org.apache.log4j.RollingFileAppender
log4j.appender.FILE.Append=true
log4j.appender.FILE.File=applog/%d{yyyy-MM-dd}/%d{yyyy-MM-dd}.log
log4j.appender.FILE.Threshold=INFO
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern=%d{yyyy-MM-dd HH\:mm\:ss} [%5p] - %c -%F(%L) -%m%n
log4j.appender.FILE.MaxFileSize=10MB

@ -0,0 +1,19 @@
{
"service": "RateLimitCalleeService",
"namespace": "Production",
"priority": 0,
"resource": "QPS",
"type": "LOCAL",
"labels": {
"method": {
"value": "/business/invoke"
}
},
"amounts": [
{
"maxAmount": 10,
"validDuration": "1s"
}
],
"action": "REJECT"
}

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>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-tencent-examples</artifactId>
<packaging>pom</packaging>
<name>Spring Cloud Tencent Examples</name>
<description>Examples of Spring Cloud Tencent</description>
<modules>
<module>polaris-discovery-example</module>
<module>polaris-ratelimit-example</module>
<module>polaris-circuitbreaker-example</module>
</modules>
</project>

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>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-tencent-starters</artifactId>
<packaging>pom</packaging>
<name>Spring Cloud Tencent Starters</name>
<description>Spring Cloud Tencent Starters</description>
<modules>
<module>spring-cloud-tencent-polaris-context</module>
<module>spring-cloud-tencent-commons</module>
<module>spring-cloud-tencent-metadata</module>
<module>spring-cloud-tencent-feign</module>
<module>spring-cloud-starter-tencent-polaris-discovery</module>
<module>spring-cloud-starter-tencent-polaris-ratelimit</module>
<module>spring-cloud-starter-tencent-polaris-circuitbreaker</module>
<module>spring-cloud-starter-tencent-polaris-router</module>
</modules>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version>
<executions>
<execution>
<id>jacoco-initialize</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>jacoco-site</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-tencent-starters</artifactId>
<groupId>com.tencent.cloud</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-starter-tencent-polaris-circuitbreaker</artifactId>
<name>Spring Cloud Starter Tencent Polaris Circuitbreaker</name>
<dependencies>
<!-- Spring Cloud Tencent dependencies start -->
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-metadata</artifactId>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-polaris-context</artifactId>
</dependency>
<!-- Spring Cloud Tencent dependencies end -->
<!-- Polaris dependencies start -->
<dependency>
<groupId>com.tencent.nameservice</groupId>
<artifactId>polaris-discovery-factory</artifactId>
</dependency>
<dependency>
<groupId>com.tencent.nameservice</groupId>
<artifactId>polaris-circuitbreaker-factory</artifactId>
</dependency>
<!-- Polaris dependencies end -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-openfeign-core</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
<scope>test</scope>
<optional>true</optional>
</dependency>
</dependencies>
</project>

@ -0,0 +1,75 @@
/*
* 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.feign.PolarisFeignBeanPostProcessor;
import com.tencent.cloud.polaris.context.PolarisConfigModifier;
import com.tencent.cloud.polaris.context.PolarisContextConfiguration;
import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.client.api.SDKContext;
import com.tencent.polaris.factory.api.DiscoveryAPIFactory;
import com.tencent.polaris.factory.config.ConfigurationImpl;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.openfeign.FeignAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import static org.springframework.core.Ordered.HIGHEST_PRECEDENCE;
/**
* Configuration for Polaris {@link feign.Feign} which can automatically bring in the call results for reporting
*
* @author Haotian Zhang
*/
@ConditionalOnProperty(
value = "spring.cloud.polaris.circuitbreaker.enabled",
havingValue = "true",
matchIfMissing = true)
@Configuration(proxyBeanMethods = false)
@AutoConfigureAfter(PolarisContextConfiguration.class)
@AutoConfigureBefore(FeignAutoConfiguration.class)
public class PolarisFeignClientAutoConfiguration {
@Bean
public ConsumerAPI consumerAPI(SDKContext context) {
return DiscoveryAPIFactory.createConsumerAPIByContext(context);
}
@Bean
@Order(value = HIGHEST_PRECEDENCE)
public PolarisFeignBeanPostProcessor polarisFeignBeanPostProcessor(ConsumerAPI consumerAPI) {
return new PolarisFeignBeanPostProcessor(consumerAPI);
}
@Bean
public CircuitBreakerConfigModifier circuitBreakerConfigModifier() {
return new CircuitBreakerConfigModifier();
}
public static class CircuitBreakerConfigModifier implements PolarisConfigModifier {
@Override
public void modify(ConfigurationImpl configuration) {
//开启熔断配置
configuration.getConsumer().getCircuitBreaker().setEnable(true);
}
}
}

@ -0,0 +1,91 @@
/*
* 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.feign;
import com.tencent.polaris.api.core.ConsumerAPI;
import feign.Client;
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.loadbalancer.blocking.client.BlockingLoadBalancerClient;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient;
import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;
import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;
/**
* Wrap Spring Bean and decorating proxy for Feign Client.
*
* @author Haotian Zhang
*/
public class PolarisFeignBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {
private BeanFactory factory;
private final ConsumerAPI consumerAPI;
public PolarisFeignBeanPostProcessor(ConsumerAPI consumerAPI) {
this.consumerAPI = consumerAPI;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return wrapper(bean);
}
private Object wrapper(Object bean) {
if (isNeedWrap(bean)) {
if (bean instanceof LoadBalancerFeignClient) {
LoadBalancerFeignClient client = ((LoadBalancerFeignClient) bean);
return new PolarisLoadBalancerFeignClient(createPolarisFeignClient(client.getDelegate()), factory(),
clientFactory());
}
if (bean instanceof FeignBlockingLoadBalancerClient) {
FeignBlockingLoadBalancerClient client = (FeignBlockingLoadBalancerClient) bean;
return new PolarisFeignBlockingLoadBalancerClient(createPolarisFeignClient(client.getDelegate()),
factory.getBean(BlockingLoadBalancerClient.class));
}
return createPolarisFeignClient((Client) bean);
}
return bean;
}
private boolean isNeedWrap(Object bean) {
return bean instanceof Client && !(bean instanceof PolarisFeignClient)
&& !(bean instanceof PolarisFeignBlockingLoadBalancerClient)
&& !(bean instanceof PolarisLoadBalancerFeignClient);
}
private PolarisFeignClient createPolarisFeignClient(Client delegate) {
return new PolarisFeignClient(delegate, consumerAPI);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.factory = beanFactory;
}
CachingSpringLoadBalancerFactory factory() {
return this.factory.getBean(CachingSpringLoadBalancerFactory.class);
}
SpringClientFactory clientFactory() {
return this.factory.getBean(SpringClientFactory.class);
}
}

@ -0,0 +1,36 @@
/*
* 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.feign;
import feign.Client;
import org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient;
import org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient;
/**
* Wrap for {@link FeignBlockingLoadBalancerClient}
*
* @author Haotian Zhang
*/
public class PolarisFeignBlockingLoadBalancerClient extends FeignBlockingLoadBalancerClient {
public PolarisFeignBlockingLoadBalancerClient(Client delegate,
BlockingLoadBalancerClient loadBalancerClient) {
super(delegate, loadBalancerClient);
}
}

@ -0,0 +1,94 @@
/*
* 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.feign;
import static feign.Util.checkNotNull;
import com.tencent.cloud.metadata.constant.MetadataConstant.SystemMetadataKey;
import com.tencent.cloud.metadata.context.MetadataContext;
import com.tencent.cloud.metadata.context.MetadataContextHolder;
import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.api.pojo.RetStatus;
import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.api.rpc.ServiceCallResult;
import feign.Client;
import feign.Request;
import feign.Request.Options;
import feign.Response;
import java.io.IOException;
import java.net.URI;
import org.apache.commons.lang.StringUtils;
/**
* Wrap for {@link Client}
*
* @author Haotian Zhang
*/
public class PolarisFeignClient implements Client {
private final Client delegate;
private final ConsumerAPI consumerAPI;
public PolarisFeignClient(Client target, ConsumerAPI consumerAPI) {
this.delegate = checkNotNull(target, "target");
this.consumerAPI = checkNotNull(consumerAPI, "CircuitBreakAPI");
}
@Override
public Response execute(Request request, Options options) throws IOException {
final ServiceCallResult resultRequest = createServiceCallResult(request);
try {
Response response = delegate.execute(request, options);
//HTTP code greater than 400 is an exception
if (response.status() >= 400) {
resultRequest.setRetStatus(RetStatus.RetFail);
}
return response;
} catch (IOException origin) {
resultRequest.setRetStatus(RetStatus.RetFail);
throw origin;
} finally {
consumerAPI.updateServiceCallResult(resultRequest);
}
}
private ServiceCallResult createServiceCallResult(final Request request) {
ServiceCallResult resultRequest = new ServiceCallResult();
MetadataContext metadataContext = MetadataContextHolder.get();
String namespace = metadataContext.getSystemMetadata(SystemMetadataKey.PEER_NAMESPACE);
resultRequest.setNamespace(namespace);
String serviceName = metadataContext.getSystemMetadata(SystemMetadataKey.PEER_SERVICE);
resultRequest.setService(serviceName);
String method = metadataContext.getSystemMetadata(SystemMetadataKey.PEER_PATH);
resultRequest.setMethod(method);
resultRequest.setRetStatus(RetStatus.RetSuccess);
String sourceNamespace = metadataContext.getSystemMetadata(SystemMetadataKey.LOCAL_NAMESPACE);
String sourceService = metadataContext.getSystemMetadata(SystemMetadataKey.LOCAL_SERVICE);
if (StringUtils.isNotBlank(sourceNamespace) && StringUtils.isNotBlank(sourceService)) {
resultRequest.setCallerService(new ServiceKey(sourceNamespace, sourceService));
}
URI uri = URI.create(request.url());
resultRequest.setHost(uri.getHost());
resultRequest.setPort(uri.getPort());
return resultRequest;
}
}

@ -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.circuitbreaker.feign;
import feign.Client;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;
import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;
/**
* Wrap for {@link LoadBalancerFeignClient}
*
* @author Haotian Zhang
*/
public class PolarisLoadBalancerFeignClient extends LoadBalancerFeignClient {
public PolarisLoadBalancerFeignClient(Client delegate,
CachingSpringLoadBalancerFactory lbClientFactory,
SpringClientFactory clientFactory) {
super(delegate, lbClientFactory, clientFactory);
}
}

@ -0,0 +1,10 @@
{
"properties": [
{
"name": "spring.cloud.polaris.circuitbreaker.enabled",
"type": "java.lang.Boolean",
"sourceType": "com.tencent.cloud.polaris.circuitbreaker.PolarisFeignProperties"
}
],
"hints": []
}

@ -0,0 +1,2 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.tencent.cloud.polaris.circuitbreaker.PolarisFeignClientAutoConfiguration

@ -0,0 +1,62 @@
/*
* 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.feign;
import com.tencent.cloud.polaris.circuitbreaker.PolarisFeignClientAutoConfiguration;
import feign.Client;
import org.junit.Test;
import org.junit.jupiter.api.Assertions;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
/**
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestPolarisFeignApp.class)
@ContextConfiguration(classes = {PolarisFeignClientAutoConfiguration.class})
public class PolarisFeignClientTest {
@Autowired
private ApplicationContext springCtx;
@Test
public void testPolarisFeignBeanPostProcessor() {
final PolarisFeignBeanPostProcessor postProcessor = springCtx.getBean(PolarisFeignBeanPostProcessor.class);
Assertions.assertNotNull(postProcessor, "PolarisFeignBeanPostProcessor");
}
@Test
public void testFeignClient() {
final Client client = springCtx.getBean(Client.class);
if (client instanceof PolarisFeignClient) {
return;
}
if (client instanceof PolarisLoadBalancerFeignClient) {
return;
}
if (client instanceof PolarisFeignBlockingLoadBalancerClient) {
return;
}
throw new IllegalStateException("Polaris burying failed");
}
}

@ -0,0 +1,63 @@
/*
* 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.feign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
/**
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
*/
@SpringBootApplication
@EnableFeignClients
public class TestPolarisFeignApp {
@Autowired
TestPolarisService service;
public static void main(String[] args) {
SpringApplication.run(TestPolarisFeignApp.class);
}
@FeignClient(name = "feign-service-polaris", fallback = TestPolarisServiceFallback.class)
public interface TestPolarisService {
/**
* B
*
* @return
*/
@GetMapping("/example/service/b/info")
String info();
}
@Component
public static class TestPolarisServiceFallback implements TestPolarisService {
@Override
public String info() {
return "trigger the refuse";
}
}
}

@ -0,0 +1,15 @@
spring:
cloud:
polaris:
address: grpc://127.0.0.1:8091
feign:
polaris:
enable: true
compression:
request:
enabled: false #是否对请求进行GZIP压缩
mime-types: text/xml,application/xml,application/json #指定压缩的请求数据类型
min-request-size: 2048 #超过该大小的请求会被压缩
response:
enabled: false #是否对响应进行GZIP压缩

@ -0,0 +1,135 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-tencent-starters</artifactId>
<groupId>com.tencent.cloud</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-starter-tencent-polaris-discovery</artifactId>
<name>Spring Cloud Starter Tencent Polaris Discovery</name>
<dependencies>
<!-- Spring Cloud Tencent dependencies start -->
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-commons</artifactId>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-metadata</artifactId>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-polaris-context</artifactId>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-polaris-router</artifactId>
</dependency>
<!-- Spring Cloud Tencent dependencies end -->
<!-- Polaris dependencies start -->
<dependency>
<groupId>com.tencent.nameservice</groupId>
<artifactId>polaris-discovery-factory</artifactId>
</dependency>
<dependency>
<groupId>com.tencent.nameservice</groupId>
<artifactId>polaris-test-common</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.tencent.nameservice</groupId>
<artifactId>polaris-test-mock-discovery</artifactId>
<scope>test</scope>
</dependency>
<!-- Polaris dependencies end -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<optional>true</optional>
</dependency>
<!-- feign客户端依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>test</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<scope>test</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<scope>test</scope>
<optional>true</optional>
</dependency>
</dependencies>
</project>

@ -0,0 +1,233 @@
/*
* 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;
import javax.annotation.PostConstruct;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.env.Environment;
/**
* Properties for Polaris.
*
* @author Haotian Zhang
*/
@ConfigurationProperties("spring.cloud.polaris.discovery")
public class PolarisProperties {
/**
* the polaris authentication token.
*/
private String token;
/**
* namespace, separation registry of different environments.
*/
@Value("${spring.cloud.polaris.discovery.namespace:#{'Production'}}")
private String namespace;
/**
* service name to registry.
*/
@Value("${spring.cloud.polaris.discovery.service:${spring.application.name:}}")
private String service;
/**
*
*/
@Value("${spring.cloud.polaris.discovery.weight:#{100}}")
private float weight;
/**
*
*/
private String version;
/**
*
*/
@Value("${spring.cloud.polaris.discovery.protocol:http}")
private String protocol;
/**
* 使spring cloud
*/
@Value("${server.port:}")
private int port;
/**
*
*/
@Value("${spring.cloud.polaris.discovery.loadbalancer.enabled:#{true}}")
private Boolean loadbalancerEnabled;
/**
* loadbalnce strategy
*/
@Value("${spring.cloud.polaris.discovery.loadbalancer.policy:#{'weightedRandom'}}")
private String policy;
/**
* loadbalnce strategy
*/
@Value("${spring.cloud.polaris.discovery.register.enabled:#{true}}")
private Boolean registerEnabled;
/**
* loadbalnce strategy
*/
@Value("${spring.cloud.polaris.discovery.heartbeat.enabled:#{false}}")
private Boolean heartbeatEnabled = true;
@Autowired
private Environment environment;
/**
* init properties
*
* @throws Exception
*/
@PostConstruct
public void init() throws Exception {
if (StringUtils.isEmpty(this.getNamespace())) {
this.setNamespace(environment.resolvePlaceholders("${spring.cloud.polaris.discovery.namespace:}"));
}
if (StringUtils.isEmpty(this.getService())) {
this.setService(environment.resolvePlaceholders("${spring.cloud.polaris.discovery.service:}"));
}
if (StringUtils.isEmpty(this.getToken())) {
this.setToken(environment.resolvePlaceholders("${spring.cloud.polaris.discovery.token:}"));
}
}
public boolean isHeartbeatEnabled() {
if (null == heartbeatEnabled) {
return false;
}
return heartbeatEnabled;
}
public void setHeartbeatEnabled(Boolean heartbeatEnabled) {
this.heartbeatEnabled = heartbeatEnabled;
}
public String getNamespace() {
return namespace;
}
public void setNamespace(String namespace) {
this.namespace = namespace;
}
public float getWeight() {
return weight;
}
public void setWeight(float weight) {
this.weight = weight;
}
public String getService() {
return service;
}
public void setService(String service) {
this.service = service;
}
public boolean isRegisterEnabled() {
return registerEnabled;
}
public void setRegisterEnabled(boolean registerEnabled) {
this.registerEnabled = registerEnabled;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getProtocol() {
return protocol;
}
public void setProtocol(String protocol) {
this.protocol = protocol;
}
public String getPolicy() {
return policy;
}
public void setPolicy(String policy) {
this.policy = policy;
}
public Boolean getLoadbalancerEnabled() {
return loadbalancerEnabled;
}
public void setLoadbalancerEnabled(Boolean loadbalancerEnabled) {
this.loadbalancerEnabled = loadbalancerEnabled;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
@Override
@SuppressWarnings("checkstyle:all")
public String toString() {
return "PolarisProperties{" +
"token='" + token + '\'' +
", namespace='" + namespace + '\'' +
", service='" + service + '\'' +
", weight=" + weight +
", version='" + version + '\'' +
", protocol='" + protocol + '\'' +
", port=" + port +
", loadbalancerEnabled=" + loadbalancerEnabled +
", policy='" + policy + '\'' +
", registerEnabled=" + registerEnabled +
", heartbeatEnabled=" + heartbeatEnabled +
", environment=" + environment +
'}';
}
}

@ -0,0 +1,52 @@
/*
* 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.client;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation for Polaris Client for service configuration.
*
* @author Haotian Zhang
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface PolarisClient {
/**
* service
*
* @return service
*/
String service() default "";
/**
* namespace
*
* @return namespace
*/
String namespace() default "";
}

@ -0,0 +1,36 @@
/*
* 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;
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;
import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;
/**
* @author Haotian Zhang
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@ConditionalOnDiscoveryEnabled
@ConditionalOnProperty(value = "spring.cloud.polaris.discovery.enabled", matchIfMissing = true)
public @interface ConditionalOnPolarisDiscoveryEnabled {
}

@ -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.discovery;
import com.tencent.cloud.polaris.PolarisProperties;
import com.tencent.cloud.polaris.discovery.reactive.PolarisReactiveDiscoveryClientConfiguration;
import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.api.core.ProviderAPI;
import com.tencent.polaris.api.exception.PolarisException;
import com.tencent.polaris.client.api.SDKContext;
import com.tencent.polaris.factory.api.DiscoveryAPIFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* Discovery Auto Configuration for Polaris.
*
* @author Haotian Zhang
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnPolarisDiscoveryEnabled
@Import({PolarisDiscoveryClientConfiguration.class, PolarisReactiveDiscoveryClientConfiguration.class})
public class PolarisDiscoveryAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public PolarisProperties polarisDiscoveryProperties() {
return new PolarisProperties();
}
@Bean(name = "polarisProvider")
@ConditionalOnMissingBean
public ProviderAPI polarisProvider(SDKContext polarisContext) throws PolarisException {
return DiscoveryAPIFactory.createProviderAPIByContext(polarisContext);
}
@Bean(name = "polarisConsumer")
@ConditionalOnMissingBean
public ConsumerAPI polarisConsumer(SDKContext polarisContext) throws PolarisException {
return DiscoveryAPIFactory.createConsumerAPIByContext(polarisContext);
}
@Bean
@ConditionalOnMissingBean
public PolarisDiscoveryHandler polarisDiscoveryHandler() {
return new PolarisDiscoveryHandler();
}
@Bean
@ConditionalOnMissingBean
public PolarisServiceDiscovery polarisServiceDiscovery(PolarisDiscoveryHandler polarisDiscoveryHandler) {
return new PolarisServiceDiscovery(polarisDiscoveryHandler);
}
}

@ -0,0 +1,61 @@
/*
* 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;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
/**
* Discovery Client for Polaris.
*
* @author Haotian Zhang
*/
public class PolarisDiscoveryClient implements DiscoveryClient {
private static final Logger log = LoggerFactory.getLogger(PolarisDiscoveryClient.class);
/**
* Polaris Discovery Client Description.
*/
public final String description = "Spring Cloud Polaris Discovery Client";
private final PolarisServiceDiscovery polarisServiceDiscovery;
public PolarisDiscoveryClient(PolarisServiceDiscovery polarisServiceDiscovery) {
this.polarisServiceDiscovery = polarisServiceDiscovery;
}
@Override
public String description() {
return description;
}
@Override
public List<ServiceInstance> getInstances(String service) {
return polarisServiceDiscovery.getInstances(service);
}
@Override
public List<String> getServices() {
return polarisServiceDiscovery.getServices();
}
}

@ -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.polaris.discovery;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.cloud.client.CommonsClientAutoConfiguration;
import org.springframework.cloud.client.ConditionalOnBlockingDiscoveryEnabled;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Discovery Client Configuration for Polaris.
*
* @author Haotian Zhang
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnBlockingDiscoveryEnabled
@AutoConfigureBefore({SimpleDiscoveryClientAutoConfiguration.class,
CommonsClientAutoConfiguration.class})
@AutoConfigureAfter(PolarisDiscoveryAutoConfiguration.class)
public class PolarisDiscoveryClientConfiguration {
@Bean
public DiscoveryClient polarisDiscoveryClient(PolarisServiceDiscovery polarisServiceDiscovery) {
return new PolarisDiscoveryClient(polarisServiceDiscovery);
}
}

@ -0,0 +1,96 @@
/*
* 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;
import com.tencent.cloud.metadata.constant.MetadataConstant.SystemMetadataKey;
import com.tencent.cloud.metadata.context.MetadataContextHolder;
import com.tencent.cloud.polaris.PolarisProperties;
import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.api.core.ProviderAPI;
import com.tencent.polaris.api.pojo.ServiceInfo;
import com.tencent.polaris.api.rpc.GetAllInstancesRequest;
import com.tencent.polaris.api.rpc.GetInstancesRequest;
import com.tencent.polaris.api.rpc.InstancesResponse;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* Discovery Handler for Polaris.
*
* @author Haotian Zhang
*/
@Component
public class PolarisDiscoveryHandler {
@Autowired
private PolarisProperties polarisProperties;
@Autowired
private ProviderAPI providerAPI;
@Autowired
private ConsumerAPI polarisConsumer;
/**
*
*
* @param service
* @return
*/
public InstancesResponse getFilteredInstances(String service) {
String namespace = polarisProperties.getNamespace();
GetInstancesRequest getInstancesRequest = new GetInstancesRequest();
getInstancesRequest.setNamespace(namespace);
getInstancesRequest.setService(service);
String method = MetadataContextHolder.get().getSystemMetadata(SystemMetadataKey.PEER_PATH);
getInstancesRequest.setMethod(method);
String localNamespace = MetadataContextHolder.get().getSystemMetadata(SystemMetadataKey.LOCAL_NAMESPACE);
String localService = MetadataContextHolder.get().getSystemMetadata(SystemMetadataKey.LOCAL_SERVICE);
Map<String, String> allTransitiveCustomMetadata = MetadataContextHolder.get().getAllTransitiveCustomMetadata();
if (StringUtils.isNotBlank(localNamespace) || StringUtils.isNotBlank(localService)
|| null != allTransitiveCustomMetadata) {
ServiceInfo sourceService = new ServiceInfo();
sourceService.setNamespace(localNamespace);
sourceService.setService(localService);
sourceService.setMetadata(allTransitiveCustomMetadata);
getInstancesRequest.setServiceInfo(sourceService);
}
return polarisConsumer.getInstances(getInstancesRequest);
}
/**
* Return all instances for the given service.
*
* @param service serviceName
* @return
*/
public InstancesResponse getInstances(String service) {
String namespace = polarisProperties.getNamespace();
GetAllInstancesRequest request = new GetAllInstancesRequest();
request.setNamespace(namespace);
request.setService(service);
return polarisConsumer.getAllInstance(request);
}
public ProviderAPI getProviderAPI() {
return providerAPI;
}
}

@ -0,0 +1,69 @@
/*
* 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;
import com.tencent.cloud.polaris.pojo.PolarisServiceInstance;
import com.tencent.polaris.api.exception.PolarisException;
import com.tencent.polaris.api.pojo.Instance;
import com.tencent.polaris.api.pojo.ServiceInstances;
import com.tencent.polaris.api.rpc.InstancesResponse;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.springframework.cloud.client.ServiceInstance;
/**
* @author Haotian Zhang
*/
public class PolarisServiceDiscovery {
private final PolarisDiscoveryHandler polarisDiscoveryHandler;
public PolarisServiceDiscovery(PolarisDiscoveryHandler polarisDiscoveryHandler) {
this.polarisDiscoveryHandler = polarisDiscoveryHandler;
}
/**
* Return all instances for the given service.
*
* @param serviceId id of service
* @return list of instances
* @throws PolarisException polarisException
*/
public List<ServiceInstance> getInstances(String serviceId) throws PolarisException {
List<ServiceInstance> instances = new ArrayList<>();
InstancesResponse filteredInstances = polarisDiscoveryHandler.getFilteredInstances(serviceId);
ServiceInstances serviceInstances = filteredInstances.toServiceInstances();
for (Instance instance : serviceInstances.getInstances()) {
instances.add(new PolarisServiceInstance(instance));
}
return instances;
}
/**
* TODO Return the names of all services.
*
* @return list of service names
* @throws PolarisException polarisException
*/
public List<String> getServices() throws PolarisException {
return Collections.emptyList();
}
}

@ -0,0 +1,84 @@
/*
* 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.reactive;
import com.tencent.polaris.api.exception.PolarisException;
import com.tencent.cloud.polaris.discovery.PolarisServiceDiscovery;
import java.util.function.Function;
import org.reactivestreams.Publisher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.ReactiveDiscoveryClient;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;
/**
* Reactive Discovery Client for Polaris.
*
* @author Haotian Zhang
*/
public class PolarisReactiveDiscoveryClient implements ReactiveDiscoveryClient {
private static final Logger log = LoggerFactory
.getLogger(PolarisReactiveDiscoveryClient.class);
private PolarisServiceDiscovery polarisServiceDiscovery;
public PolarisReactiveDiscoveryClient(
PolarisServiceDiscovery polarisServiceDiscovery) {
this.polarisServiceDiscovery = polarisServiceDiscovery;
}
@Override
public String description() {
return "Spring Cloud Polaris Reactive Discovery Client";
}
@Override
public Flux<ServiceInstance> getInstances(String serviceId) {
return Mono.justOrEmpty(serviceId).flatMapMany(loadInstancesFromPolaris())
.subscribeOn(Schedulers.boundedElastic());
}
private Function<String, Publisher<ServiceInstance>> loadInstancesFromPolaris() {
return serviceId -> {
try {
return Flux.fromIterable(polarisServiceDiscovery.getInstances(serviceId));
} catch (PolarisException e) {
log.error("get service instance[{}] from polaris error!", serviceId, e);
return Flux.empty();
}
};
}
@Override
public Flux<String> getServices() {
return Flux.defer(() -> {
try {
return Flux.fromIterable(polarisServiceDiscovery.getServices());
} catch (Exception e) {
log.error("get services from polaris server fail,", e);
return Flux.empty();
}
}).subscribeOn(Schedulers.boundedElastic());
}
}

@ -0,0 +1,50 @@
/*
* 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.reactive;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryAutoConfiguration;
import com.tencent.cloud.polaris.discovery.PolarisServiceDiscovery;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.client.ConditionalOnReactiveDiscoveryEnabled;
import org.springframework.cloud.client.ReactiveCommonsClientAutoConfiguration;
import org.springframework.cloud.client.discovery.composite.reactive.ReactiveCompositeDiscoveryClientAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Reactive Discovery Client Configuration for Polaris.
*
* @author Haotian Zhang
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnReactiveDiscoveryEnabled
@AutoConfigureAfter({PolarisDiscoveryAutoConfiguration.class,
ReactiveCompositeDiscoveryClientAutoConfiguration.class})
@AutoConfigureBefore({ReactiveCommonsClientAutoConfiguration.class})
public class PolarisReactiveDiscoveryClientConfiguration {
@Bean
@ConditionalOnMissingBean
public PolarisReactiveDiscoveryClient polarisReactiveDiscoveryClient(
PolarisServiceDiscovery polarisServiceDiscovery) {
return new PolarisReactiveDiscoveryClient(polarisServiceDiscovery);
}
}

@ -0,0 +1,95 @@
/*
* 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.registry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration;
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
import org.springframework.util.StringUtils;
/**
* @author Haotian Zhang
*/
public class PolarisAutoServiceRegistration extends AbstractAutoServiceRegistration<Registration> {
private static final Logger log = LoggerFactory.getLogger(PolarisAutoServiceRegistration.class);
private final PolarisRegistration registration;
public PolarisAutoServiceRegistration(ServiceRegistry<Registration> serviceRegistry,
AutoServiceRegistrationProperties autoServiceRegistrationProperties,
PolarisRegistration registration) {
super(serviceRegistry, autoServiceRegistrationProperties);
this.registration = registration;
}
@Override
protected PolarisRegistration getRegistration() {
if (this.registration.getPort() <= 0) {
this.registration.setPort(this.getPort().get());
}
return this.registration;
}
@Override
protected PolarisRegistration getManagementRegistration() {
return null;
}
@Override
protected void register() {
if (!this.registration.getPolarisProperties().isRegisterEnabled()) {
log.debug("Registration disabled.");
return;
}
if (this.registration.getPort() <= 0) {
this.registration.setPort(getPort().get());
}
super.register();
}
@Override
protected void registerManagement() {
if (!this.registration.getPolarisProperties().isRegisterEnabled()) {
return;
}
super.registerManagement();
}
@Override
protected Object getConfiguration() {
return this.registration.getPolarisProperties();
}
@Override
protected boolean isEnabled() {
return this.registration.getPolarisProperties().isRegisterEnabled();
}
@Override
@SuppressWarnings("deprecation")
protected String getAppName() {
String appName = registration.getPolarisProperties().getService();
return StringUtils.isEmpty(appName) ? super.getAppName() : appName;
}
}

@ -0,0 +1,89 @@
/*
* 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.registry;
import com.tencent.cloud.metadata.context.MetadataContextHolder;
import com.tencent.cloud.polaris.PolarisProperties;
import com.tencent.polaris.client.api.SDKContext;
import java.net.URI;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.serviceregistry.Registration;
/**
* @author Haotian Zhang
*/
public class PolarisRegistration implements Registration, ServiceInstance {
private final PolarisProperties polarisProperties;
private final SDKContext polarisContext;
public PolarisRegistration(PolarisProperties polarisProperties, SDKContext context) {
this.polarisProperties = polarisProperties;
this.polarisContext = context;
}
@Override
public String getServiceId() {
return polarisProperties.getService();
}
@Override
public String getHost() {
return polarisContext.getConfig().getGlobal().getAPI().getBindIP();
}
@Override
public int getPort() {
return polarisProperties.getPort();
}
public void setPort(int port) {
this.polarisProperties.setPort(port);
}
@Override
public boolean isSecure() {
return StringUtils.equalsIgnoreCase(polarisProperties.getProtocol(), "https");
}
@Override
public URI getUri() {
return DefaultServiceInstance.getUri(this);
}
@Override
public Map<String, String> getMetadata() {
return MetadataContextHolder.get().getAllSystemMetadata();
}
public PolarisProperties getPolarisProperties() {
return polarisProperties;
}
@Override
public String toString() {
return "PolarisRegistration{" +
"polarisProperties=" + polarisProperties +
", polarisContext=" + polarisContext +
'}';
}
}

@ -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.registry;
import static org.springframework.util.ReflectionUtils.rethrowRuntimeException;
import com.tencent.cloud.metadata.config.MetadataLocalProperties;
import com.tencent.cloud.polaris.PolarisProperties;
import com.tencent.polaris.api.core.ProviderAPI;
import com.tencent.polaris.api.exception.PolarisException;
import com.tencent.polaris.api.pojo.Instance;
import com.tencent.polaris.api.rpc.InstanceDeregisterRequest;
import com.tencent.polaris.api.rpc.InstanceHeartbeatRequest;
import com.tencent.polaris.api.rpc.InstanceRegisterRequest;
import com.tencent.polaris.api.rpc.InstancesResponse;
import com.tencent.polaris.client.util.NamedThreadFactory;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
import org.springframework.util.StringUtils;
/**
* @author Haotian Zhang
*/
public class PolarisServiceRegistry implements ServiceRegistry<Registration> {
private static final Logger log = LoggerFactory.getLogger(PolarisServiceRegistry.class);
private static final int ttl = 5;
private final PolarisProperties polarisProperties;
private final PolarisDiscoveryHandler polarisDiscoveryHandler;
private final MetadataLocalProperties metadataLocalProperties;
private final ScheduledExecutorService heartbeatExecutor;
public PolarisServiceRegistry(PolarisProperties polarisProperties, PolarisDiscoveryHandler polarisDiscoveryHandler,
MetadataLocalProperties metadataLocalProperties) {
this.polarisProperties = polarisProperties;
this.polarisDiscoveryHandler = polarisDiscoveryHandler;
this.metadataLocalProperties = metadataLocalProperties;
if (polarisProperties.isHeartbeatEnabled()) {
ScheduledThreadPoolExecutor heartbeatExecutor = new ScheduledThreadPoolExecutor(0,
new NamedThreadFactory("spring-cloud-heartbeat"));
heartbeatExecutor.setMaximumPoolSize(1);
this.heartbeatExecutor = heartbeatExecutor;
} else {
this.heartbeatExecutor = null;
}
}
@Override
public void register(Registration registration) {
if (StringUtils.isEmpty(registration.getServiceId())) {
log.warn("No service to register for polaris client...");
return;
}
// 注册实例
InstanceRegisterRequest instanceRegisterRequest = new InstanceRegisterRequest();
instanceRegisterRequest.setNamespace(polarisProperties.getNamespace());
instanceRegisterRequest.setService(registration.getServiceId());
instanceRegisterRequest.setHost(registration.getHost());
instanceRegisterRequest.setPort(registration.getPort());
instanceRegisterRequest.setToken(polarisProperties.getToken());
if (null != heartbeatExecutor) {
instanceRegisterRequest.setTtl(ttl);
}
instanceRegisterRequest.setMetadata(metadataLocalProperties.getContent());
instanceRegisterRequest.setProtocol(polarisProperties.getProtocol());
instanceRegisterRequest.setVersion(polarisProperties.getVersion());
try {
ProviderAPI providerClient = polarisDiscoveryHandler.getProviderAPI();
providerClient.register(instanceRegisterRequest);
log.info("polaris registry, {} {} {}:{} {} register finished",
polarisProperties.getNamespace(),
registration.getServiceId(), registration.getHost(),
registration.getPort(), metadataLocalProperties.getContent());
if (null != heartbeatExecutor) {
InstanceHeartbeatRequest heartbeatRequest = new InstanceHeartbeatRequest();
BeanUtils.copyProperties(instanceRegisterRequest, heartbeatRequest);
//注册成功后开始启动心跳线程
heartbeat(heartbeatRequest);
}
} catch (Exception e) {
log.error("polaris registry, {} register failed...{},", registration.getServiceId(), registration, e);
rethrowRuntimeException(e);
}
}
@Override
public void deregister(Registration registration) {
log.info("De-registering from Polaris Server now...");
if (StringUtils.isEmpty(registration.getServiceId())) {
log.warn("No dom to de-register for polaris client...");
return;
}
InstanceDeregisterRequest deRegisterRequest = new InstanceDeregisterRequest();
deRegisterRequest.setToken(polarisProperties.getToken());
deRegisterRequest.setNamespace(polarisProperties.getNamespace());
deRegisterRequest.setService(registration.getServiceId());
deRegisterRequest.setHost(registration.getHost());
deRegisterRequest.setPort(registration.getPort());
try {
ProviderAPI providerClient = polarisDiscoveryHandler.getProviderAPI();
providerClient.deRegister(deRegisterRequest);
} catch (Exception e) {
log.error("ERR_POLARIS_DEREGISTER, de-register failed...{},", registration, e);
} finally {
if (null != heartbeatExecutor) {
heartbeatExecutor.shutdown();
}
}
log.info("De-registration finished.");
}
@Override
public void close() {
}
@Override
public void setStatus(Registration registration, String status) {
}
@Override
public Object getStatus(Registration registration) {
String serviceName = registration.getServiceId();
InstancesResponse instancesResponse = polarisDiscoveryHandler.getInstances(serviceName);
Instance[] instances = instancesResponse.getInstances();
if (null == instances || instances.length == 0) {
return null;
}
for (Instance instance : instances) {
if (instance.getHost().equalsIgnoreCase(registration.getHost())
&& instance.getPort() == polarisProperties.getPort()) {
return instance.isHealthy() ? "UP" : "DOWN";
}
}
return null;
}
/**
* 线
*
* @param heartbeatRequest
*/
public void heartbeat(InstanceHeartbeatRequest heartbeatRequest) {
heartbeatExecutor.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
try {
polarisDiscoveryHandler.getProviderAPI().heartbeat(heartbeatRequest);
} catch (PolarisException e) {
log.error("polaris heartbeat[{}]", e.getCode(), e);
} catch (Exception e) {
log.error("polaris heartbeat runtime error", e);
}
}
}, 0, ttl, TimeUnit.SECONDS);
}
}

@ -0,0 +1,70 @@
/*
* 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.registry;
import com.tencent.cloud.metadata.config.MetadataLocalProperties;
import com.tencent.cloud.polaris.PolarisProperties;
import com.tencent.polaris.client.api.SDKContext;
import com.tencent.cloud.polaris.discovery.ConditionalOnPolarisDiscoveryEnabled;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryAutoConfiguration;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration;
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration;
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author Haotian Zhang
*/
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties
@ConditionalOnPolarisDiscoveryEnabled
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
@AutoConfigureAfter({AutoServiceRegistrationConfiguration.class,
AutoServiceRegistrationAutoConfiguration.class,
PolarisDiscoveryAutoConfiguration.class})
public class PolarisServiceRegistryAutoConfiguration {
@Bean
public PolarisServiceRegistry polarisServiceRegistry(PolarisProperties polarisProperties,
PolarisDiscoveryHandler polarisDiscoveryHandler,
MetadataLocalProperties metadataLocalProperties) {
return new PolarisServiceRegistry(polarisProperties, polarisDiscoveryHandler, metadataLocalProperties);
}
@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
public PolarisRegistration polarisRegistration(PolarisProperties polarisProperties,
SDKContext context) {
return new PolarisRegistration(polarisProperties, context);
}
@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
public PolarisAutoServiceRegistration polarisAutoServiceRegistration(PolarisServiceRegistry registry,
AutoServiceRegistrationProperties autoServiceRegistrationProperties, PolarisRegistration registration) {
return new PolarisAutoServiceRegistration(registry,
autoServiceRegistrationProperties, registration);
}
}

@ -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.ribbon;
import com.tencent.cloud.polaris.discovery.ConditionalOnPolarisDiscoveryEnabled;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration;
import org.springframework.cloud.netflix.ribbon.RibbonClients;
import org.springframework.context.annotation.Configuration;
/**
* @author Haotian Zhang
*/
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties
@ConditionalOnPolarisDiscoveryEnabled
@AutoConfigureAfter(RibbonAutoConfiguration.class)
@RibbonClients(defaultConfiguration = PolarisRibbonServerListConfiguration.class)
public class PolarisDiscoveryRibbonAutoConfiguration {
}

@ -0,0 +1,42 @@
/*
* 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.ribbon;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author Haotian Zhang
*/
@Configuration
public class PolarisRibbonServerListConfiguration {
@Bean
@ConditionalOnMissingBean
public ServerList<Server> ribbonServerList(PolarisDiscoveryHandler polarisDiscoveryHandler,
IClientConfig iClientConfig) {
PolarisServerList serverList = new PolarisServerList(polarisDiscoveryHandler);
serverList.initWithNiwsConfig(iClientConfig);
return serverList;
}
}

@ -0,0 +1,74 @@
/*
* 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.ribbon;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractServerList;
import com.netflix.loadbalancer.Server;
import com.tencent.cloud.polaris.pojo.PolarisServer;
import com.tencent.polaris.api.pojo.Instance;
import com.tencent.polaris.api.pojo.ServiceInstances;
import com.tencent.polaris.api.rpc.InstancesResponse;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler;
import java.util.ArrayList;
import java.util.List;
/**
* @author Haotian Zhang
*/
public class PolarisServerList extends AbstractServerList<Server> {
private String serviceId;
private PolarisDiscoveryHandler polarisDiscoveryHandler;
public PolarisServerList(PolarisDiscoveryHandler polarisDiscoveryHandler) {
this.polarisDiscoveryHandler = polarisDiscoveryHandler;
}
@Override
public List<Server> getInitialListOfServers() {
return getServers();
}
@Override
public List<Server> getUpdatedListOfServers() {
return getServers();
}
private List<Server> getServers() {
InstancesResponse filteredInstances = polarisDiscoveryHandler.getInstances(serviceId);
ServiceInstances serviceInstances = filteredInstances.toServiceInstances();
List<Server> polarisServers = new ArrayList<>();
for (Instance instance : serviceInstances.getInstances()) {
polarisServers.add(new PolarisServer(serviceInstances, instance));
}
return polarisServers;
}
public String getServiceId() {
return serviceId;
}
@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) {
this.serviceId = iClientConfig.getClientName();
}
}

@ -0,0 +1,46 @@
{
"properties": [
{
"name": "spring.cloud.polaris.discovery.service",
"type": "java.lang.String",
"defaultValue": "${spring.application.name}",
"description": "the service name to register, default value is ${spring.application.name}."
},
{
"name": "spring.cloud.polaris.discovery.enabled",
"type": "java.lang.Boolean",
"defaultValue": true,
"description": "enable polaris discovery or not."
},
{
"name": "spring.cloud.polaris.discovery.instance-enabled",
"type": "java.lang.Boolean",
"defaultValue": true,
"description": "If instance is enabled to accept request. The default value is true."
},
{
"name": "spring.cloud.polaris.discovery.token",
"type": "java.lang.String",
"defaultValue": "${spring.cloud.polaris.token}",
"description": "polaris discovery service's username to authenticate."
},
{
"name": "spring.cloud.polaris.discovery.version",
"type": "java.lang.String",
"defaultValue": "${spring.cloud.polaris.version}",
"description": "polaris discovery service's username to authenticate."
},
{
"name": "spring.cloud.polaris.protocol",
"type": "java.lang.String",
"defaultValue": "${spring.cloud.polaris.protocol}",
"description": "the protocol of polaris instance ."
},
{
"name": "spring.cloud.polaris.weight",
"type": "java.lang.String",
"defaultValue": 100,
"description": "the weight of polaris instance , use to loadbalance."
}
]
}

@ -0,0 +1,5 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.tencent.cloud.polaris.discovery.PolarisDiscoveryAutoConfiguration,\
com.tencent.cloud.polaris.ribbon.PolarisDiscoveryRibbonAutoConfiguration,\
com.tencent.cloud.polaris.registry.PolarisServiceRegistryAutoConfiguration

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save