diff --git a/README-zh.md b/README-zh.md index 27d5895e..747faab4 100644 --- a/README-zh.md +++ b/README-zh.md @@ -4,6 +4,7 @@ Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。 依托 Spring Cloud Alibaba,您只需要添加一些注解和少量配置,就可以将 Spring Cloud 应用接入阿里微服务解决方案,通过阿里中间件来迅速搭建分布式应用系统。 +参考文档 请查看 [WIKI](https://github.com/spring-cloud-incubator/spring-cloud-alibaba/wiki) ## 主要功能 @@ -39,7 +40,7 @@ Spring Cloud 使用 Maven 来构建,最快的使用方式是将本项目clone ## 如何使用 ### 如何引入依赖 -项目已经发布了第一个版本,版本 0.2.0.RELEASE 对应的是 Spring Boot 2.x 版本,版本 0.1.0.RELEASE 对应的是 Spring Boot 1.x 版本。 +项目已经发布了第一个版本,版本 0.2.0.RELEASE 对应的是 Spring Cloud Finchley 版本,版本 0.1.0.RELEASE 对应的是 Spring Cloud Edgware 版本。 如果需要使用已发布的版本,在 `dependencyManagement` 中添加如下配置。 @@ -70,18 +71,6 @@ Spring Cloud 使用 Maven 来构建,最快的使用方式是将本项目clone - -### Reference Doc - -[目录](https://github.com/spring-cloud-incubator/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-docs/src/main/asciidoc-zh/spring-cloud-alibaba.adoc) - -[Nacos Config](https://github.com/spring-cloud-incubator/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-config.adoc) - -[Nacos Discovery](https://github.com/spring-cloud-incubator/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-discovery.adoc) - -[ACM](https://github.com/spring-cloud-incubator/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-docs/src/main/asciidoc-zh/acm.adoc) - - ## 演示 Demo 为了演示如何使用,Spring Cloud Alibaba 项目包含了一个子模块`spring-cloud-alibaba-examples`。此模块中提供了演示用的 example ,您可以阅读对应的 example 工程下的 readme 文档,根据里面的步骤来体验。 @@ -120,4 +109,4 @@ spring-cloud-alibaba@googlegroups.com,欢迎通过此邮件列表讨论与 spr ### 钉钉群 -![DingQR](https://cdn.nlark.com/lark/0/2018/png/64647/1535108150178-409a1689-437f-495b-8dcb-b667ccb32f85.png) \ No newline at end of file +![DingQR](https://cdn.nlark.com/lark/0/2018/png/64647/1535108150178-409a1689-437f-495b-8dcb-b667ccb32f85.png) diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/acm.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/acm.adoc index 16ff206c..4824e321 100644 --- a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/acm.adoc +++ b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/acm.adoc @@ -12,7 +12,7 @@ Spring Cloud AliCloud ACM 提供了和阿里云上的ACM的集成。使得在项 1、轻量版配置中心的下载和启动方式可参考 https://help.aliyun.com/document_detail/44163.html?spm=a2c4g.11186623.6.677.5f206b82Z2mTCF[这里] -2、启动好轻量版配置中心之后,在控制台中添加如下的配置。注意data id是以 properties为扩展名(默认的文件扩展名方式)。 +2、启动好轻量版配置中心之后,在控制台中添加如下的配置。 [source,subs="normal"] ---- @@ -24,6 +24,8 @@ Content: user.name=alibaba user.age=56 ---- +NOTE: data id是以 `properties` 为扩展名(默认的文件扩展名方式)。Group 的值目前只支持 DEFAULT_GROUP,注意在使用的过程中无需更改其默认值。 + ===== 客户端使用方式 为了能够在应用程序中使用ACM作为Sping Cloud Config的后端存储服务,在您构建Spring Boot 应用的同时添加一个Spring Boot Starter org.springframework.cloud:spring-cloud-starter-alicloud-acm。以下是一个基础的maven 依赖配置: @@ -122,6 +124,8 @@ Content: user.name: yaml-alibaba user.age: 102 ---- +NOTE: 这里的DataId的命名规则。${spring.application.name}.${spring.cloud.nacos.config.file-extension}。因为配置中配置的是 acm-config和yaml,因此根据规则这里的DataId的命名是:acm-config.yaml。 + 完成之后,重启测试程序,可以在控制台看到输出的结果的值。 [source,subs="normal"] @@ -153,6 +157,8 @@ spring-cloud-starter-alicloud 在加载配置的时候,不仅仅加载了以da [sources,properties] ---- spring.profiles.active=${deploy.env} +spring.application.name=acm-config +spring.cloud.nacos.config.file-extension=yaml #显示的声明使用的文件扩展名 ---- 其中 ${deploy.env}变量的值可以在启动应用时通过-Ddeploy.env=*****来动态指定。比如现在在轻量版配置中心上新增了一个dataid为:acm-config-develop.yaml的基础配置,如下所示: @@ -168,6 +174,8 @@ Content: deploy.env: develop 同时启动应用的时候通过-Ddeploy.env=develop 来指定当前spring.profiles.active的值。 +NOTE: 特别关注下这里的DataId 的命名。因为DataId的命名规则为 ${spring.application.name}-${profile}.${file-extension:properties}。而案例中配置的值依次为 acm-config、develop、yaml,因此这里的DataId为 acm-config-develop.yaml。Group的配置目前只支持 DEFAULT_GROUP,注意在使用的过程中不要更改其他的值。 + 启动 Spring Boot 应用测试的代码如下: [source,java] @@ -231,10 +239,6 @@ Deploy Env:Product spring.application.group=com.infrastructure.alibaba ---- -这个时候注意在轻量版配置中心填写的dataid的格式为: - - ${spring.application.group}:application.${file-extension} - 如下所示: [source,subs="normal"] @@ -246,6 +250,10 @@ DataId: com.infrastructure.alibaba:application.yaml Content: owner.group: infrastructure ---- +NOTE: 这个时候注意在轻量版配置中心填写的dataid的格式为:`${spring.application.group}:application.${file-extension}` 或者 + `${spring.application.group}:${spring.application.name}.${file-extension}` 。如果有 `spring.profiles.active` 的配置,dataid的格式还支持 + `${spring.application.group}:${spring.application.name}-${spring.profiles.active}.${file-extension}`。 Group 的值目前只支持 `DEFAULT_GROUP`,因此在使用过程中请额外注意该值配置的正确性,不要和 `spring.application.group` 这个配置搞混了。 + 启动 Spring Boot 应用测试的代码如下: [source,java] diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-config.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-config.adoc index 684f3f82..66a76abd 100644 --- a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-config.adoc +++ b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-config.adoc @@ -1,5 +1,9 @@ = Spring Cloud Alibaba Nacos Config +Nacos 提供用于存储配置和其他元数据的 key/value 存储,为分布式系统中的外部化配置提供服务器端和客户端支持。使用 Spring Cloud Alibaba Nacos Config,您可以在 Nacos Server 集中管理你 Spring Cloud 应用的外部属性配置。 + +Spring Cloud Alibaba Nacos Config 是 Config Server 和 Client 的替代方案,客户端和服务器上的概念与 Spring Environment 和 PropertySource 有着一致的抽象,在特殊的 bootstrap 阶段,配置被加载到 Spring 环境中。当应用程序通过部署管道从开发到测试再到生产时,您可以管理这些环境之间的配置,并确保应用程序具有迁移时需要运行的所有内容。 + == 快速开始 === 基于 dataid 为 properties 的文件扩展名配置方式 @@ -8,7 +12,7 @@ 1、启动Nacos Server。启动方式可见 https://nacos.io/zh-cn/docs/quick-start.html[Nacos 官网] -2、启动好Nacos之后,在Nacos添加如下的配置。注意dataid是以 properties为扩展名,默认的文件扩展名方式。如下所示: +2、启动好Nacos之后,在Nacos添加如下的配置: [source,subs="normal"] ---- @@ -16,15 +20,17 @@ Data ID: nacos-config.properties Group : DEFAULT_GROUP -配置格式: TEXT +配置格式: Properties -配置内容: user.name: nacos-config-properties - user.age: 90 +配置内容: user.name=nacos-config-properties + user.age=90 ---- +NOTE: 注意dataid是以 properties(默认的文件扩展名方式)为扩展名。 + ==== 客户端使用方式 -为了能够在应用程序中使用Nacos作为Sping Cloud Config的后端存储服务,在您构建Spring Boot 应用的同时添加一个Spring Boot Starter org.springframework.cloud:spring-cloud-starter-alibaba-nacos-config。以下是一个基础的maven 依赖配置: +为了能够在应用程序中使用 Nacos 来实现应用的外部化配置,在构建应用的同时添加一个Spring Boot Starter org.springframework.cloud:spring-cloud-starter-alibaba-nacos-config。以下是一个基本的 maven 依赖配置: [source,xml] ---- @@ -75,7 +81,7 @@ Group : DEFAULT_GROUP ---- -现在就可以创建一个标准的Spring Boot的应用。 +现在就可以创建一个标准的 Spring Boot 应用。 [source,java] ---- @@ -91,12 +97,12 @@ public class ProviderApplication { } ---- -spring-cloud-starter-alibaba-nacos-config 对于 Nacos 服务端的基础配置没有默认值,因此在运行此Example 之前, 必须使用 bootstrap.properties 配置文件来配置Nacos Server地址,例如: +在运行此 Example 之前, 必须使用 bootstrap.properties 配置文件来配置Nacos Server 地址,例如: .bootstrap.properties [source,properties] ---- -spring.application.name=nacos-config #注意,spring.application.name 必须要放在bootstrap.properties中 +spring.application.name=nacos-config spring.cloud.nacos.config.server-addr=127.0.0.1:8848 ---- @@ -104,7 +110,7 @@ NOTE: 注意当你使用域名的方式来访问 Nacos 时,`spring.cloud.nacos 例如 Nacos 的域名为abc.com.nacos,监听的端口为 80,则 `spring.cloud.nacos.config.server-addr=abc.com.nacos:80`。 注意 80 端口不能省略。 -启动这个Example,可以在控制台看到打印出的值正是在Nacos上预先配置好的值。 +启动这个 Example,可以看到如下输出结果: [source,subs="normal"] ---- @@ -116,8 +122,7 @@ user name :nacos-config-properties; age: 90 === 基于 dataid 为 yaml 的文件扩展名配置方式 -spring-cloud-starter-alibaba-nacos-config 默认对 dateid 的文件扩展名是 properties。如果习惯使用yaml格式来作为应用中的基础配置,也是可以支持的。 -这个时候只需要完成以下两步: +spring-cloud-starter-alibaba-nacos-config 对于 yaml 格式也是完美支持的。这个时候只需要完成以下两步: 1、在应用的 bootstrap.properties 配置文件中显示的声明 dataid 文件扩展名。如下所示 @@ -141,7 +146,7 @@ Group : DEFAULT_GROUP user.age: 68 ---- -这两步完成后,重启测试程序,可以在控制台看到输出是以dataid为opensource-service-provider3.yaml配置的值。 +这两步完成后,重启测试程序,可以看到如下输出结果。 [source,subs="normal"] ---- @@ -152,7 +157,27 @@ user name :nacos-config-yaml; age: 68 === 支持配置的动态更新 -spring-cloud-starter-alibaba-nacos-config 也支持配置的动态更新,如下所示,当变更user.name时,应用程序中能够获取到最新的值: +spring-cloud-starter-alibaba-nacos-config 也支持配置的动态更新,启动 Spring Boot 应用测试的代码如下: + +[source,java] +---- +@SpringBootApplication +public class ProviderApplication { + + public static void main(String[] args) { + ConfigurableApplicationContext applicationContext = SpringApplication.run(ProviderApplication.class, args); + while(true) { + //当动态配置刷新时,会更新到 Enviroment中,因此这里每隔一秒中从Enviroment中获取配置 + String userName = applicationContext.getEnvironment().getProperty("user.name"); + String userAge = applicationContext.getEnvironment().getProperty("user.age"); + System.err.println("user name :" + userName + "; age: " + userAge); + TimeUnit.SECONDS.sleep(1); + } + } +} +---- + +如下所示,当变更user.name时,应用程序中能够获取到最新的值: [source,subs="normal"] ---- @@ -162,20 +187,25 @@ user name :nacos-config-yaml; age: 68 2018-11-02 15:04:25.069 INFO 32957 --- [-127.0.0.1:8848] o.s.boot.SpringApplication : Started application in 0.144 seconds (JVM running for 71.752) 2018-11-02 15:04:25.070 INFO 32957 --- [-127.0.0.1:8848] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@10c89124: startup date [Fri Nov 02 15:04:25 CST 2018]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@6520af7 2018-11-02 15:04:25.071 INFO 32957 --- [-127.0.0.1:8848] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@6520af7: startup date [Fri Nov 02 15:04:24 CST 2018]; root of context hierarchy +//从 Enviroment 中 读取到更改后的值 user name :nacos-config-yaml-update; age: 68 user name :nacos-config-yaml-update; age: 68 ---- +NOTE: 你可以通过配置 `spring.cloud.nacos.config.refresh.enabled=false` 来关闭动态刷新 + === 可支持profile粒度的配置 -spring-cloud-starter-alibaba-nacos-config 在加载配置的时候,不仅仅加载了以dataid为${spring.application.name}.${file-extension:properties}为前缀的基础配置,还加载了dataid为${spring.application.name}-${profile}.${file-extension:properties}的基础配置。在日常开发中如果遇到多套环境下的不同配置,可以打开Spring自带的配置功能。 +spring-cloud-starter-alibaba-nacos-config 在加载配置的时候,不仅仅加载了以 dataid 为 `${spring.application.name}.${file-extension:properties}` 为前缀的基础配置,还加载了dataid为 `${spring.application.name}-${profile}.${file-extension:properties}` 的基础配置。在日常开发中如果遇到多套环境下的不同配置,可以通过Spring 提供的 `${spring.profiles.active}` 这个配置项来配置。 [source,properties] ---- -spring.profiles.active=${deploy.env} +spring.profiles.active=develop ---- -其中 ${deploy.env}变量的值可以在启动应用时通过-Ddeploy.env=*****来动态指定。比如现在在Nacos上新增了一个dataid为:nacos-config-develop.yaml的基础配置,如下所示: +NOTE: ${spring.profiles.active} 当通过配置文件来指定时必须放在 bootstrap.properties 文件中。 + +Nacos 上新增一个dataid为:nacos-config-develop.yaml的基础配置,如下所示: [source,subs="normal"] ---- @@ -188,7 +218,6 @@ Group : DEFAULT_GROUP 配置内容: current.env: develop-env ---- -同时启动应用的时候通过-Ddeploy.env=develop 来指定当前spring.profiles.active的值。 启动 Spring Boot 应用测试的代码如下: [source,java] @@ -217,7 +246,14 @@ in develop-evn enviroment; user name :nacos-config-yaml-update; age: 68 2018-11-02 15:34:25.013 INFO 33014 --- [ Thread-11] ConfigServletWebServerApplicationContext : Closing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@6f1c29b7: startup date [Fri Nov 02 15:33:57 CST 2018]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@63355449 ---- -如果需要切换到生产环境,那么只需要更改启动的-Ddeploy.env=product 参数即可。前提是生产环境上Nacos已经添加了该环境的基础配置。例如,现在在生成环境下的Naocs添加了dataid为:nacos-config-product.yaml的配置: +如果需要切换到生产环境,只需要更改 `${spring.profiles.active}` 参数配置即可。如下所示: + +[source,properties] +---- +spring.profiles.active=product +---- + +同时生产环境上 Nacos 需要添加对应 dataid 的基础配置。例如,在生成环境下的 Naocs 添加了dataid为:nacos-config-product.yaml的配置: [source,subs="normal"] ---- @@ -230,7 +266,7 @@ Group : DEFAULT_GROUP 配置内容: current.env: product-env ---- -以-Ddeploy.env=product 启动测试程序,输出结果如下: +启动测试程序,输出结果如下: [source,subs="normal"] ---- @@ -238,4 +274,26 @@ in product-env enviroment; user name :nacos-config-yaml-update; age: 68 2018-11-02 15:42:14.628 INFO 33024 --- [Thread-11] ConfigServletWebServerApplicationContext : Closing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@6aa8e115: startup date [Fri Nov 02 15:42:03 CST 2018]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@19bb07ed ---- +NOTE: 此案例中我们通过 spring.profiles.active=XXXX 的方式写死在配置文件中,而在真正的项目实施过程中这个变量的值是需要不同环境而有不同的值。这个时候通常的做法是通过 -Dspring.profiles.active=XXXX 参数指定其配置来达到环境间灵活的切换。 +=== 支持自定义 namespace 的配置 + +在没有明确指定 `${spring.cloud.nacos.config.namespace}` 配置的情况下, 默认使用的是 Nacos 上 Public 这个namespae。在我们日常业务的开发过程中,经常需要自定义自己的 namespace,那这个时候可以通过以下配置来实现: + +[source,properties] +---- +spring.cloud.nacos.config.namespace=b3404bc0-d7dc-4855-b519-570ed34b62d7 +---- + +NOTE: 该配置必须放在 bootstrap.properties 文件中。此外 `spring.cloud.nacos.config.namespace` 的值是 namespace 对应的 id,id 值可以在 Nacos 的控制台获取。并且在添加配置时注意不要选择其他的 namespae,否则将会导致读取不到正确的配置。 + +=== 支持自定义 Group 的配置 + +在没有明确指定 `${spring.cloud.nacos.config.group}` 配置的情况下, 默认使用的是 DEFAULT_GROUP 。在我们日常业务的开发过程中,经常需要自定义自己的 Group,那这个时候可以通过以下配置来实现: + +[source,properties] +---- +spring.cloud.nacos.config.group=DEVELOP_GROUP +---- + +NOTE: 该配置必须放在 bootstrap.properties 文件中。并且在添加配置时 Group 的值一定要和 `spring.cloud.nacos.config.group` 的配置值一致。 diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/sentinel.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/sentinel.adoc index 260c3df3..e4c9817f 100644 --- a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/sentinel.adoc +++ b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/sentinel.adoc @@ -167,7 +167,7 @@ private ReadableDataSource dataSource; 如果 `ApplicationContext` 中存在超过1个 `ReadableDataSource` bean,那么不会加载这些 `ReadableDataSource` 中的任意一个。 只有在 `ApplicationContext` 存在一个 `ReadableDataSource` 的情况下才会生效。 -如果数据库生效并且规则成功加载,控制台会打印类似如下信息: +如果数据源生效并且规则成功加载,控制台会打印类似如下信息: ``` [Sentinel Starter] load 3 flow rules @@ -216,6 +216,13 @@ NOTE: d1, ds2, ds3, ds4 是 `ReadableDataSource` 的名字,可随意编写。 用户使用这种配置的时候只需要填写正确的json或xml就行,有任何不合理的信息都会在日志里打印出来。 +如果数据源生效并且规则成功加载,控制台会打印类似如下信息: + +``` +[Sentinel Starter] DataSource ds1-sentinel-file-datasource load 3 DegradeRule +[Sentinel Starter] DataSource ds2-sentinel-nacos-datasource load 2 FlowRule +``` + NOTE: 默认情况下,xml格式是不支持的。需要添加 `jackson-dataformat-xml` 依赖后才会自动生效。 关于Sentinel动态数据源的实现原理,参考: https://github.com/alibaba/Sentinel/wiki/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%99%E6%89%A9%E5%B1%95[动态规则扩展] diff --git a/spring-cloud-alibaba-examples/rocketmq-example/readme-zh.md b/spring-cloud-alibaba-examples/rocketmq-example/readme-zh.md new file mode 100644 index 00000000..f8f4e4ee --- /dev/null +++ b/spring-cloud-alibaba-examples/rocketmq-example/readme-zh.md @@ -0,0 +1,259 @@ +# RocketMQ Example + +## 项目说明 + +本项目演示如何使用 RocketMQ Binder 完成 Spring Cloud 应用消息的订阅和发布。 + +[RocketMQ](https://rocketmq.apache.org/) 是一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。 + +在说明RocketMQ的示例之前,我们先了解一下 Spring Cloud Stream 中的Binder和Binding概念。 + +Binder: 跟外部消息中间件集成的组件,用来创建Binding,各消息中间件都有自己的Binder实现。 + +比如 `Kafka` 的实现 `KafkaMessageChannelBinder` ,`RabbitMQ` 的实现 `RabbitMessageChannelBinder` 以及 `RocketMQ` 的实现 `RocketMQMessageChannelBinder` 。 + +Binding: 包括Input Binding和Output Binding。 + +Binding在消息中间件与应用程序提供的Provider和Consumer之间提供了一个桥梁,实现了开发者只需使用应用程序的Provider或Consumer生产或消费数据即可,屏蔽了开发者与底层消息中间件的接触。 + +下图是Spring Cloud Stream的架构设计。 + +![](https://docs.spring.io/spring-cloud-stream/docs/current/reference/htmlsingle/images/SCSt-overview.png) + +## 示例 + +### 如何接入 + +在启动示例进行演示之前,我们先了解一下 Spring Cloud 应用如何接入 RocketMQ Binder。 + +> **注意:本章节只是为了便于您理解接入方式,本示例代码中已经完成****接入工作,您无需再进行修改。** + +1. 首先,修改 `pom.xml` 文件,引入 RocketMQ Stream Starter。 + +```xml + + org.springframework.cloud + spring-cloud-starter-stream-rocketmq + +``` + +2. 配置Input和Output的Binding信息并配合`@EnableBinding`注解使其生效 + +```java +@SpringBootApplication +@EnableBinding({ Source.class, Sink.class }) +public class RocketMQApplication { + public static void main(String[] args) { + SpringApplication.run(RocketMQApplication.class, args); + } +} +``` + +配置Binding信息: +```properties +# 配置rocketmq的nameserver地址 +spring.cloud.stream.rocketmq.binder.namesrv-addr=127.0.0.1:9876 +# 定义name为output的binding +spring.cloud.stream.bindings.output.destination=test-topic +spring.cloud.stream.bindings.output.content-type=application/json +# 定义name为input的binding +spring.cloud.stream.bindings.input.destination=test-topic +spring.cloud.stream.bindings.input.content-type=application/json +spring.cloud.stream.bindings.input.group=test-group + +``` + +3. 消息发送及消息订阅 + +### 下载并启动 RocketMQ + +在接入RocketMQ Binder之前,首先需要启动RocketMQ的Name Server和Broker。 + +1. 下载[RocketMQ最新的二进制文件](https://www.apache.org/dyn/closer.cgi?path=rocketmq/4.3.2/rocketmq-all-4.3.2-bin-release.zip),并解压 + +2. 启动 Name Server + +```bash +sh bin/mqnamesrv +``` + +3. 启动Broker + +```bash +sh bin/mqbroker -n localhost:9876 +``` + +4. 创建Topic: test-topic + +```bash +sh bin/mqadmin updateTopic -n localhost:9876 -c DefaultCluster -t test-topic +``` + +### 应用启动 + +1. 增加配置,在应用的 /src/main/resources/application.properties 中添加基本配置信息 + +```properties +spring.application.name=rocketmq-example +server.port=28081 +``` + +2. 启动应用,支持 IDE 直接启动和编译打包后启动。 + + 1. IDE直接启动:找到主类 `RocketMQApplication`,执行 main 方法启动应用。 + 2. 打包编译后启动:首先执行 `mvn clean package` 将工程编译打包,然后执行 `java -jar rocketmq-example.jar`启动应用。 + + +### 消息处理 + +使用name为output对应的binding发送消息到test-topic这个topic。 + +使用2个input binding订阅数据。 + +input1: 订阅topic为test-topic的消息,顺序消费所有消息(顺序消费的前提是所有消息都在一个MessageQueue中) +input2: 订阅topic为test-topic的消息,异步消费tags为tagStr的消息,Consumer端线程池个数为20 + +配置信息如下: + +```properties +spring.cloud.stream.rocketmq.binder.namesrv-addr=127.0.0.1:9876 + +spring.cloud.stream.bindings.output.destination=test-topic +spring.cloud.stream.bindings.output.content-type=application/json + +spring.cloud.stream.bindings.input1.destination=test-topic +spring.cloud.stream.bindings.input1.content-type=application/json +spring.cloud.stream.bindings.input1.group=test-group1 +spring.cloud.stream.rocketmq.bindings.input1.consumer.orderly=true + +spring.cloud.stream.bindings.input2.destination=test-topic +spring.cloud.stream.bindings.input2.content-type=application/json +spring.cloud.stream.bindings.input2.group=test-group2 +spring.cloud.stream.rocketmq.bindings.input2.consumer.orderly=false +spring.cloud.stream.rocketmq.bindings.input2.consumer.tags=tagStr +spring.cloud.stream.bindings.input2.consumer.concurrency=20 + +``` + +#### 消息发送 + +使用MessageChannel进行消息发送: + +```java +public class ProducerRunner implements CommandLineRunner { + @Autowired + private MessageChannel output; // 获取name为output的binding + @Override + public void run(String... args) throws Exception { + Map headers = new HashMap<>(); + headers.put(MessageConst.PROPERTY_TAGS, "tagStr"); + Message message = MessageBuilder.createMessage(msg, new MessageHeaders(headers)); + output.send(message); + } +} +``` + +或者使用RocketMQ原生的API进行消息发送: + +```java +public class RocketMQProducer { + DefaultMQProducer producer = new DefaultMQProducer("producer_group"); + producer.setNamesrvAddr("127.0.0.1:9876"); + producer.start(); + + Message msg = new Message("test-topic", "tagStr", "message from rocketmq producer".getBytes()); + producer.send(msg); +} +``` + +#### 消息接收 + +使用`@StreamListener`注解接收消息: + +```java +@Service +public class ReceiveService { + + @StreamListener("input1") + public void receiveInput1(String receiveMsg) { + System.out.println("input1 receive: " + receiveMsg); + } + + @StreamListener("input2") + public void receiveInput2(String receiveMsg) { + System.out.println("input2 receive: " + receiveMsg); + } + +} +``` + +## Endpoint 信息查看 + +Spring Boot 应用支持通过 Endpoint 来暴露相关信息,RocketMQ Stream Starter 也支持这一点。 + +在使用之前需要在 Maven 中添加 `spring-boot-starter-actuator`依赖,并在配置中允许 Endpoints 的访问。 +* Spring Boot 1.x 中添加配置 `management.security.enabled=false` +* Spring Boot 2.x 中添加配置 `management.endpoints.web.exposure.include=*` + +Spring Boot 1.x 可以通过访问 http://127.0.0.1:18083/rocketmq-binder 来查看 RocketMQ Binder Endpoint 的信息。Spring Boot 2.x 可以通过访问 http://127.0.0.1:28081/acutator/rocketmq-binder 来访问。 + +这里会统计消息最后一次发送的数据,消息发送成功或失败的次数,消息消费成功或失败的次数等数据。 + +```json +{ + "runtime": { + "lastSend.timestamp": 1542786623915 + }, + "metrics": { + "scs-rocketmq.consumer.test-topic.totalConsumed": { + "count": 11 + }, + "scs-rocketmq.consumer.test-topic.totalConsumedFailures": { + "count": 0 + }, + "scs-rocketmq.producer.test-topic.totalSentFailures": { + "count": 0 + }, + "scs-rocketmq.consumer.test-topic.consumedPerSecond": { + "count": 11, + "fifteenMinuteRate": 0.012163847780107841, + "fiveMinuteRate": 0.03614605351360527, + "meanRate": 0.3493213353657594, + "oneMinuteRate": 0.17099243039490175 + }, + "scs-rocketmq.producer.test-topic.totalSent": { + "count": 5 + }, + "scs-rocketmq.producer.test-topic.sentPerSecond": { + "count": 5, + "fifteenMinuteRate": 0.005540151995103271, + "fiveMinuteRate": 0.01652854617838251, + "meanRate": 0.10697493212602836, + "oneMinuteRate": 0.07995558537067671 + }, + "scs-rocketmq.producer.test-topic.sentFailuresPerSecond": { + "count": 0, + "fifteenMinuteRate": 0.0, + "fiveMinuteRate": 0.0, + "meanRate": 0.0, + "oneMinuteRate": 0.0 + }, + "scs-rocketmq.consumer.test-topic.consumedFailuresPerSecond": { + "count": 0, + "fifteenMinuteRate": 0.0, + "fiveMinuteRate": 0.0, + "meanRate": 0.0, + "oneMinuteRate": 0.0 + } + } +} +``` + +## More + +RocketMQ 是一款功能强大的分布式消息系统,广泛应用于多个领域,包括异步通信解耦、企业解决方案、金融支付、电信、电子商务、快递物流、广告营销、社交、即时通信、移动应用、手游、视频、物联网、车联网等。 + +此 Demo 仅演示了 RocketMQ 与 Spring Cloud Stream 结合后的使用,更多 RocketMQ 相关的信息,请参考 [RocketMQ 项目](https://github.com/apache/rocketmq)。 + +如果您对 spring cloud starter stream rocketmq 有任何建议或想法,欢迎在 issue 中或者通过其他社区渠道向我们提出。 + diff --git a/spring-cloud-alibaba-examples/rocketmq-example/src/main/resources/application.properties b/spring-cloud-alibaba-examples/rocketmq-example/src/main/resources/application.properties index 2a41b0d9..e936d25c 100644 --- a/spring-cloud-alibaba-examples/rocketmq-example/src/main/resources/application.properties +++ b/spring-cloud-alibaba-examples/rocketmq-example/src/main/resources/application.properties @@ -26,6 +26,8 @@ spring.cloud.stream.rocketmq.bindings.input3.consumer.tags=tagObj spring.cloud.stream.bindings.input3.consumer.concurrency=20 spring.cloud.stream.bindings.input3.consumer.maxAttempts=1 +spring.application.name=rocketmq-example + server.port=28081 management.endpoints.web.exposure.include=* \ No newline at end of file diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme-zh.md b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme-zh.md index c07c20e3..af535e6d 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme-zh.md +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme-zh.md @@ -196,77 +196,33 @@ Sentinel 控制台支持实时监控查看,您可以通过 Sentinel 控制台 Sentinel 内部提供了[动态规则的扩展实现 ReadableDataSource](https://github.com/alibaba/Sentinel/wiki/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%99%E6%89%A9%E5%B1%95#datasource-%E6%89%A9%E5%B1%95)。 -Sentinel starter 整合了目前存在的几类 DataSource。只需要在配置文件中进行相关配置,即可在 Spring 容器中自动注册 DataSource。 +Sentinel starter 整合了目前存在的几类 ReadableDataSource。只需要在配置文件中进行相关配置,即可在 Spring 容器中自动注册 DataSource。 -比如要定义一个 `FileRefreshableDataSource`,配置如下: +比如要定义两个ReadableDataSource,分别是 `FileRefreshableDataSource` 和 `NacosDataSource`,配置如下: - spring.cloud.sentinel.datasource.type=file - spring.cloud.sentinel.datasource.recommendRefreshMs=2000 - spring.cloud.sentinel.datasource.bufSize=2048 - spring.cloud.sentinel.datasource.charset=utf-8 - spring.cloud.sentinel.datasource.converter=myParser - spring.cloud.sentinel.datasource.file=/Users/you/rule.json +```properties +spring.cloud.sentinel.datasource.ds1.file.file=classpath: degraderule.json +spring.cloud.sentinel.datasource.ds1.file.data-type=json -然后使用`@SentinelDataSource` 注解修饰 DataSource 即可注入: +spring.cloud.sentinel.datasource.ds2.nacos.server-addr=localhost:8848 +spring.cloud.sentinel.datasource.ds2.nacos.dataId=sentinel +spring.cloud.sentinel.datasource.ds2.nacos.groupId=DEFAULT_GROUP +spring.cloud.sentinel.datasource.ds2.nacos.data-type=json +``` - @SentinelDataSource("spring.cloud.sentinel.datasource") - private ReadableDataSource dataSource; +`ds1` 和 `ds2` 表示ReadableDataSource的名称,可随意编写。`ds1` 和 `ds2` 后面的 `file` 和 `nacos` 表示ReadableDataSource的类型。 -`@SentinelDataSource` 注解的 value 属性可以不填。默认值就是 `spring.cloud.sentinel.datasource`。 +目前支持`file`, `nacos`, `zk`, `apollo` 这4种类型。 -`value` 属性代表配置前缀。示例中会去找 `spring.cloud.sentinel.datasource.xxx` 相关的配置。 +其中`nacos`,`zk`,`apollo`这3种类型的使用需要加上对应的依赖`sentinel-datasource-nacos`, `sentinel-datasource-zookeeper`, `sentinel-datasource-apollo`。 -`spring.cloud.sentinel.datasource.type` 就是对应的 DataSource 类型。 +当ReadableDataSource加载规则数据成功的时候,控制台会打印出相应的日志信息: -`spring.cloud.sentinel.datasource.recommendRefreshMs` 里的 `recommendRefreshMs` 对应相关 DataSource 的属性。 +``` +[Sentinel Starter] DataSource ds1-sentinel-file-datasource load 3 DegradeRule +[Sentinel Starter] DataSource ds2-sentinel-nacos-datasource load 2 FlowRule +``` -`spring.cloud.sentinel.datasource.converter`代表 `Converter` 在 Spring 容器里的 name。如果没找到,会抛出异常。 - -type目前支持file, nacos, zk, apollo。其中nacos,zk,apollo的使用需要加上对应的依赖`sentinel-datasource-nacos`, `sentinel-datasource-zookeeper`, `sentinel-datasource-apollo` - -### 自定义DataSource - -自定义DataSource只需要两步。 - -1. 定义DataSource - - public class CustomDataSource implements ReadableDataSource { - private String fieldA; - private String fieldB; - ... - } - -2. 装配DataSource。有两种方式处理。 - - * 直接构造DataSource - - @Bean - public CustomDataSource customDataSource() { - CustomDataSource customDataSource = - new CustomDataSource(); - customDataSource.setFieldA("valueA"); - customDataSource.setFieldB("valueB"); - ... - return customDataSource; - } - - * 在classpath:/META-INF/sentinel-datasource.properties中管理DataSource信息 - - custom = yourpackage.CustomDataSource - - 在application.properties中定义DataSource - - spring.cloud.sentinel.datasource.type = custom - spring.cloud.sentinel.datasource.fieldA = valueA - spring.cloud.sentinel.datasource.fieldB = valueB - - 注意:由于目前Sentinel的AbstractDataSource需要有个Converter作为构造函数中的参数,并且它的子类的构造都是通过多个参数的构造函数构造的。 - 所以目前所有的Sentinel starter中的DataSource都是基于FactoryBean并且通过设置属性构造的。如果有这方面的需求,需要再多加一个registerFactoryBean过程。 - - SentinelDataSourceRegistry.registerFactoryBean("custeom", CustomDataSourceFactoryBean.class); - - 如果自定义DataSource可以注入属性,那么没有必要使用SentinelDataSourceRegistry注册FactoryBean。 - ## More Sentinel 是一款功能强大的中间件,从流量控制,熔断降级,系统负载保护等多个维度保护服务的稳定性。此 Demo 仅演示了 使用 Sentinel 作为限流工具的使用,更多 Sentinel 相关的信息,请参考 [Sentinel 项目](https://github.com/alibaba/Sentinel)。 diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme.md b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme.md index dcdd77fc..e3135729 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme.md +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme.md @@ -71,7 +71,7 @@ Before we start the demo, let's learn how to connect Sentinel to a Spring Cloud 2. Start the application in IDE or by building a fatjar. 1. Start in IDE: Find main class `ServiceApplication`, and execute the main method. - 2. Build a fatjar:Execute command `mvn clean package` to build a fatjar,and run command `java -jar sentinel-core-example.jar` to start the application. + 2. Build a fatjar:Execute command `mvn clean package` to build a fatjar, and run command `java -jar sentinel-core-example.jar` to start the application. ### Invoke Service @@ -86,7 +86,7 @@ The screenshot belows shows invoke success: 1. Open http://localhost:8080 in browser, and you can find a Sentinel-Example Application has been registered to the dashboard. - **Note: If you can't find your application in the dashboard, invoke a method that has been defined as a Sentinel Resource,for Sentinel uses lazy load strategy.** + **Note: If you can't find your application in the dashboard, invoke a method that has been defined as a Sentinel Resource, for Sentinel uses lazy load strategy.**

@@ -171,73 +171,30 @@ Sentinel provide [ReadableDataSource](https://github.com/alibaba/Sentinel/blob/m Sentinel starter integrated 4 DataSources provided by Sentinel. It will be register into Spring Context if you write some configs in `application.properties`. -If you want to define FileRefreshableDataSource: +If you want to define `FileRefreshableDataSource` and `NacosDataSource`, see the code below: - spring.cloud.sentinel.datasource.type=file - spring.cloud.sentinel.datasource.recommendRefreshMs=2000 - spring.cloud.sentinel.datasource.bufSize=2048 - spring.cloud.sentinel.datasource.charset=utf-8 - spring.cloud.sentinel.datasource.converter=myParser - spring.cloud.sentinel.datasource.file=/Users/you/rule.json - -then use `@SentinelDataSource` to annotate DataSource: - - @SentinelDataSource("spring.cloud.sentinel.datasource") - private ReadableDataSource dataSource; - -The value() of `@SentinelDataSource` is not required, it means the prefix of configuration. Default value is `spring.cloud.sentinel.datasource`. +```properties +spring.cloud.sentinel.datasource.ds1.file.file=classpath: degraderule.json +spring.cloud.sentinel.datasource.ds1.file.data-type=json -spring.cloud.sentinel.datasource.type means the type of DataSource. +spring.cloud.sentinel.datasource.ds2.nacos.server-addr=localhost:8848 +spring.cloud.sentinel.datasource.ds2.nacos.dataId=sentinel +spring.cloud.sentinel.datasource.ds2.nacos.groupId=DEFAULT_GROUP +spring.cloud.sentinel.datasource.ds2.nacos.data-type=json +``` -spring.cloud.sentinel.datasource.recommendRefreshMs means the recommendRefreshMs property of specified DataSource. +`ds1` and `ds2` means the name of ReadableDataSource, you can write whatever you want. The `file` and `nacos` after name `ds1` and `ds2` means the type of ReadableDataSource. -spring.cloud.sentinel.datasource.converter means the name of spring bean that type is Converter. If the bean is not exists, will throw exception. - -Now datasource type support 4 categories: file, nacos, zk, apollo. If you want to using nacos, zk or apollo, you should add `sentinel-datasource-nacos`, `sentinel-datasource-zookeeper` or `sentinel-datasource-apollo` dependency. +Now ReadableDataSource type support 4 categories: `file`, `nacos`, `zk` and `apollo`. +If you want to use `nacos`, `zk` or `apollo` ReadableDataSource, you could add `sentinel-datasource-nacos`, `sentinel-datasource-zookeeper` or `sentinel-datasource-apollo` dependency. -### User-defined DataSource +When ReadableDataSource load rule data successfully, console will print some logs: -User-defined DataSource need 2 steps. - -1. Define DataSource - - public class CustomDataSource implements ReadableDataSource { - private String fieldA; - private String fieldB; - ... - } - -2. Assemble DataSource. There are 2 ways to do this. - - * Construct DataSource directly - - @Bean - public CustomDataSource customDataSource() { - CustomDataSource customDataSource = new CustomDataSource(); - customDataSource.setFieldA("valueA"); - customDataSource.setFieldB("valueB"); - ... - return customDataSource; - } - - * define DataSource metadata in `classpath:/META-INF/sentinel-datasource.properties` - - custom = yourpackage.CustomDataSource - - define configuration in `application.properties` - - spring.cloud.sentinel.datasource.type = custom - spring.cloud.sentinel.datasource.fieldA = valueA - spring.cloud.sentinel.datasource.fieldB = valueB - -Note: The AbstractDataSource of Sentinel need a Converter as a constructor param and the subclass of AbstractDataSource was construct by multi-param constructor. -Now All DataSources in starter was construct by FactoryBean. If you want to do it in this way, you should register FactoryBean by SentinelDataSourceRegistry. - - SentinelDataSourceRegistry.registerFactoryBean("custeom", CustomDataSourceFactoryBean.class); - -It is no need to using SentinelDataSourceRegistry to register FactoryBean if your User-defined DataSource can inject fields. - +``` +[Sentinel Starter] DataSource ds1-sentinel-file-datasource load 3 DegradeRule +[Sentinel Starter] DataSource ds2-sentinel-nacos-datasource load 2 FlowRule +``` ## More For more information about Sentinel, see [Sentinel Project](https://github.com/alibaba/Sentinel). diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/application.properties b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/application.properties index 100b4010..9f9a734e 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/application.properties +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/src/main/resources/application.properties @@ -1,8 +1,7 @@ spring.application.name=sentinel-example server.port=18083 management.endpoints.web.exposure.include=* -spring.cloud.sentinel.transport.port=8721 -spring.cloud.sentinel.transport.dashboard=localhost:9999 +spring.cloud.sentinel.transport.dashboard=localhost:8080 spring.cloud.sentinel.eager=true spring.cloud.sentinel.datasource.ds1.file.file=classpath: flowrule.json diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ApolloDataSourceFactoryBean.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ApolloDataSourceFactoryBean.java index e0df905b..ddca34cb 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ApolloDataSourceFactoryBean.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ApolloDataSourceFactoryBean.java @@ -57,7 +57,7 @@ public class ApolloDataSourceFactoryBean implements FactoryBean return converter; } - public void setConverter(Converter Converter) { - this.converter = Converter; + public void setConverter(Converter converter) { + this.converter = converter; } } diff --git a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ZookeeperDataSourceFactoryBean.java b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ZookeeperDataSourceFactoryBean.java index 8b4ed177..b266f01f 100644 --- a/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ZookeeperDataSourceFactoryBean.java +++ b/spring-cloud-alibaba-sentinel-datasource/src/main/java/org/springframework/cloud/alibaba/sentinel/datasource/factorybean/ZookeeperDataSourceFactoryBean.java @@ -75,7 +75,7 @@ public class ZookeeperDataSourceFactoryBean implements FactoryBean