merge from 2.2.4.RELEASE

pull/1955/head
theonefx 4 years ago
commit 36bc0e5caf

@ -24,7 +24,7 @@ jobs:
- ~/.m2
- run:
name: "Running build"
command: ./mvnw -Pdocs clean install -U -nsu --batch-mode -Dmaven.test.redirectTestOutputToFile=true -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn -Dgpg.skip
command: ./mvnw clean install -U -nsu --batch-mode -Dmaven.test.redirectTestOutputToFile=true -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn -Dgpg.skip
- run:
name: "Aggregate test results"
when: always

8
.gitignore vendored

@ -33,3 +33,11 @@ target
.DS_Store
.flattened-pom.xml
# temp ignore
*.cache
*.diff
*.patch
*.tmp
# Maven ignore
.flattened-pom.xml

@ -1 +0,0 @@
-DaltSnapshotDeploymentRepository=repo.spring.io::default::https://repo.spring.io/libs-snapshot-local -P spring

@ -39,8 +39,6 @@ Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。
**[Seata](https://github.com/seata/seata)**:阿里巴巴开源产品,一个易于使用的高性能微服务分布式事务解决方案。
**[Alibaba Cloud ACM](https://www.aliyun.com/product/acm)**:一款在分布式架构环境中对应用配置进行集中管理和推送的应用配置中心产品。
**[Alibaba Cloud OSS](https://www.aliyun.com/product/oss)**: 阿里云对象存储服务Object Storage Service简称 OSS是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。
**[Alibaba Cloud SchedulerX](https://help.aliyun.com/document_detail/43136.html)**: 阿里中间件团队开发的一款分布式任务调度产品,提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。
@ -72,7 +70,7 @@ Spring Cloud 使用 Maven 来构建,最快的使用方式是将本项目 clone
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<version>2.1.4.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@ -97,13 +95,11 @@ Example 列表:
[Seata Example](https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-examples/seata-example/readme-zh.md)
[Alibaba Cloud OSS Example](https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-examples/oss-example/readme-zh.md)
[Alibaba Cloud ANS Example](https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-examples/ans-example/ans-provider-example/readme-zh.md)
[Alibaba Cloud OSS Example](https://github.com/alibaba/aliyun-spring-boot/tree/master/aliyun-spring-boot-samples/aliyun-oss-spring-boot-sample)
[Alibaba Cloud ACM Example](https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-examples/acm-example/acm-local-example/readme-zh.md)
[Alibaba Cloud SMS Example](https://github.com/alibaba/aliyun-spring-boot/tree/master/aliyun-spring-boot-samples/aliyun-sms-spring-boot-sample)
[Alibaba Cloud SchedulerX Example](https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-examples/schedulerx-example/schedulerx-simple-task-example/readme-zh.md)
[Alibaba Cloud SchedulerX Example](https://github.com/alibaba/aliyun-spring-boot)
## 版本管理规范
@ -114,6 +110,7 @@ Example 列表:
* 1.5.x 版本适用于 Spring Boot 1.5.x
* 2.0.x 版本适用于 Spring Boot 2.0.x
* 2.1.x 版本适用于 Spring Boot 2.1.x
* 2.2.x 版本适用于 Spring Boot 2.2.x
## 社区交流
@ -124,7 +121,9 @@ spring-cloud-alibaba@googlegroups.com欢迎通过此邮件列表讨论与 spr
### 钉钉群
![DingQR](https://img.alicdn.com/tfs/TB1zrRie4v1gK0jSZFFXXb0sXXa-7862-3570.png)
![DingQR](https://img.alicdn.com/tfs/TB1jXikzAL0gK0jSZFtXXXQCXXa-1002-323.png)
如图片有问题,访问 https://img.alicdn.com/tfs/TB1jXikzAL0gK0jSZFtXXXQCXXa-1002-323.png
## 社区相关开源

@ -45,7 +45,7 @@ For more features, please refer to [Roadmap](https://github.com/alibaba/spring-c
**[Alibaba Cloud SMS](https://www.aliyun.com/product/sms)**: A messaging service that covers the globe, Alibaba SMS provides convenient, efficient, and intelligent communication capabilities that help businesses quickly contact their customers.
**[Alibaba Cloud SchedulerX](https://www.aliyun.com/product/SchedulerX)**:accurate, highly reliable, and highly available scheduled job scheduling services with response time within seconds..
**[Alibaba Cloud SchedulerX](https://www.aliyun.com/aliware/schedulerx?spm=5176.10695662.784137.1.4b07363dej23L3)**:accurate, highly reliable, and highly available scheduled job scheduling services with response time within seconds..
For more features please refer to [Roadmap](https://github.com/alibaba/spring-cloud-alibaba/blob/master/Roadmap.md).
@ -71,7 +71,7 @@ These artifacts are available from Maven Central and Spring Release repository v
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<version>2.2.4.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@ -89,8 +89,6 @@ add the module in `dependencies`.
[Nacos Discovery](https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-discovery.adoc)
[ACM](https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-docs/src/main/asciidoc-zh/acm.adoc)
## Examples
@ -106,9 +104,9 @@ Examples
[RocketMQ Example](https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-examples/rocketmq-example/readme.md)
[Alibaba Cloud OSS Example](https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-examples/oss-example/readme.md)
[Alibaba Cloud OSS Example](https://github.com/alibaba/aliyun-spring-boot/tree/master/aliyun-spring-boot-samples/aliyun-oss-spring-boot-sample)
[Duboo Spring Cloud Example](https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/README_CN.md)
[Dubbo Spring Cloud Example](https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/README_CN.md)
## Version control guidelines
The version number of the project is in the form of x.x.x, where x is a number, starting from 0, and is not limited to the range 0~9. When the project is in the incubator phase, the version number is 0.x.x.
@ -118,6 +116,7 @@ As the interfaces and annotations of Spring Boot 1 and Spring Boot 2 have been c
* 1.5.x for Spring Boot 1.5.x
* 2.0.x for Spring Boot 2.0.x
* 2.1.x for Spring Boot 2.1.x
* 2.2.x for Spring Boot 2.2.x
## Code of Conduct
This project is a sub-project of Spring Cloud, it adheres to the Contributor Covenant [code of conduct](https://github.com/spring-cloud/spring-cloud-build/blob/master/docs/src/main/asciidoc/code-of-conduct.adoc). By participating, you are expected to uphold this code. Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.

1
mvnw vendored

@ -249,5 +249,6 @@ fi
exec "$JAVACMD" \
$MAVEN_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Drevision=${VERSION}" \
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} ${MAVEN_ARGS} "$@"

@ -80,7 +80,7 @@
<properties>
<!-- Project revision -->
<revision>2.1.3.RELEASE</revision>
<revision>2.1.4.RELEASE</revision>
<!-- Dependency Versions -->
<spring-cloud-commons.version>2.1.6.RELEASE</spring-cloud-commons.version>
@ -98,7 +98,7 @@
<slf4j-api.version>1.7.25</slf4j-api.version>
<!-- Apache Dubbo -->
<dubbo.version>2.7.6</dubbo.version>
<dubbo.version>2.7.8</dubbo.version>
<curator.version>4.0.1</curator.version>
<!-- Apache RocketMQ -->
@ -108,12 +108,12 @@
<maven-compiler-plugin.version>3.7.0</maven-compiler-plugin.version>
<maven-deploy-plugin.version>2.8.2</maven-deploy-plugin.version>
<maven-surefire-plugin.version>2.21.0</maven-surefire-plugin.version>
<gmavenplus-plugin.version>1.6</gmavenplus-plugin.version>
<jacoco.version>0.8.3</jacoco.version>
<maven-source-plugin.version>2.2.1</maven-source-plugin.version>
<maven-javadoc-plugin.version>3.1.1</maven-javadoc-plugin.version>
<maven-gpg-plugin.version>1.6</maven-gpg-plugin.version>
<flatten-maven-plugin.version>1.1.0</flatten-maven-plugin.version>
<gmavenplus-plugin.version>1.6</gmavenplus-plugin.version>
<jacoco.version>0.8.3</jacoco.version>
</properties>
<modules>
@ -349,6 +349,31 @@
<reuseForks>false</reuseForks>
</configuration>
</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>
@ -362,69 +387,6 @@
</reporting>
<profiles>
<profile>
<id>spring</id>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/libs-snapshot-local</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
<releases>
<enabled>false</enabled>
</releases>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/libs-snapshot-local</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
<releases>
<enabled>false</enabled>
</releases>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/libs-release-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
<profile>
<id>release</id>
<build>
@ -469,32 +431,6 @@
</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>
@ -511,9 +447,6 @@
</repository>
</distributionManagement>
</profile>
</profiles>
</project>

@ -19,60 +19,60 @@
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-datasource</artifactId>
<version>${project.version}</version>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>${project.version}</version>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
<version>${project.version}</version>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>${project.version}</version>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>${project.version}</version>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config-server</artifactId>
<version>${project.version}</version>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rocketmq</artifactId>
<version>${project.version}</version>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-bus-rocketmq</artifactId>
<version>${project.version}</version>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sidecar</artifactId>
<version>${project.version}</version>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
<version>${project.version}</version>
<version>${revision}</version>
</dependency>
</dependencies>

@ -19,11 +19,11 @@
<properties>
<!-- Project revision -->
<revision>2.1.3.RELEASE</revision>
<revision>2.1.4.RELEASE</revision>
<sentinel.version>1.8.0</sentinel.version>
<seata.version>1.3.0</seata.version>
<nacos.client.version>1.3.3</nacos.client.version>
<nacos.client.version>1.4.1</nacos.client.version>
<nacos.config.version>0.8.0</nacos.config.version>
<spring.context.support.version>1.0.10</spring.context.support.version>
@ -185,67 +185,74 @@
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-datasource</artifactId>
<version>${project.version}</version>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
<version>${project.version}</version>
<version>${revision}</version>
</dependency>
<!-- Own dependencies - Starters -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>${project.version}</version>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-circuitbreaker-sentinel</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
<version>${project.version}</version>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>${project.version}</version>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>${project.version}</version>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config-server</artifactId>
<version>${project.version}</version>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rocketmq</artifactId>
<version>${project.version}</version>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-bus-rocketmq</artifactId>
<version>${project.version}</version>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sidecar</artifactId>
<version>${project.version}</version>
<version>${revision}</version>
</dependency>
<!-- Dubbo -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
<version>${project.version}</version>
<version>${revision}</version>
</dependency>
<dependency>
@ -260,69 +267,6 @@
</dependencyManagement>
<profiles>
<profile>
<id>spring</id>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/libs-snapshot-local</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
<releases>
<enabled>false</enabled>
</releases>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/libs-snapshot-local</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
<releases>
<enabled>false</enabled>
</releases>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/libs-release-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
<profile>
<id>release</id>
<build>
@ -409,5 +353,6 @@
</repository>
</distributionManagement>
</profile>
</profiles>
</project>

@ -6,7 +6,9 @@
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-alibaba-docs</artifactId>

@ -10,7 +10,7 @@ Spring Cloud Alibaba BOM 包含了它所使用的所有依赖的版本。
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.3.RELEASE</version>
<version>2.1.4.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>

@ -229,7 +229,7 @@ in develop-env enviroment; user name :nacos-config-yaml-update; age: 68
spring.profiles.active=product
----
同时生产环境上 Nacos 需要添加对应 DataId 的基础配置。例如,在生环境下的 Naocs 添加了DataId为nacos-config-product.yaml的配置
同时生产环境上 Nacos 需要添加对应 DataId 的基础配置。例如,在生环境下的 Naocs 添加了DataId为nacos-config-product.yaml的配置
[source,subs="normal"]
----
@ -415,8 +415,8 @@ Endpoint 暴露的 json 中包含了三种属性:
|===
|配置项 |Key |默认值 |说明
|服务端地址|`spring.cloud.nacos.config.server-addr`|| Nacos Server 启动监听的ip地址和端口
|配置对应的 DataId|`spring.cloud.nacos.config.name`|| 先取 prefix name最后取 spring.application.name
|配置对应的 DataId|`spring.cloud.nacos.config.prefix`|| 先取 prefix name最后取 spring.application.name
|配置对应的 DataId|`spring.cloud.nacos.config.name`|| 先取 prefix name最后取 spring.application.name
|配置对应的 DataId|`spring.cloud.nacos.config.prefix`|| 先取 prefix name最后取 spring.application.name
|配置内容编码|`spring.cloud.nacos.config.encode`||读取的配置内容对应的编码
|GROUP|`spring.cloud.nacos.config.group`|`DEFAULT_GROUP`|配置对应的组
|文件扩展名|`spring.cloud.nacos.config.fileExtension`|`properties`|配置项对应的文件扩展名,目前支持 properties 和 yaml(yml)

@ -1,10 +1,11 @@
== Spring Cloud Alibaba Sidecar
`Spring Cloud Alibaba Sidecar` 是一个用来快速**完美整合** Spring Cloud 与 *异构微服务* 的框架,灵感来自
https://github.com/spring-cloud/spring-cloud-netflix/tree/master/spring-cloud-netflix-sidecar[Spring Cloud Netflix Sidecar] 。目前支持的服务发现组件:
`Spring Cloud Alibaba Sidecar` 是一个用来快速**完美整合** Spring Cloud
与 *异构微服务* 的框架,灵感来自
https://github.com/spring-cloud/spring-cloud-netflix/tree/master/spring-cloud-netflix-sidecar[Spring
Cloud Netflix Sidecar] 。目前支持的服务发现组件:
* Nacos
* Consul
=== 术语
@ -25,26 +26,42 @@ https://github.com/spring-cloud/spring-cloud-netflix/tree/master/spring-cloud-ne
原因有两点:
* Spring Cloud子项目 `Spring Cloud Netflix Sidecar` 是可以快速整合异构微服务的。然而Sidecar只支持使用Eureka作为服务发现*如果使用其他服务发现组件就抓瞎了*。
* *Sidecar是基于Zuul 1.x的*Spring Cloud官方明确声明未来将会逐步淘汰Zuul。今年早些时候我有给Spring Cloud官方提出需求希望官方实现一个基于Spring Cloud Gateway的新一代Sidecar然而官方表示并没有该计划。详见https://github.com/spring-cloud/spring-cloud-gateway/issues/735
* Spring Cloud子项目 `Spring Cloud Netflix Sidecar`
是可以快速整合异构微服务的。然而Sidecar只支持使用Eureka作为服务发现*如果使用其他服务发现组件就抓瞎了*。
* *Sidecar是基于Zuul 1.x的*Spring
Cloud官方明确声明未来将会逐步淘汰Zuul。今年早些时候我有给Spring
Cloud官方提出需求希望官方实现一个基于Spring Cloud
Gateway的新一代Sidecar然而官方表示并没有该计划。详见https://github.com/spring-cloud/spring-cloud-gateway/issues/735
既然没有,索性自己写了。
==== 为什么不用Service Mesh
* 目前Mesh主要使用场景在Kubernetes领域Istio、Linkerd大多将Kubernetes作为First Class支持虽然Istio也可部署在非Kubernetes环境而目前业界Spring Cloud应用未必有试试Mesh的环境
* 使用Alibaba Sidecar一个小组件就能解决问题了核心代码不超过200行引入整套Mesh方案颇有点屠龙刀杀黄鳝的意思。
* 目前Mesh主要使用场景在Kubernetes领域Istio、Linkerd
2等大多将Kubernetes作为First
Class支持虽然Istio也可部署在非Kubernetes环境而目前业界Spring
Cloud应用未必有试试Mesh的环境
* 使用Alibaba
Sidecar一个小组件就能解决问题了核心代码不超过200行引入整套Mesh方案颇有点屠龙刀杀黄鳝的意思。
=== 原理
* Alibaba
Sidecar根据配置的异构微服务的IP、端口等信息*将异构微服务的IP/端口注册到服务发现组件上*。
* Alibaba Sidecar实现了 *健康检查* Alibaba Sidecar会定时检测异构微服务是否健康。如果发现异构微服务不健康Alibaba Sidecar会自动将代表异构微服务的Alibaba Sidecar实例下线如果异构微服务恢复正常则会自动上线。最长延迟是30秒详见 `Alibaba SidecarChecker#check` 。
Sidecar根据配置的异构微服务的IP、端口等信息*将异构微服务的IP/端口注册到服务发现组件上*
* Alibaba Sidecar实现了 *健康检查* Alibaba
Sidecar会定时检测异构微服务是否健康。如果发现异构微服务不健康Alibaba
Sidecar会自动将代表异构微服务的Alibaba
Sidecar实例下线如果异构微服务恢复正常则会自动上线。最长延迟是30秒详见
`Alibaba SidecarChecker#check` 。
=== 要求
* 【必须】你的异构微服务需使用HTTP通信。这一点严格来说不算要求因为Spring Cloud本身就是基于HTTP的
* 【可选】如果微服务配置了 `sidecar.health-check-url`,则表示开启健康检查,此时,你的异构微服务需实现健康检查(可以是空实现,只要暴露一个端点,返回类似 `{"status": "UP"}` 的字符串即可)。
* 【必须】你的异构微服务需使用HTTP通信。这一点严格来说不算要求因为Spring
Cloud本身就是基于HTTP的
* 【可选】如果微服务配置了 `sidecar.health-check-url`
,则表示开启健康检查,此时,你的异构微服务需实现健康检查(可以是空实现,只要暴露一个端点,返回类似
`{"status": "UP"}` 的字符串即可)。
=== 使用示例
@ -92,7 +109,8 @@ endpoint:
show-details: always
----
+
配置比较简单就是把Alibaba Sidecar注册到Nacos上然后添加了几行Alibaba Sidecar的配置。
配置比较简单就是把Alibaba Sidecar注册到Nacos上然后添加了几行Alibaba
Sidecar的配置。
==== 异构微服务
@ -132,13 +150,16 @@ server.listen(8060, function() {
===== 测试1Spring Cloud微服务完美调用异构微服务
为你的Spring Cloud微服务整合Ribbon然后构建 `http://node-service/\\**`,就可以请求到异构微服务的 `/**` 了。
为你的Spring Cloud微服务整合Ribbon然后构建 `http://node-service/**`
,就可以请求到异构微服务的 `/**` 了。
示例:
Ribbon请求 `http://node-service/` 会请求到 `http://localhost:8060/`,以此类推。
Ribbon请求 `http://node-service/` 会请求到 `http://localhost:8060/`
,以此类推。
至于断路器正常为你的Spring Cloud微服务整合Sentinel或者Hystirx、Resilience4J即可 。
至于断路器正常为你的Spring
Cloud微服务整合Sentinel或者Hystirx、Resilience4J即可 。
===== 测试2异构微服务完美调用Spring Cloud微服务
@ -146,13 +167,18 @@ Ribbon请求 `http://node-service/` 会请求到 `http://localhost:8060/`,以
示例:
如果你有一个Spring Cloud微服务叫做 `spring-cloud-microservice`那么NodeJS应用只需构建 `http://localhost:8070/spring-cloud-microservice/\\**` Alibaba Sidecar就会把请求转发到 `spring-cloud-microservice` 的 `/**` 。
如果你有一个Spring Cloud微服务叫做 `spring-cloud-microservice`
那么NodeJS应用只需构建
`http://localhost:8070/spring-cloud-microservice/**` Alibaba
Sidecar就会把请求转发到 `spring-cloud-microservice` 的 `/**` 。
而Spring Cloud Gateway是整合了Ribbon的所以实现了负载均衡Spring Cloud Gateway还可以整合Sentinel或者Hystirx、Resilience4J所以也带有了断路器。
而Spring Cloud Gateway是整合了Ribbon的所以实现了负载均衡Spring Cloud
Gateway还可以整合Sentinel或者Hystirx、Resilience4J所以也带有了断路器。
=== Alibaba Sidecar优缺点分析
Alibaba Sidecar的设计和Sidecar基本一致优缺点和Sidecar的优缺点也是一样的。
Alibaba
Sidecar的设计和Sidecar基本一致优缺点和Sidecar的优缺点也是一样的。
优点:
@ -161,5 +187,8 @@ Alibaba Sidecar的设计和Sidecar基本一致优缺点和Sidecar的优缺点
缺点:
* 每接入一个异构微服务实例都需要额外部署一个Alibaba Sidecar实例增加了部署成本虽然这个成本在Kubernetes环境中几乎可以忽略不计只需将Alibaba Sidecar实例和异构微服务作为一个Pod部署即可
* 异构微服务调用Spring Cloud微服务时本质是把Alibaba Sidecar当网关在使用经过了一层转发性能有一定下降。
* 每接入一个异构微服务实例都需要额外部署一个Alibaba
Sidecar实例增加了部署成本虽然这个成本在Kubernetes环境中几乎可以忽略不计只需将Alibaba
Sidecar实例和异构微服务作为一个Pod部署即可
* 异构微服务调用Spring Cloud微服务时本质是把Alibaba
Sidecar当网关在使用经过了一层转发性能有一定下降。

@ -8,7 +8,7 @@ If youre a Maven Central user, add our BOM to your pom.xml <dependencyManagem
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.3.RELEASE</version>
<version>2.1.4.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>

@ -1,6 +1,6 @@
== Introduction
Spring Cloud Alibaba aims to provide a one-stop solution for microservices development. This prjoect includes the required components for developing distributed applications and services, so that developers can develop distributed applications easily with the Spring Cloud programming models.
Spring Cloud Alibaba aims to provide a one-stop solution for microservices development. This project includes the required components for developing distributed applications and services, so that developers can develop distributed applications easily with the Spring Cloud programming models.
With Spring Cloud Alibaba, you only need to add a few annotations and configurations, and you will be able to use the distributed solutions of Alibaba for your applications, and build a distributed system of your own with Alibaba middleware.
@ -16,4 +16,4 @@ The features of Spring Cloud Alibaba:
8. **Alibaba Cloud SchedulerX**accurate, highly reliable, and highly available scheduled job scheduling services with response time within seconds.
9. **Alibaba Cloud SMS** A messaging service that covers the globe, Alibaba SMS provides convenient, efficient, and intelligent communication capabilities that help businesses quickly contact their customers.
Spring Cloud Alibaba also provide rich https://github.com/alibaba/spring-cloud-alibaba/tree/master/spring-cloud-alibaba-examples[examples].
Spring Cloud Alibaba also provide rich https://github.com/alibaba/spring-cloud-alibaba/tree/master/spring-cloud-alibaba-examples[examples].

@ -159,7 +159,7 @@ NOTE: Before you start the provider application, please start Nacos first. Refer
==== Start a Consumer Application
It might not be as easy as starting a provider application, because the consumer needs to call the RESTful service of the provider. In this example, we will use the most primitive way, that is,
combining the LoadBalanceClient and RestTemolate explicitly to access the RESTful service.
combining the LoadBalanceClient and RestTemplate explicitly to access the RESTful service.
You can refer to section 1.2 for pom.xml and application.properties configurations. The following is the sample code for starting a consumer application.
NOTE: You can also access the service by using RestTemplate and FeignClient with load balancing.

@ -15,6 +15,7 @@
<description>Example demonstrating how to use nacos config</description>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>

@ -175,7 +175,7 @@ AccessKey|spring.cloud.nacos.config.access-key||
SecretKey|spring.cloud.nacos.config.secret-key||
相对路径|spring.cloud.nacos.config.context-path||服务端 API 的相对路径
接入点|spring.cloud.nacos.config.endpoint|UTF-8|地域的某个服务的入口域名,通过此域名可以动态地拿到服务端地址
是否开启监听和自动刷新|spring.cloud.nacos.config.refresh.enabled|true|
是否开启监听和自动刷新|spring.cloud.nacos.config.refresh-enabled|true|

@ -25,6 +25,7 @@ Before we start the demo, let's learn how to connect Nacos Config to a Spring Cl
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
3. After completing the above two steps, the application will get the externalized configuration from Nacos Server and put it in the Spring Environment's PropertySources.We use the @Value annotation to inject the corresponding configuration into the userName and age fields of the SampleController, and add @RefreshScope to turn on dynamic refresh .
@RefreshScope
class SampleController {

@ -18,6 +18,7 @@ package com.alibaba.cloud.examples;
import java.io.IOException;
import java.io.StringReader;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;
@ -34,7 +35,9 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@ -62,8 +65,12 @@ class UserConfig {
private String name;
private String hr;
private Map<String, Object> map;
private List<User> users;
public int getAge() {
return age;
}
@ -88,10 +95,65 @@ class UserConfig {
this.map = map;
}
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
public String getHr() {
return hr;
}
public void setHr(String hr) {
this.hr = hr;
}
@Override
public String toString() {
return "UserConfig{" + "age=" + age + ", name='" + name + '\'' + ", map=" + map
+ '}';
+ ", hr='" + hr + '\'' + ", users=" + users + '}';
}
public static class User {
private String name;
private String hr;
private String avg;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getHr() {
return hr;
}
public void setHr(String hr) {
this.hr = hr;
}
public String getAvg() {
return avg;
}
public void setAvg(String avg) {
this.avg = avg;
}
@Override
public String toString() {
return "User{" + "name='" + name + '\'' + ", hr=" + hr + ", avg=" + avg + '}';
}
}
}
@ -99,7 +161,7 @@ class UserConfig {
@Component
class SampleRunner implements ApplicationRunner {
@Value("${user.name}")
@Value("${user.name:zz}")
String userName;
@Value("${user.age:25}")
@ -156,7 +218,10 @@ class SampleController {
@Autowired
private NacosConfigManager nacosConfigManager;
@Value("${user.name}")
@Autowired
private Environment environment;
@Value("${user.name:zz}")
String userName;
@Value("${user.age:25}")
@ -168,6 +233,11 @@ class SampleController {
+ userConfig + "!" + nacosConfigManager.getConfigService();
}
@RequestMapping("/get/{name}")
public String getValue(@PathVariable String name) {
return String.valueOf(environment.getProperty(name));
}
@RequestMapping("/bool")
public boolean bool() {
return (Boolean) (userConfig.getMap().get("2"));

@ -5,19 +5,26 @@ spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.username=nacos
spring.cloud.nacos.password=nacos
#spring.cloud.nacos.config.namespace=public
spring.cloud.nacos.config.name=test-aaa
spring.cloud.nacos.config.file-extension=yaml
#spring.cloud.nacos.config.refreshable-dataids=common.properties
#spring.cloud.nacos.config.shared-data-ids=common.properties,base-common.properties
spring.cloud.nacos.config.shared-configs[0]= common333.properties
spring.cloud.nacos.config.shared-configs[1].data-id= common111.properties
spring.cloud.nacos.config.shared-configs[1].group= GROUP_APP1
spring.cloud.nacos.config.shared-configs[1].refresh= true
spring.cloud.nacos.config.shared-configs[2]= common222.properties
#spring.cloud.nacos.config.shared-configs[0]= common333.properties
#spring.cloud.nacos.config.shared-configs[1].data-id= common111.properties
#spring.cloud.nacos.config.shared-configs[1].group= GROUP_APP1
#spring.cloud.nacos.config.shared-configs[1].refresh= true
#spring.cloud.nacos.config.shared-configs[2]= common222.properties
spring.cloud.nacos.config.shared-configs[0].data-id= test2.yaml
spring.cloud.nacos.config.shared-configs[0].refresh=true
#spring.cloud.nacos.config.ext-config[0]=ext.properties
spring.cloud.nacos.config.extension-configs[0].data-id= extension1.properties
spring.cloud.nacos.config.extension-configs[0].refresh= true
spring.cloud.nacos.config.extension-configs[1]= extension2.properties
spring.cloud.nacos.config.extension-configs[2].data-id= extension3.json
spring.cloud.nacos.config.extension-configs[0].refresh=true
spring.cloud.nacos.config.extension-configs[1].data-id= test1.yml
spring.cloud.nacos.config.extension-configs[1].refresh= true

@ -15,6 +15,7 @@
<description>Example demonstrating how to use nacos discovery</description>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>

@ -9,11 +9,13 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>nacos-discovery-provider-example</artifactId>
<name>Spring Cloud Starter Alibaba Nacos Discovery Provider Example</name>
<description>Example demonstrating how to use nacos discovery</description>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>

@ -1,6 +1,7 @@
server.port=18082
spring.application.name=service-provider
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
#spring.cloud.nacos.discovery.instance-enabled=true
spring.cloud.nacos.username=nacos
spring.cloud.nacos.password=nacos

@ -9,11 +9,13 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>nacos-discovery-spring-cloud-config-client-example</artifactId>
<name>Spring Cloud Starter Alibaba Nacos Discovery x Config Client Example</name>
<description>Example demonstrating how to use nacos discovery</description>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>

@ -9,11 +9,13 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>nacos-discovery-spring-cloud-config-server-example</artifactId>
<name>Spring Cloud Starter Alibaba Nacos Discovery x Config Server Example</name>
<description>Example demonstrating how to use nacos discovery</description>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>

@ -15,6 +15,7 @@
<description>Example demonstrating how to use nacos discovery</description>
<packaging>pom</packaging>
<modules>
<module>nacos-discovery-consumer-example</module>
<module>nacos-discovery-provider-example</module>

@ -30,7 +30,7 @@
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
SpringApplication.run(ProviderApplication.class, args);
}
@RestController

@ -29,7 +29,7 @@ Before we start the demo, let's learn how to connect Nacos Config to a Spring Cl
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
SpringApplication.run(ProviderApplication.class, args);
}
@RestController
@ -207,6 +207,7 @@ Metadata|spring.cloud.nacos.discovery.metadata||Extended data, Configure using M
log name|spring.cloud.nacos.discovery.log-name||
endpoint|spring.cloud.nacos.discovery.endpoint||The domain name of a service, through which the server address can be dynamically obtained.
Integration Ribbon|ribbon.nacos.enabled|true|
enabled|spring.cloud.nacos.discovery.enabled|true|The switch to enable or disable nacos service discovery

@ -9,11 +9,13 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>nacos-gateway-discovery-example</artifactId>
<name>Spring Cloud Starter Alibaba Nacos Discovery x Gateway Example</name>
<description>Example demonstrating how to use gateway with nacos</description>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>

@ -9,11 +9,13 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>nacos-gateway-provider-example</artifactId>
<name>Spring Cloud Starter Alibaba Nacos Discovery x Gateway - Provider Example</name>
<description>Example demonstrating how to use gateway with nacos</description>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>

@ -10,11 +10,13 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>nacos-gateway-example</artifactId>
<name>Spring Cloud Starter Alibaba Nacos Discovery x Gateway Examples</name>
<description>Example demonstrating how to use gateway with nacos</description>
<packaging>pom</packaging>
<modules>
<module>nacos-gateway-discovery-example</module>
<module>nacos-gateway-provider-example</module>

@ -10,11 +10,13 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>rocketmq-consume-example</artifactId>
<name>Spring Cloud Starter Stream Alibaba RocketMQ Consume Example</name>
<description>Example demonstrating how to use rocketmq consume</description>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>

@ -10,11 +10,13 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>rocketmq-produce-example</artifactId>
<name>Spring Cloud Starter Stream Alibaba RocketMQ Produce Example</name>
<description>Example demonstrating how to use rocketmq produce</description>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>

@ -83,7 +83,7 @@ public class RocketMQProduceApplication {
@Override
public void run(String... args) throws Exception {
if (this.bindingName.equals("output1")) {
if ("output1".equals(this.bindingName)) {
int count = 5;
for (int index = 1; index <= count; index++) {
String msgContent = "msg-" + index;
@ -98,7 +98,7 @@ public class RocketMQProduceApplication {
}
}
}
else if (this.bindingName.equals("output3")) {
else if ("output3".equals(this.bindingName)) {
int count = 20;
for (int index = 1; index <= count; index++) {
String msgContent = "pullMsg-" + index;

@ -9,8 +9,8 @@
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>account-service</artifactId>
<artifactId>account-service</artifactId>
<name>Spring Cloud Starter Alibaba Seata Example - Account Service</name>
<packaging>jar</packaging>

@ -1,67 +0,0 @@
transport {
# tcp udt unix-domain-socket
type = "TCP"
#NIO NATIVE
server = "NIO"
#enable heartbeat
heartbeat = false
#thread factory for netty
thread-factory {
boss-thread-prefix = "NettyBoss"
worker-thread-prefix = "NettyServerNIOWorker"
server-executor-thread-prefix = "NettyServerBizHandler"
share-boss-worker = false
client-selector-thread-prefix = "NettyClientSelector"
client-selector-thread-size = 1
client-worker-thread-prefix = "NettyClientWorkerThread"
# netty boss thread size,will not be used for UDT
boss-thread-size = 1
#auto default pin or 8
worker-thread-size = 8
}
shutdown {
# when destroy server, wait seconds
wait = 3
}
serialization = "seata"
compressor = "none"
}
service {
#vgroup->rgroup
vgroup_mapping.account-service-seata-service-group = "default"
#only support single node
default.grouplist = "127.0.0.1:8091"
#degrade current not support
enableDegrade = false
#disable
disable = false
#unit ms,s,m,h,d represents milliseconds, seconds, minutes, hours, days, default permanent
max.commit.retry.timeout = "-1"
max.rollback.retry.timeout = "-1"
}
client {
async.commit.buffer.limit = 10000
lock {
retry.internal = 10
retry.times = 30
}
report.retry.count = 5
tm.commit.retry.count = 1
tm.rollback.retry.count = 1
}
transaction {
undo.data.validation = true
undo.log.serialization = "jackson"
undo.log.save.days = 7
#schedule delete expired undo_log in milliseconds
undo.log.delete.period = 86400000
undo.log.table = "undo_log"
}
support {
## spring
spring {
# auto proxy the DataSource bean
datasource.autoproxy = false
}
}

@ -1,73 +0,0 @@
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "file"
nacos {
serverAddr = "localhost"
namespace = ""
cluster = "default"
}
eureka {
serviceUrl = "http://localhost:8761/eureka"
application = "default"
weight = "1"
}
redis {
serverAddr = "localhost:6379"
db = "0"
}
zk {
cluster = "default"
serverAddr = "127.0.0.1:2181"
session.timeout = 6000
connect.timeout = 2000
}
consul {
cluster = "default"
serverAddr = "127.0.0.1:8500"
}
etcd3 {
cluster = "default"
serverAddr = "http://localhost:2379"
}
sofa {
serverAddr = "127.0.0.1:9603"
application = "default"
region = "DEFAULT_ZONE"
datacenter = "DefaultDataCenter"
cluster = "default"
group = "SEATA_GROUP"
addressWaitTime = "3000"
}
file {
name = "file.conf"
}
}
config {
# file、nacos 、apollo、zk、consul、etcd3
type = "file"
nacos {
serverAddr = "localhost"
namespace = ""
}
consul {
serverAddr = "127.0.0.1:8500"
}
apollo {
app.id = "seata-server"
apollo.meta = "http://192.168.1.204:8801"
}
zk {
serverAddr = "127.0.0.1:2181"
session.timeout = 6000
connect.timeout = 2000
}
etcd3 {
serverAddr = "http://localhost:2379"
}
file {
name = "file.conf"
}
}

@ -9,8 +9,8 @@
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>business-service</artifactId>
<artifactId>business-service</artifactId>
<name>Spring Cloud Starter Alibaba Seata Example - Business Service</name>
<packaging>jar</packaging>
@ -31,6 +31,10 @@
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-loadbalancer</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>

@ -5,6 +5,8 @@ spring.cloud.nacos.discovery.server-addr=localhost:8848
#feign.hystrix.enabled=true
#feign.sentinel.enabled=true
feign.client.config.default.connectTimeout=10000
feign.client.config.default.readTimeout=10000
logging.level.io.seata=debug

@ -1,67 +0,0 @@
transport {
# tcp udt unix-domain-socket
type = "TCP"
#NIO NATIVE
server = "NIO"
#enable heartbeat
heartbeat = false
#thread factory for netty
thread-factory {
boss-thread-prefix = "NettyBoss"
worker-thread-prefix = "NettyServerNIOWorker"
server-executor-thread-prefix = "NettyServerBizHandler"
share-boss-worker = false
client-selector-thread-prefix = "NettyClientSelector"
client-selector-thread-size = 1
client-worker-thread-prefix = "NettyClientWorkerThread"
# netty boss thread size,will not be used for UDT
boss-thread-size = 1
#auto default pin or 8
worker-thread-size = 8
}
shutdown {
# when destroy server, wait seconds
wait = 3
}
serialization = "seata"
compressor = "none"
}
service {
#vgroup->rgroup
vgroup_mapping.business-service-seata-service-group = "default"
#only support single node
default.grouplist = "127.0.0.1:8091"
#degrade current not support
enableDegrade = false
#disable
disable = false
#unit ms,s,m,h,d represents milliseconds, seconds, minutes, hours, days, default permanent
max.commit.retry.timeout = "-1"
max.rollback.retry.timeout = "-1"
}
client {
async.commit.buffer.limit = 10000
lock {
retry.internal = 10
retry.times = 30
}
report.retry.count = 5
tm.commit.retry.count = 1
tm.rollback.retry.count = 1
}
transaction {
undo.data.validation = true
undo.log.serialization = "jackson"
undo.log.save.days = 7
#schedule delete expired undo_log in milliseconds
undo.log.delete.period = 86400000
undo.log.table = "undo_log"
}
support {
## spring
spring {
# auto proxy the DataSource bean
datasource.autoproxy = false
}
}

@ -1,73 +0,0 @@
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "file"
nacos {
serverAddr = "localhost"
namespace = ""
cluster = "default"
}
eureka {
serviceUrl = "http://localhost:8761/eureka"
application = "default"
weight = "1"
}
redis {
serverAddr = "localhost:6379"
db = "0"
}
zk {
cluster = "default"
serverAddr = "127.0.0.1:2181"
session.timeout = 6000
connect.timeout = 2000
}
consul {
cluster = "default"
serverAddr = "127.0.0.1:8500"
}
etcd3 {
cluster = "default"
serverAddr = "http://localhost:2379"
}
sofa {
serverAddr = "127.0.0.1:9603"
application = "default"
region = "DEFAULT_ZONE"
datacenter = "DefaultDataCenter"
cluster = "default"
group = "SEATA_GROUP"
addressWaitTime = "3000"
}
file {
name = "file.conf"
}
}
config {
# file、nacos 、apollo、zk、consul、etcd3
type = "file"
nacos {
serverAddr = "localhost"
namespace = ""
}
consul {
serverAddr = "127.0.0.1:8500"
}
apollo {
app.id = "seata-server"
apollo.meta = "http://192.168.1.204:8801"
}
zk {
serverAddr = "127.0.0.1:2181"
session.timeout = 6000
connect.timeout = 2000
}
etcd3 {
serverAddr = "http://localhost:2379"
}
file {
name = "file.conf"
}
}

@ -9,9 +9,9 @@
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>order-service</artifactId>
<name>Spring Cloud Starter Alibaba Seata Example - Business Service</name>
<artifactId>order-service</artifactId>
<name>Spring Cloud Starter Alibaba Seata Example - Order Service</name>
<packaging>jar</packaging>
<dependencies>
@ -54,4 +54,4 @@
</dependencies>
</project>
</project>

@ -25,10 +25,10 @@ import org.springframework.web.client.RestTemplate;
* @author xiaojing
*/
@SpringBootApplication
public class OderApplication {
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OderApplication.class, args);
SpringApplication.run(OrderApplication.class, args);
}
@Bean

@ -1,67 +0,0 @@
transport {
# tcp udt unix-domain-socket
type = "TCP"
#NIO NATIVE
server = "NIO"
#enable heartbeat
heartbeat = false
#thread factory for netty
thread-factory {
boss-thread-prefix = "NettyBoss"
worker-thread-prefix = "NettyServerNIOWorker"
server-executor-thread-prefix = "NettyServerBizHandler"
share-boss-worker = false
client-selector-thread-prefix = "NettyClientSelector"
client-selector-thread-size = 1
client-worker-thread-prefix = "NettyClientWorkerThread"
# netty boss thread size,will not be used for UDT
boss-thread-size = 1
#auto default pin or 8
worker-thread-size = 8
}
shutdown {
# when destroy server, wait seconds
wait = 3
}
serialization = "seata"
compressor = "none"
}
service {
#vgroup->rgroup
vgroup_mapping.order-service-seata-service-group = "default"
#only support single node
default.grouplist = "127.0.0.1:8091"
#degrade current not support
enableDegrade = false
#disable
disable = false
#unit ms,s,m,h,d represents milliseconds, seconds, minutes, hours, days, default permanent
max.commit.retry.timeout = "-1"
max.rollback.retry.timeout = "-1"
}
client {
async.commit.buffer.limit = 10000
lock {
retry.internal = 10
retry.times = 30
}
report.retry.count = 5
tm.commit.retry.count = 1
tm.rollback.retry.count = 1
}
transaction {
undo.data.validation = true
undo.log.serialization = "jackson"
undo.log.save.days = 7
#schedule delete expired undo_log in milliseconds
undo.log.delete.period = 86400000
undo.log.table = "undo_log"
}
support {
## spring
spring {
# auto proxy the DataSource bean
datasource.autoproxy = false
}
}

@ -1,73 +0,0 @@
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "file"
nacos {
serverAddr = "localhost"
namespace = ""
cluster = "default"
}
eureka {
serviceUrl = "http://localhost:8761/eureka"
application = "default"
weight = "1"
}
redis {
serverAddr = "localhost:6379"
db = "0"
}
zk {
cluster = "default"
serverAddr = "127.0.0.1:2181"
session.timeout = 6000
connect.timeout = 2000
}
consul {
cluster = "default"
serverAddr = "127.0.0.1:8500"
}
etcd3 {
cluster = "default"
serverAddr = "http://localhost:2379"
}
sofa {
serverAddr = "127.0.0.1:9603"
application = "default"
region = "DEFAULT_ZONE"
datacenter = "DefaultDataCenter"
cluster = "default"
group = "SEATA_GROUP"
addressWaitTime = "3000"
}
file {
name = "file.conf"
}
}
config {
# file、nacos 、apollo、zk、consul、etcd3
type = "file"
nacos {
serverAddr = "localhost"
namespace = ""
}
consul {
serverAddr = "127.0.0.1:8500"
}
apollo {
app.id = "seata-server"
apollo.meta = "http://192.168.1.204:8801"
}
zk {
serverAddr = "127.0.0.1:2181"
session.timeout = 6000
connect.timeout = 2000
}
etcd3 {
serverAddr = "http://localhost:2379"
}
file {
name = "file.conf"
}
}

@ -9,6 +9,7 @@
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>storage-service</artifactId>
<name>Spring Cloud Starter Alibaba Seata Example - Storage Service</name>
<packaging>jar</packaging>

@ -1,67 +0,0 @@
transport {
# tcp udt unix-domain-socket
type = "TCP"
#NIO NATIVE
server = "NIO"
#enable heartbeat
heartbeat = false
#thread factory for netty
thread-factory {
boss-thread-prefix = "NettyBoss"
worker-thread-prefix = "NettyServerNIOWorker"
server-executor-thread-prefix = "NettyServerBizHandler"
share-boss-worker = false
client-selector-thread-prefix = "NettyClientSelector"
client-selector-thread-size = 1
client-worker-thread-prefix = "NettyClientWorkerThread"
# netty boss thread size,will not be used for UDT
boss-thread-size = 1
#auto default pin or 8
worker-thread-size = 8
}
shutdown {
# when destroy server, wait seconds
wait = 3
}
serialization = "seata"
compressor = "none"
}
service {
#vgroup->rgroup
vgroup_mapping.storage-service-seata-service-group = "default"
#only support single node
default.grouplist = "127.0.0.1:8091"
#degrade current not support
enableDegrade = false
#disable
disable = false
#unit ms,s,m,h,d represents milliseconds, seconds, minutes, hours, days, default permanent
max.commit.retry.timeout = "-1"
max.rollback.retry.timeout = "-1"
}
client {
async.commit.buffer.limit = 10000
lock {
retry.internal = 10
retry.times = 30
}
report.retry.count = 5
tm.commit.retry.count = 1
tm.rollback.retry.count = 1
}
transaction {
undo.data.validation = true
undo.log.serialization = "jackson"
undo.log.save.days = 7
#schedule delete expired undo_log in milliseconds
undo.log.delete.period = 86400000
undo.log.table = "undo_log"
}
support {
## spring
spring {
# auto proxy the DataSource bean
datasource.autoproxy = false
}
}

@ -1,73 +0,0 @@
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "file"
nacos {
serverAddr = "localhost"
namespace = ""
cluster = "default"
}
eureka {
serviceUrl = "http://localhost:8761/eureka"
application = "default"
weight = "1"
}
redis {
serverAddr = "localhost:6379"
db = "0"
}
zk {
cluster = "default"
serverAddr = "127.0.0.1:2181"
session.timeout = 6000
connect.timeout = 2000
}
consul {
cluster = "default"
serverAddr = "127.0.0.1:8500"
}
etcd3 {
cluster = "default"
serverAddr = "http://localhost:2379"
}
sofa {
serverAddr = "127.0.0.1:9603"
application = "default"
region = "DEFAULT_ZONE"
datacenter = "DefaultDataCenter"
cluster = "default"
group = "SEATA_GROUP"
addressWaitTime = "3000"
}
file {
name = "file.conf"
}
}
config {
# file、nacos 、apollo、zk、consul、etcd3
type = "file"
nacos {
serverAddr = "localhost"
namespace = ""
}
consul {
serverAddr = "127.0.0.1:8500"
}
apollo {
app.id = "seata-server"
apollo.meta = "http://192.168.1.204:8801"
}
zk {
serverAddr = "127.0.0.1:2181"
session.timeout = 6000
connect.timeout = 2000
}
etcd3 {
serverAddr = "http://localhost:2379"
}
file {
name = "file.conf"
}
}

@ -22,6 +22,11 @@
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-datasource</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
@ -35,10 +40,10 @@
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--<dependency>-->
<!--<groupId>com.alibaba.csp</groupId>-->
<!--<artifactId>sentinel-datasource-nacos</artifactId>-->
<!--</dependency>-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<!--<dependency>-->
<!--<groupId>com.alibaba.csp</groupId>-->
<!--<artifactId>sentinel-datasource-zookeeper</artifactId>-->

@ -9,11 +9,19 @@ management.health.diskspace.enabled=false
spring.cloud.sentinel.transport.dashboard=localhost:8080
spring.cloud.sentinel.eager=true
spring.cloud.sentinel.web-context-unify=true
#spring.cloud.sentinel.block-page=/errorPage
#spring.cloud.sentinel.filter.enabled=false
#spring.cloud.sentinel.http-method-specify=false
#spring.cloud.sentinel.datasource.ds6.nacos.server-addr=127.0.0.1:8848
#spring.cloud.sentinel.datasource.ds6.nacos.username=nacos
#spring.cloud.sentinel.datasource.ds6.nacos.password=nacos
#spring.cloud.sentinel.datasource.ds6.nacos.dataId=flowrule.json
#spring.cloud.sentinel.datasource.ds6.nacos.data-type=json
#spring.cloud.sentinel.datasource.ds6.nacos.rule-type=flow
spring.cloud.sentinel.datasource.ds1.file.file=classpath: flowrule.json
spring.cloud.sentinel.datasource.ds1.file.data-type=json
spring.cloud.sentinel.datasource.ds1.file.rule-type=flow

@ -10,11 +10,13 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sentinel-dubbo-consumer-example</artifactId>
<name>Spring Cloud Starter Alibaba Sentinel x Dubbo - Consumer Example</name>
<description>Example demonstrating how to use sentinel with dubbo</description>
<packaging>jar</packaging>
<dependencies>
<dependency>
@ -30,7 +32,7 @@
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>sentinel-dubbo-api</artifactId>
<version>${revision}</version>
<version>${project.version}</version>
</dependency>
<dependency>

@ -10,11 +10,13 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sentinel-dubbo-provider-example</artifactId>
<name>Spring Cloud Starter Alibaba Sentinel x Dubbo - Provider Example</name>
<description>Example demonstrating how to use sentinel with dubbo</description>
<packaging>jar</packaging>
<dependencies>
<dependency>
@ -30,7 +32,7 @@
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>sentinel-dubbo-api</artifactId>
<version>${revision}</version>
<version>${project.version}</version>
</dependency>
<dependency>

@ -10,11 +10,13 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sentinel-feign-consumer-example</artifactId>
<name>Spring Cloud Starter Alibaba Sentinel x Feign - Consumer Example</name>
<description>Example demonstrating how to use sentinel with feign</description>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>

@ -20,7 +20,6 @@ import com.alibaba.cloud.examples.service.EchoService;
/**
* @author lengleng
* @date 2019-08-01
* <p>
* sentinel
*/
@ -35,7 +34,7 @@ public class EchoServiceFallback implements EchoService {
/**
* .
* @param str
* @return
* @return String
*/
@Override
public String echo(String str) {

@ -22,7 +22,6 @@ import org.springframework.stereotype.Component;
/**
* @author lengleng
* @date 2019-08-01
*/
@Component
public class EchoServiceFallbackFactory implements FallbackFactory<EchoServiceFallback> {

@ -24,7 +24,6 @@ import org.springframework.web.bind.annotation.PathVariable;
/**
* @author lengleng
* @date 2019-08-01
* <p>
* example feign client
*/

@ -22,7 +22,6 @@ import org.springframework.web.bind.annotation.RestController;
/**
* @author lengleng
* @date 2019-08-01
*/
@RestController
public class EchoController {

@ -10,11 +10,13 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sentinel-webflux-example</artifactId>
<name>Spring Cloud Starter Alibaba Sentinel x WebFlux Example</name>
<description>Example demonstrating how to use sentinel with webflux</description>
<packaging>jar</packaging>
<dependencies>
<dependency>

@ -41,10 +41,10 @@ public class ZuulConfiguration {
@Override
public BlockResponse fallbackResponse(String route, Throwable cause) {
if (route.equals("my-service3")) {
if ("my-service3".equals(route)) {
return new BlockResponse(433, "Sentinel Block3", route);
}
else if (route.equals("my-service4")) {
else if ("my-service4".equals(route)) {
return new BlockResponse(444, "my-service4", route);
}
else {

@ -13,14 +13,13 @@
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-dubbo-client-sample</artifactId>
<name>Spring Cloud Dubbo Client Sample</name>
<version>${revision}</version>
<dependencies>
<!-- Sample API -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-dubbo-sample-api</artifactId>
<version>${revision}</version>
<version>${project.version}</version>
</dependency>
<!-- Spring Boot dependencies -->

@ -17,7 +17,7 @@
package com.alibaba.cloud.dubbo.bootstrap;
import com.alibaba.cloud.dubbo.service.EchoService;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
@ -27,13 +27,15 @@ import org.springframework.web.bind.annotation.RestController;
/**
* Dubbo Spring Cloud Client Bootstrap.
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@EnableDiscoveryClient
@EnableAutoConfiguration
@RestController
public class DubboSpringCloudClientBootstrap {
@Reference
@DubboReference
private EchoService echoService;
@GetMapping("/echo")

@ -1,6 +1,9 @@
dubbo:
cloud:
subscribed-services: spring-cloud-alibaba-dubbo-server
protocols:
dubbo:
port: -1
spring:
application:

@ -23,7 +23,7 @@ import com.alibaba.cloud.dubbo.annotation.DubboTransported;
import com.alibaba.cloud.dubbo.service.RestService;
import com.alibaba.cloud.dubbo.service.User;
import com.alibaba.cloud.dubbo.service.UserService;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
@ -52,6 +52,8 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
/**
* Dubbo Spring Cloud Consumer Bootstrap.
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@EnableDiscoveryClient
@EnableAutoConfiguration
@ -60,10 +62,10 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
@EnableCaching
public class DubboSpringCloudConsumerBootstrap {
@Reference
@DubboReference
private UserService userService;
@Reference(version = "1.0.0", protocol = "dubbo")
@DubboReference(version = "1.0.0", protocol = "dubbo")
private RestService restService;
@Autowired

@ -1,14 +1,12 @@
dubbo:
registry:
# The Spring Cloud Dubbo's registry extension
## the default value of dubbo-provider-services is "*", that means to subscribe all providers,
## thus it's optimized if subscriber specifies the required providers.
address: spring-cloud://localhost
# The traditional Dubbo's registry also is supported
# address: zookeeper://127.0.0.1:2181
cloud:
# The subscribed services in consumer side
subscribed-services: ${provider.application.name}
protocols:
dubbo:
port: -1
consumer:
check: false
consumer:
check: false

@ -8,6 +8,8 @@ spring:
# default disable all
cloud:
nacos:
username: nacos
password: nacos
discovery:
enabled: false
register-enabled: false

@ -23,6 +23,8 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* Dubbo Spring Cloud Provider Bootstrap.
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@EnableDiscoveryClient
@EnableAutoConfiguration

@ -20,12 +20,12 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.apache.dubbo.config.annotation.Service;
import org.apache.dubbo.config.annotation.DubboService;
/**
* In-Memory {@link UserService} implementation.
*/
@Service(protocol = "dubbo")
@DubboService(protocol = "dubbo")
public class InMemoryUserService implements UserService {
private Map<Long, User> usersRepository = new HashMap<>();

@ -30,7 +30,7 @@ import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import org.apache.dubbo.config.annotation.Service;
import org.apache.dubbo.config.annotation.DubboService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -42,7 +42,7 @@ import static org.springframework.util.MimeTypeUtils.APPLICATION_JSON_VALUE;
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@Service(version = "1.0.0", protocol = { "dubbo", "rest" })
@DubboService(version = "1.0.0", protocol = { "dubbo", "rest" })
@Path("/")
public class StandardRestService implements RestService {

@ -9,11 +9,6 @@ dubbo:
name: rest
port: 9090
server: netty
registry:
# The Spring Cloud Dubbo's registry extension
address: spring-cloud://localhost
# The traditional Dubbo's registry
# address: zookeeper://127.0.0.1:2181
feign:
hystrix:
enabled: true

@ -33,6 +33,7 @@ spring:
enabled: true
register-enabled: true
server-addr: 127.0.0.1:8848
ephemeral: false
---

@ -22,6 +22,8 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* Dubbo Spring Cloud Provider Bootstrap.
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@EnableDiscoveryClient
@EnableAutoConfiguration

@ -20,12 +20,12 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.apache.dubbo.config.annotation.Service;
import org.apache.dubbo.config.annotation.DubboService;
/**
* In-Memory {@link UserService} implementation.
*/
@Service(protocol = "dubbo")
@DubboService(protocol = "dubbo")
public class InMemoryUserService implements UserService {
private Map<Long, User> usersRepository = new HashMap<>();

@ -19,7 +19,7 @@ package com.alibaba.cloud.dubbo.service;
import java.util.HashMap;
import java.util.Map;
import org.apache.dubbo.config.annotation.Service;
import org.apache.dubbo.config.annotation.DubboService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -39,7 +39,7 @@ import static com.alibaba.cloud.dubbo.util.LoggerUtils.log;
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@Service(version = "1.0.0")
@DubboService(version = "1.0.0")
@RestController
public class SpringRestService implements RestService {

@ -3,16 +3,7 @@ dubbo:
base-packages: com.alibaba.cloud.dubbo.service
protocols:
dubbo:
name: dubbo
port: -1
registries:
new:
address: spring-cloud://localhost
# registry:
# The Spring Cloud Dubbo's registry extension
# address: spring-cloud://localhost
# The traditional Dubbo's registry
# address: nacos://127.0.0.1:8848
feign:
hystrix:

@ -8,6 +8,8 @@ spring:
# default disable all
cloud:
nacos:
username: nacos
password: nacos
discovery:
enabled: false
register-enabled: false

@ -17,7 +17,7 @@
package com.alibaba.cloud.dubbo.bootstrap;
import com.alibaba.cloud.dubbo.service.EchoService;
import org.apache.dubbo.config.annotation.Service;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
@ -25,6 +25,8 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* Dubbo Spring Cloud Server Bootstrap.
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@EnableDiscoveryClient
@EnableAutoConfiguration
@ -36,7 +38,7 @@ public class DubboSpringCloudServerBootstrap {
}
@Service
@DubboService
class EchoServiceImpl implements EchoService {
@Override

@ -24,6 +24,8 @@ import org.springframework.cloud.openfeign.EnableFeignClients;
/**
* Dubbo Spring Cloud Servlet Gateway Bootstrap.
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@EnableDiscoveryClient
@EnableAutoConfiguration

@ -52,8 +52,8 @@ import org.springframework.util.StreamUtils;
import org.springframework.web.servlet.HttpServletBean;
import org.springframework.web.util.UriComponents;
import static org.apache.commons.lang3.StringUtils.substringAfter;
import static org.apache.commons.lang3.StringUtils.substringBetween;
import static org.apache.commons.lang.StringUtils.substringAfter;
import static org.apache.commons.lang.StringUtils.substringBetween;
import static org.springframework.web.util.UriComponentsBuilder.fromUriString;
@WebServlet(urlPatterns = "/dsc/*")

@ -20,9 +20,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
@ -33,10 +34,6 @@
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>

@ -6,11 +6,13 @@ spring:
username: nacos
password: nacos
discovery:
server-addr: localhost:8848
server-addr: 127.0.0.1:8848
group: test
gateway:
discovery:
locator:
enabled: true
application:
name: node-service
sidecar:
@ -18,8 +20,9 @@ sidecar:
ip: 127.0.0.1
# 异构微服务的端口
port: 8060
# 异构微服务的健康检查URL
health-check-url: http://localhost:8060/health.json
#health-check-url: http://localhost:8060/health.json
management:
endpoint:
health:

@ -13,8 +13,7 @@
<artifactId>spring-cloud-bus-rocketmq-example</artifactId>
<name>Spring Cloud Starter Bus Alibaba RocketMQ Example</name>
<description>Example demonstrating how to use Spring Cloud Bus RocketMQ</description>
<packaging>jar</packaging>
<packaging>jar</packaging>
<dependencies>

@ -101,6 +101,12 @@
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<optional>true</optional>
</dependency>
<!--spring boot-->
<dependency>

@ -34,6 +34,7 @@ import org.springframework.util.ObjectUtils;
* @see ZookeeperDataSourceProperties
* @see FileDataSourceProperties
* @see RedisDataSourceProperties
* @see ConsulDataSourceProperties
*/
public class DataSourcePropertiesConfiguration {

@ -59,6 +59,7 @@
<artifactId>spring-cloud-starter-gateway</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>

@ -37,7 +37,7 @@ public final class ConfigConstants {
/**
* ConfigurationProperties for {@link SentinelZuulProperties}.
*/
public static final String ZUUl_PREFIX = "spring.cloud.sentinel.zuul";
public static final String ZUUL_PREFIX = "spring.cloud.sentinel.zuul";
/**
* ConfigurationProperties for {@link SentinelGatewayProperties}.

@ -47,7 +47,7 @@ import org.springframework.context.annotation.Configuration;
*/
@Configuration
@ConditionalOnClass(ZuulServlet.class)
@ConditionalOnProperty(prefix = ConfigConstants.ZUUl_PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true)
@ConditionalOnProperty(prefix = ConfigConstants.ZUUL_PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true)
@EnableConfigurationProperties(SentinelZuulProperties.class)
public class SentinelZuulAutoConfiguration {

@ -28,7 +28,7 @@ import org.springframework.boot.context.properties.NestedConfigurationProperty;
/**
* @author <a href="mailto:fangjian0423@gmail.com">Jim</a>
*/
@ConfigurationProperties(prefix = ConfigConstants.ZUUl_PREFIX)
@ConfigurationProperties(prefix = ConfigConstants.ZUUL_PREFIX)
public class SentinelZuulProperties {
@NestedConfigurationProperty

@ -18,6 +18,8 @@ package com.alibaba.cloud.nacos;
import java.util.Objects;
import javax.annotation.PreDestroy;
import com.alibaba.cloud.nacos.diagnostics.analyzer.NacosConnectionFailureException;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
@ -73,6 +75,14 @@ public class NacosConfigManager {
return service;
}
@PreDestroy
public void destroy() throws NacosException {
if (service != null) {
service.shutDown();
service = null;
}
}
public NacosConfigProperties getNacosConfigProperties() {
return nacosConfigProperties;
}

@ -16,12 +16,16 @@
package com.alibaba.cloud.nacos.client;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import com.alibaba.cloud.nacos.NacosConfigProperties;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.util.CollectionUtils;
/**
* @author xiaojing
@ -58,6 +62,32 @@ public class NacosPropertySource extends MapPropertySource {
this.isRefreshable = isRefreshable;
}
NacosPropertySource(List<PropertySource<?>> propertySources, String group,
String dataId, Date timestamp, boolean isRefreshable) {
this(group, dataId, getSourceMap(group, dataId, propertySources), timestamp,
isRefreshable);
}
private static Map<String, Object> getSourceMap(String group, String dataId,
List<PropertySource<?>> propertySources) {
if (CollectionUtils.isEmpty(propertySources)) {
return Collections.emptyMap();
}
// If only one, return the internal element, otherwise wrap it.
if (propertySources.size() == 1) {
PropertySource propertySource = propertySources.get(0);
if (propertySource != null && propertySource.getSource() instanceof Map) {
return (Map<String, Object>) propertySource.getSource();
}
}
// If it is multiple, it will be returned as it is, and the internal elements
// cannot be directly retrieved, so the user needs to implement the retrieval
// logic by himself
return Collections.singletonMap(
String.join(NacosConfigProperties.COMMAS, dataId, group),
propertySources);
}
public String getGroup() {
return this.group;
}

@ -16,8 +16,9 @@
package com.alibaba.cloud.nacos.client;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import com.alibaba.cloud.nacos.NacosPropertySourceRepository;
@ -27,6 +28,7 @@ import com.alibaba.nacos.api.exception.NacosException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.PropertySource;
import org.springframework.util.StringUtils;
/**
@ -38,7 +40,7 @@ public class NacosPropertySourceBuilder {
private static final Logger log = LoggerFactory
.getLogger(NacosPropertySourceBuilder.class);
private static final Map<String, Object> EMPTY_MAP = new LinkedHashMap();
private static final Map<String, Object> EMPTY_MAP = Collections.emptyMap();
private ConfigService configService;
@ -71,14 +73,15 @@ public class NacosPropertySourceBuilder {
*/
NacosPropertySource build(String dataId, String group, String fileExtension,
boolean isRefreshable) {
Map<String, Object> p = loadNacosData(dataId, group, fileExtension);
NacosPropertySource nacosPropertySource = new NacosPropertySource(group, dataId,
p, new Date(), isRefreshable);
List<PropertySource<?>> propertySources = loadNacosData(dataId, group,
fileExtension);
NacosPropertySource nacosPropertySource = new NacosPropertySource(propertySources,
group, dataId, new Date(), isRefreshable);
NacosPropertySourceRepository.collectNacosPropertySource(nacosPropertySource);
return nacosPropertySource;
}
private Map<String, Object> loadNacosData(String dataId, String group,
private List<PropertySource<?>> loadNacosData(String dataId, String group,
String fileExtension) {
String data = null;
try {
@ -87,24 +90,23 @@ public class NacosPropertySourceBuilder {
log.warn(
"Ignore the empty nacos configuration and get it based on dataId[{}] & group[{}]",
dataId, group);
return EMPTY_MAP;
return Collections.emptyList();
}
if (log.isDebugEnabled()) {
log.debug(String.format(
"Loading nacos data, dataId: '%s', group: '%s', data: %s", dataId,
group, data));
}
Map<String, Object> dataMap = NacosDataParserHandler.getInstance()
.parseNacosData(data, fileExtension);
return dataMap == null ? EMPTY_MAP : dataMap;
return NacosDataParserHandler.getInstance().parseNacosData(dataId, data,
fileExtension);
}
catch (NacosException e) {
log.error("get data from Nacos error,dataId:{}, ", dataId, e);
log.error("get data from Nacos error,dataId:{} ", dataId, e);
}
catch (Exception e) {
log.error("parse data from Nacos error,dataId:{},data:{},", dataId, data, e);
log.error("parse data from Nacos error,dataId:{},data:{}", dataId, data, e);
}
return EMPTY_MAP;
return Collections.emptyList();
}
}

@ -21,7 +21,6 @@ import java.util.List;
import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.cloud.nacos.NacosConfigProperties;
import com.alibaba.cloud.nacos.NacosPropertySourceRepository;
import com.alibaba.cloud.nacos.parser.NacosDataParserHandler;
import com.alibaba.cloud.nacos.refresh.NacosContextRefresher;
import com.alibaba.nacos.api.config.ConfigService;
import org.slf4j.Logger;
@ -101,7 +100,6 @@ public class NacosPropertySourceLocator implements PropertySourceLocator {
loadSharedConfiguration(composite);
loadExtConfiguration(composite);
loadApplicationConfiguration(composite, dataIdPrefix, nacosConfigProperties, env);
return composite;
}
@ -165,7 +163,6 @@ public class NacosPropertySourceLocator implements PropertySourceLocator {
private void checkConfiguration(List<NacosConfigProperties.Config> configs,
String tips) {
String[] dataIds = new String[configs.size()];
for (int i = 0; i < configs.size(); i++) {
String dataId = configs.get(i).getDataId();
if (dataId == null || dataId.trim().length() == 0) {
@ -173,10 +170,7 @@ public class NacosPropertySourceLocator implements PropertySourceLocator {
"the [ spring.cloud.nacos.config.%s[%s] ] must give a dataId",
tips, i));
}
dataIds[i] = dataId;
}
// Just decide that the current dataId must have a suffix
NacosDataParserHandler.getInstance().checkDataId(dataIds);
}
private void loadNacosDataIfPresent(final CompositePropertySource composite,

@ -36,7 +36,7 @@ import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
*
* @author xiaojing
*/
@Endpoint(id = "nacos-config")
@Endpoint(id = "nacosconfig")
public class NacosConfigEndpoint {
private final NacosConfigProperties properties;

@ -0,0 +1,129 @@
/*
* Copyright 2013-2018 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
*
* https://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.
*/
package com.alibaba.cloud.nacos.parser;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.springframework.boot.env.PropertySourceLoader;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.Resource;
import org.springframework.util.StringUtils;
import static com.alibaba.cloud.nacos.parser.AbstractNacosDataParser.DOT;
/**
* Nacos-specific loader, If need to support other methods of parsing,you need to do the
* following steps:
* <p>
* 1.inherit {@link AbstractPropertySourceLoader} ;<br/>
* 2. define the file{@code spring.factories} and append
* {@code org.springframework.boot.env.PropertySourceLoader=..}; <br/>
* 3.the last step validate.
* </p>
* Notice the use of {@link NacosByteArrayResource} .
*
* @author zkz
*/
public abstract class AbstractPropertySourceLoader implements PropertySourceLoader {
/**
* Prevent interference with other loaders.Nacos-specific loader, unless the reload
* changes it.
* @param name the root name of the property source. If multiple documents are loaded
* an additional suffix should be added to the name for each source loaded.
* @param resource the resource to load
* @return if the resource can be loaded
*/
protected boolean canLoad(String name, Resource resource) {
return resource instanceof NacosByteArrayResource;
}
/**
* Load the resource into one or more property sources. Implementations may either
* return a list containing a single source, or in the case of a multi-document format
* such as yaml a source for each document in the resource.
* @param name the root name of the property source. If multiple documents are loaded
* an additional suffix should be added to the name for each source loaded.
* @param resource the resource to load
* @return a list property sources
* @throws IOException if the source cannot be loaded
*/
@Override
public List<PropertySource<?>> load(String name, Resource resource)
throws IOException {
if (!canLoad(name, resource)) {
return Collections.emptyList();
}
return this.doLoad(name, resource);
}
/**
* Load the resource into one or more property sources. Implementations may either
* return a list containing a single source, or in the case of a multi-document format
* such as yaml a source for each document in the resource.
* @param name the root name of the property source. If multiple documents are loaded
* an additional suffix should be added to the name for each source loaded.
* @param resource the resource to load
* @return a list property sources
* @throws IOException if the source cannot be loaded
*/
protected abstract List<PropertySource<?>> doLoad(String name, Resource resource)
throws IOException;
protected void flattenedMap(Map<String, Object> result, Map<String, Object> dataMap,
String parentKey) {
if (dataMap == null || dataMap.isEmpty()) {
return;
}
Set<Entry<String, Object>> entries = dataMap.entrySet();
for (Iterator<Entry<String, Object>> iterator = entries.iterator(); iterator
.hasNext();) {
Map.Entry<String, Object> entry = iterator.next();
String key = entry.getKey();
Object value = entry.getValue();
String fullKey = StringUtils.isEmpty(parentKey) ? key : key.startsWith("[")
? parentKey.concat(key) : parentKey.concat(DOT).concat(key);
if (value instanceof Map) {
Map<String, Object> map = (Map<String, Object>) value;
flattenedMap(result, map, fullKey);
continue;
}
else if (value instanceof Collection) {
int count = 0;
Collection<Object> collection = (Collection<Object>) value;
for (Object object : collection) {
flattenedMap(result,
Collections.singletonMap("[" + (count++) + "]", object),
fullKey);
}
continue;
}
result.put(fullKey, value);
}
}
}

@ -0,0 +1,60 @@
/*
* Copyright 2013-2018 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
*
* https://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.
*/
package com.alibaba.cloud.nacos.parser;
import org.springframework.core.io.ByteArrayResource;
/**
* Nacos-specific resource.
*
* @author zkz
*/
public class NacosByteArrayResource extends ByteArrayResource {
private String filename;
/**
* Create a new {@code ByteArrayResource}.
* @param byteArray the byte array to wrap
*/
public NacosByteArrayResource(byte[] byteArray) {
super(byteArray);
}
/**
* Create a new {@code ByteArrayResource} with a description.
* @param byteArray the byte array to wrap
* @param description where the byte array comes from
*/
public NacosByteArrayResource(byte[] byteArray, String description) {
super(byteArray, description);
}
public void setFilename(String filename) {
this.filename = filename;
}
/**
* This implementation always returns {@code null}, assuming that this resource type
* does not have a filename.
*/
@Override
public String getFilename() {
return null == this.filename ? this.getDescription() : this.filename;
}
}

@ -1,66 +0,0 @@
/*
* Copyright 2013-2018 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
*
* https://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.
*/
package com.alibaba.cloud.nacos.parser;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
/**
* @author zkz
* @author yuhuangbin
*/
public class NacosDataJsonParser extends AbstractNacosDataParser {
protected NacosDataJsonParser() {
super("json");
}
@Override
protected Map<String, Object> doParse(String data) throws IOException {
if (StringUtils.isEmpty(data)) {
return null;
}
Map<String, Object> map = parseJSON2Map(data);
return this.reloadMap(map);
}
/**
* JSON to Map.
* @param json json data
* @return the map convert by json string
* @throws IOException thrown if there is a problem parsing config.
*/
private Map<String, Object> parseJSON2Map(String json) throws IOException {
Map<String, Object> result = new LinkedHashMap<>(32);
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> nacosDataMap = mapper.readValue(json, LinkedHashMap.class);
if (CollectionUtils.isEmpty(nacosDataMap)) {
return result;
}
flattenedMap(result, nacosDataMap, EMPTY_STRING);
return result;
}
}

@ -17,63 +17,139 @@
package com.alibaba.cloud.nacos.parser;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import org.springframework.boot.env.OriginTrackedMapPropertySource;
import org.springframework.boot.env.PropertySourceLoader;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
/**
* @author zkz
*/
public final class NacosDataParserHandler {
private AbstractNacosDataParser parser;
/**
* symbol: dot.
*/
public static final String DOT = ".";
/**
* constant.
*/
public static final String VALUE = "value";
/**
* default extension.
*/
public static final String DEFAULT_EXTENSION = "properties";
private static List<PropertySourceLoader> propertySourceLoaders;
private NacosDataParserHandler() {
parser = this.createParser();
propertySourceLoaders = SpringFactoriesLoader
.loadFactories(PropertySourceLoader.class, getClass().getClassLoader());
}
/**
* Parsing nacos configuration content.
* @param data config from Nacos
* @param extension file extension. json or xml or yml or yaml or properties
* @return result of LinkedHashMap
* @param configName name of nacos-config
* @param configValue value from nacos-config
* @param extension identifies the type of configValue
* @return result of Map
* @throws IOException thrown if there is a problem parsing config.
*/
public Map<String, Object> parseNacosData(String data, String extension)
throws IOException {
if (null == parser) {
parser = this.createParser();
public List<PropertySource<?>> parseNacosData(String configName, String configValue,
String extension) throws IOException {
if (StringUtils.isEmpty(configValue)) {
return Collections.emptyList();
}
if (StringUtils.isEmpty(extension)) {
extension = this.getFileExtension(configName);
}
return parser.parseNacosData(data, extension);
for (PropertySourceLoader propertySourceLoader : propertySourceLoaders) {
if (!canLoadFileExtension(propertySourceLoader, extension)) {
continue;
}
NacosByteArrayResource nacosByteArrayResource = new NacosByteArrayResource(
configValue.getBytes(), configName);
nacosByteArrayResource.setFilename(getFileName(configName, extension));
List<PropertySource<?>> propertySourceList = propertySourceLoader
.load(configName, nacosByteArrayResource);
if (CollectionUtils.isEmpty(propertySourceList)) {
return Collections.emptyList();
}
return propertySourceList.stream().filter(Objects::nonNull)
.map(propertySource -> {
if (propertySource instanceof EnumerablePropertySource) {
String[] propertyNames = ((EnumerablePropertySource) propertySource)
.getPropertyNames();
if (propertyNames != null && propertyNames.length > 0) {
Map<String, Object> map = new LinkedHashMap<>();
Arrays.stream(propertyNames).forEach(name -> {
map.put(name, propertySource.getProperty(name));
});
return new OriginTrackedMapPropertySource(
propertySource.getName(), map);
}
}
return propertySource;
}).collect(Collectors.toList());
}
return Collections.emptyList();
}
/**
* check the validity of file extensions in dataid.
* @param dataIdAry array of dataId
* @return dataId handle success or not
* check the current extension can be processed.
* @param loader the propertySourceLoader
* @param extension file extension
* @return if can match extension
*/
public boolean checkDataId(String... dataIdAry) {
StringBuilder stringBuilder = new StringBuilder();
for (String dataId : dataIdAry) {
int idx = dataId.lastIndexOf(AbstractNacosDataParser.DOT);
if (idx > 0 && idx < dataId.length() - 1) {
String extension = dataId.substring(idx + 1);
if (parser.checkFileExtension(extension)) {
break;
}
}
// add tips
stringBuilder.append(dataId).append(",");
private boolean canLoadFileExtension(PropertySourceLoader loader, String extension) {
return Arrays.stream(loader.getFileExtensions())
.anyMatch((fileExtension) -> StringUtils.endsWithIgnoreCase(extension,
fileExtension));
}
/**
* @param name filename
* @return file extension, default {@code DEFAULT_EXTENSION} if don't get
*/
public String getFileExtension(String name) {
if (StringUtils.isEmpty(name)) {
return DEFAULT_EXTENSION;
}
if (stringBuilder.length() > 0) {
String result = stringBuilder.substring(0, stringBuilder.length() - 1);
throw new IllegalStateException(AbstractNacosDataParser.getTips(result));
int idx = name.lastIndexOf(DOT);
if (idx > 0 && idx < name.length() - 1) {
return name.substring(idx + 1);
}
return true;
return DEFAULT_EXTENSION;
}
private AbstractNacosDataParser createParser() {
return new NacosDataPropertiesParser().addNextParser(new NacosDataYamlParser())
.addNextParser(new NacosDataXmlParser())
.addNextParser(new NacosDataJsonParser());
private String getFileName(String name, String extension) {
if (StringUtils.isEmpty(extension)) {
return name;
}
if (StringUtils.isEmpty(name)) {
return extension;
}
int idx = name.lastIndexOf(DOT);
if (idx > 0 && idx < name.length() - 1) {
String ext = name.substring(idx + 1);
if (extension.equalsIgnoreCase(ext)) {
return name;
}
}
return name + DOT + extension;
}
public static NacosDataParserHandler getInstance() {

@ -1,44 +0,0 @@
/*
* Copyright 2013-2018 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
*
* https://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.
*/
package com.alibaba.cloud.nacos.parser;
import java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.beans.factory.config.YamlMapFactoryBean;
import org.springframework.core.io.ByteArrayResource;
/**
* @author zkz
*/
public class NacosDataYamlParser extends AbstractNacosDataParser {
public NacosDataYamlParser() {
super(",yml,yaml,");
}
@Override
protected Map<String, Object> doParse(String data) {
YamlMapFactoryBean yamlFactory = new YamlMapFactoryBean();
yamlFactory.setResources(new ByteArrayResource(data.getBytes()));
Map<String, Object> result = new LinkedHashMap<>();
flattenedMap(result, yamlFactory.getObject(), EMPTY_STRING);
return result;
}
}

@ -0,0 +1,92 @@
/*
* Copyright 2013-2018 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
*
* https://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.
*/
package com.alibaba.cloud.nacos.parser;
import java.io.IOException;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.boot.env.OriginTrackedMapPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.Resource;
import static com.alibaba.cloud.nacos.parser.AbstractNacosDataParser.DOT;
import static com.alibaba.cloud.nacos.parser.AbstractNacosDataParser.VALUE;
/**
* @author zkz
*/
public class NacosJsonPropertySourceLoader extends AbstractPropertySourceLoader {
/**
* Returns the file extensions that the loader supports (excluding the '.').
* @return the file extensions
*/
@Override
public String[] getFileExtensions() {
return new String[] { "json" };
}
/**
* Load the resource into one or more property sources. Implementations may either
* return a list containing a single source, or in the case of a multi-document format
* such as yaml a source for each document in the resource.
* @param name the root name of the property source. If multiple documents are loaded
* an additional suffix should be added to the name for each source loaded.
* @param resource the resource to load
* @return a list property sources
* @throws IOException if the source cannot be loaded
*/
@Override
protected List<PropertySource<?>> doLoad(String name, Resource resource)
throws IOException {
Map<String, Object> result = new LinkedHashMap<>(32);
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> nacosDataMap = mapper.readValue(resource.getInputStream(),
LinkedHashMap.class);
flattenedMap(result, nacosDataMap, null);
return Collections.singletonList(
new OriginTrackedMapPropertySource(name, this.reloadMap(result)));
}
/**
* Reload the key ending in `value` if need.
*/
protected Map<String, Object> reloadMap(Map<String, Object> map) {
if (map == null || map.isEmpty()) {
return null;
}
Map<String, Object> result = new LinkedHashMap<>(map);
for (Map.Entry<String, Object> entry : map.entrySet()) {
String key = entry.getKey();
if (key.contains(DOT)) {
int idx = key.lastIndexOf(DOT);
String suffix = key.substring(idx + 1);
if (VALUE.equalsIgnoreCase(suffix)) {
result.put(key.substring(0, idx), entry.getValue());
}
}
}
return result;
}
}

@ -17,8 +17,9 @@
package com.alibaba.cloud.nacos.parser;
import java.io.IOException;
import java.io.StringReader;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
@ -28,39 +29,78 @@ import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.springframework.boot.env.OriginTrackedMapPropertySource;
import org.springframework.boot.env.PropertiesPropertySourceLoader;
import org.springframework.core.Ordered;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.Resource;
import org.springframework.util.StringUtils;
import static com.alibaba.cloud.nacos.parser.AbstractNacosDataParser.DOT;
/**
* With relatively few usage scenarios, only simple parsing is performed to reduce jar
* dependencies.
* Parsing for XML requires overwriting the default
* {@link PropertiesPropertySourceLoader}, because it internally rigorously validates
* ({@conde DOCTYPE}) THE XML in a way that makes it difficult to customize the
* configuration; at finally, make sure it's in the first place.
*
* @author zkz
*/
public class NacosDataXmlParser extends AbstractNacosDataParser {
public class NacosXmlPropertySourceLoader extends AbstractPropertySourceLoader
implements Ordered {
public NacosDataXmlParser() {
super("xml");
/**
* Get the order value of this object.
* <p>
* Higher values are interpreted as lower priority. As a consequence, the object with
* the lowest value has the highest priority (somewhat analogous to Servlet
* {@code load-on-startup} values).
* <p>
* Same order values will result in arbitrary sort positions for the affected objects.
* @return the order value
* @see #HIGHEST_PRECEDENCE
* @see #LOWEST_PRECEDENCE
*/
@Override
public int getOrder() {
return Integer.MIN_VALUE;
}
/**
* Returns the file extensions that the loader supports (excluding the '.').
* @return the file extensions
*/
@Override
protected Map<String, Object> doParse(String data) throws IOException {
if (StringUtils.isEmpty(data)) {
return null;
}
Map<String, Object> map = parseXml2Map(data);
return this.reloadMap(map);
public String[] getFileExtensions() {
return new String[] { "xml" };
}
/**
* Load the resource into one or more property sources. Implementations may either
* return a list containing a single source, or in the case of a multi-document format
* such as yaml a source for each document in the resource.
* @param name the root name of the property source. If multiple documents are loaded
* an additional suffix should be added to the name for each source loaded.
* @param resource the resource to load
* @return a list property sources
* @throws IOException if the source cannot be loaded
*/
@Override
protected List<PropertySource<?>> doLoad(String name, Resource resource)
throws IOException {
Map<String, Object> nacosDataMap = parseXml2Map(resource);
return Collections
.singletonList(new OriginTrackedMapPropertySource(name, nacosDataMap));
}
private Map<String, Object> parseXml2Map(String xml) throws IOException {
xml = xml.replaceAll("\\r", "").replaceAll("\\n", "").replaceAll("\\t", "");
private Map<String, Object> parseXml2Map(Resource resource) throws IOException {
Map<String, Object> map = new LinkedHashMap<>(32);
try {
DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance()
.newDocumentBuilder();
Document document = documentBuilder
.parse(new InputSource(new StringReader(xml)));
Document document = documentBuilder.parse(resource.getInputStream());
if (null == document) {
return null;
}

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

Loading…
Cancel
Save