Spring Cloud Stream入门demo

前言

本文提供一个Spring Cloud Stream极简的入门demo。

概念

  1. Spring Cloud Stream是什么
    Spring Cloud Stream使我们不再需要关注具体的消息中间件的细节,而只需要用一种适配绑定的方式,修改配置文件,就能自动的在各种消息中间件内切换,它能屏蔽底层消息中间件的差异,降低切换成本,统一消息的编程模型,这使得Spring Cloud Stream具有很大的吸引力。
  2. 编程模式:Spring Cloud Stream提供了三个开箱即用的预定义接口。
  • Source: 用于有单个输出(outbound)通道的应用。
  • Sink: 用于有单个输入(inbound)通道的应用。
  • Processor: 用于单个应用同时包含输入和输出通道的情况。
    这几个接口就是Spring Cloud Stream提供的对于消息中间件的抽象,我们仅仅需要在配置文件中关注具体的中间件,而写代码的时候对具体的消息中间件是无感知的,无论是RabbitMQ、RocketMQ还是Kafka等,代码都是相同的。这也是Spring Cloud Stream最具有吸引力的一点,她定义了一种消息驱动编程模型,

在这里插入图片描述

如果刚接触Spring Cloud Stream,肯定会一头雾水,不过没有关系,下面通过一个极简的demo来帮助理解。

其实Sink和Source接口是位于不同的模块中的(生产者和消费者),但是为了演示方便,我放在了同一个项目里面。

//消费者
public interface MySink {
    String INPUT = "orderInput";
    @Input(MySink.INPUT)
    SubscribableChannel input();
}

// 生产者
public interface MySource {
    String OUTPUT = "orderOutput";
    @Output(MySource.OUTPUT)
    MessageChannel output();
}

@Slf4j
@Component
@Configuration
@EnableBinding({MySink.class,MySource.class})
public class Demo1Runner implements CommandLineRunner {

    final MySink sink;
    final MySource mySource;

    public Demo1Runner(MySink sink, MySource mySource) {
        this.sink = sink;
        this.mySource = mySource;
    }

    @Override
    public void run(String... args) {
        sink.input().subscribe(message -> log.info(message.toString()));
        for (int i=0;i<10;i++){
            mySource.output().send(new GenericMessage<>("hello world"));
        }
    }
}
server:
  host: your host

spring:
  application:
    name: stream-demo
  cloud:
    stream:
      default-binder: rabbit
      bindings:
        orderInput:
          binder: rabbit
          destination: order-exchange
          group: order-queue
        orderOutput:
          binder: rabbit
          destination: order-exchange
          group: order-queue
      rocketmq:
        binder:
          name-server: ${server.host}:9876

  rabbitmq:
    host: ${server.host}
    port: 5672
    username: guest
    password: guest

buld.gradle

plugins {
	id 'org.springframework.boot' version '2.3.0.RELEASE'
	id 'io.spring.dependency-management' version '1.0.9.RELEASE'
	id 'java'
}

group = 'com.delicious.demo'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '14'

configurations {
	developmentOnly
	runtimeClasspath {
		extendsFrom developmentOnly
	}
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
	maven { url 'http://maven.aliyun.com/nexus/content/repositories/jcenter' }
	mavenCentral()
}

ext {
	set('springCloudAlibabaVersion', "2.2.1.RELEASE")
	set('springCloudVersion', "Hoxton.SR4")
}

dependencies {
	compile group: 'org.springframework.boot', name: 'spring-boot-starter-web'

	implementation 'org.springframework.boot:spring-boot-starter-amqp'
	implementation 'com.alibaba.cloud:spring-cloud-starter-stream-rocketmq'
	implementation 'org.springframework.cloud:spring-cloud-stream'
	implementation 'org.springframework.cloud:spring-cloud-stream-binder-rabbit'
	compileOnly 'org.projectlombok:lombok'
	testImplementation 'org.projectlombok:lombok'
	testAnnotationProcessor 'org.projectlombok:lombok'
	developmentOnly 'org.springframework.boot:spring-boot-devtools'
	annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation('org.springframework.boot:spring-boot-starter-test') {
//		exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
	}
	testImplementation 'org.springframework.amqp:spring-rabbit-test'
	testImplementation 'org.springframework.cloud:spring-cloud-stream-test-support'
}

dependencyManagement {
	imports {
		mavenBom "com.alibaba.cloud:spring-cloud-alibaba-dependencies:${springCloudAlibabaVersion}"
		mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
	}
}

test {
	useJUnitPlatform()
}

这个例子是演示生产者发送订单消息到消息中间件,然后消费者监听并对消息进行消费。
启动Spring boot应用,控制台输出如下:
在这里插入图片描述
可以看到一个专门的线程监听订单队列。
通过RabbitMQ控制台也可以看到配置中指定的交换机和队列也已经创建 了。
在这里插入图片描述在这里插入图片描述
生成的exchange的type默认是topic类型。

注意点

@EnableBinding(Sink.class)如果没有对Sink注册消息处理器消费消息,则会出现以下异常:
Caused by: org.springframework.integration.MessageDispatchingException: Dispatcher has no subscribers

结语

到这完成了对Spring Cloud Stream的入门演示,如果要实现更复杂的功能,就需要在配置文件中进行更多的配置了。这里贴上一份RocketMQ官方的参考配置,以供学习。

#################################### common config : ####################################
spring.application.name=cloud_stream_demo
# 应用服务web访问端口
server.port=8080
# ActuatorWeb访问端口
management.server.port=8081
management.endpoints.jmx.exposure.include=*
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always

# spring cloud access&secret config
# 可以访问如下地址查看: https://usercenter.console.aliyun.com/#/manage/ak
alibaba.cloud.access-key=****
alibaba.cloud.secret-key=****


#################################### rocketmq config : ####################################
## 控制台: https://ons.console.aliyun.com
## Spring Cloud Alibaba RocketMQ 文档:https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-docs/src/main/asciidoc-zh/rocketmq.adoc
## RocketMQ 帮助文档:https://help.aliyun.com/product/29530.html

########## RocketMQ 通用配置
# 客户端接入点,必填
spring.cloud.stream.rocketmq.binder.name-server=111.229.90.24:9876
# 阿里云账号 AccessKey,默认为空;如果使用aliyun提供的rocketmq服务,该值必填
spring.cloud.stream.rocketmq.binder.access-key=
# 阿里云账号 SecretKey,默认为空;如果使用aliyun提供的rocketmq服务,该值必填
spring.cloud.stream.rocketmq.binder.secret-key=
# 日志级别
logging.level.com.alibaba.cloud.stream.binder.rocketmq=INFO

########## Consumer Config
# input1 的配置:
spring.cloud.stream.bindings.input1.destination=test-topic
spring.cloud.stream.bindings.input1.content-type=text/plain
spring.cloud.stream.bindings.input1.group=test-group1
# Consumer 是否同步消费消息模式。默认为false
spring.cloud.stream.rocketmq.bindings.input1.consumer.orderly=true
# Consumer 基于 TAGS 订阅,多个 tag 以 || 分割。默认值: empty(即空字符串"")
spring.cloud.stream.rocketmq.bindings.input1.consumer.tags=tagStr
# 异步消费消息模式下消费失败重试策略,默认值: 0
# -1 = 不重复,直接放入死信队列
#  0 = broker 控制重试策略
# >0 = client 控制重试策略
spring.cloud.stream.rocketmq.bindings.input1.consumer.delayLevelWhenNextConsume=0
# 同步消费消息模式下消费失败后再次消费的时间间隔。默认值: 1000
spring.cloud.stream.rocketmq.bindings.input1.consumer.suspendCurrentQueueTimeMillis=1000
# 更多配置参数,可查看源码:com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties
# input2 的配置:
spring.cloud.stream.bindings.input2.destination=test-topic
spring.cloud.stream.bindings.input2.content-type=text/plain
spring.cloud.stream.bindings.input2.group=test-group2
spring.cloud.stream.bindings.input2.consumer.concurrency=20
spring.cloud.stream.bindings.input2.consumer.maxAttempts=1
spring.cloud.stream.rocketmq.bindings.input2.consumer.orderly=false
spring.cloud.stream.rocketmq.bindings.input2.consumer.tags=tagStr
# input3 的配置:
spring.cloud.stream.bindings.input3.destination=test-topic
spring.cloud.stream.bindings.input3.content-type=application/json
spring.cloud.stream.bindings.input3.group=test-group3
spring.cloud.stream.bindings.input3.consumer.concurrency=20
spring.cloud.stream.rocketmq.bindings.input3.consumer.tags=tagObj
# input4 的配置:
spring.cloud.stream.bindings.input4.destination=TransactionTopic
spring.cloud.stream.bindings.input4.content-type=text/plain
spring.cloud.stream.bindings.input4.group=transaction-group
spring.cloud.stream.bindings.input4.consumer.concurrency=5
# input5 的配置:
spring.cloud.stream.bindings.input5.destination=pull-topic
spring.cloud.stream.bindings.input5.content-type=text/plain
spring.cloud.stream.bindings.input5.group=pull-topic-group

########## Produce Config
# output1 的配置如下:
spring.cloud.stream.bindings.output1.destination=test-topic
spring.cloud.stream.bindings.output1.content-type=text/plain
# Producer group name。默认值为empty(即"")
spring.cloud.stream.rocketmq.bindings.output1.producer.group=my_group
# 是否发送事务消息。默认值为false
spring.cloud.stream.rocketmq.bindings.output1.producer.transactional=false
# 是否使用同步得方式发送消息。默认值为false
spring.cloud.stream.rocketmq.bindings.output1.producer.sync=true
# 更多配置参数,可查看源码:com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQProducerProperties

# output2 的配置如下:
spring.cloud.stream.bindings.output2.destination=test-topic
spring.cloud.stream.bindings.output2.content-type=application/json
spring.cloud.stream.rocketmq.bindings.output2.producer.group=myTxProducerGroup
spring.cloud.stream.rocketmq.bindings.output2.producer.transactional=true
spring.cloud.stream.rocketmq.bindings.output2.producer.sync=false



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值