天天看点

Spring Cloud Alibaba - Spring Cloud Stream 整合 RocketMQ

Spring Cloud Stream

在微服务的开发过程中,可能会经常用到消息中间件,通过消息中间件在服务与服务之间传递消息,不管你使用的是哪款消息中间件,比如RabbitMQ、Kafka和RocketMQ,那么消息中间件和服务之间都有一点耦合性,这个耦合性就是指如果我原来使用的RabbitMQ,现在要替换为RocketMQ,那么我们的微服务都需要修改,变动会比较大,因为这两款消息中间件有一些区别,如果我们使用Spring Cloud Stream来整合我们的消息中间件,那么这样就可以降低微服务和消息中间件的耦合性,做到轻松在不同消息中间件间切换,当然Spring Cloud Stream官方只支持rabbitmq 和 kafka,spring cloud alibaba新写了一个starter可以支持RocketMQ;

按照官方的定义,Spring Cloud Stream 是一个构建消息驱动微服务的框架;

Spring Cloud Stream解决了开发人员无感知的使用消息中间件的问题,因为Spring Cloud Stream对消息中间件的进一步封装,可以做到代码层面对消息中间件的无感知,甚至于动态的切换中间件(rabbitmq切换为rocketmq或者kafka),使得微服务开发的高度解耦,服务可以关注更多自己的业务流程;

Spring Cloud Alibaba - Spring Cloud Stream 整合 RocketMQ

Spring Cloud Stream 内部有几个概念:Binder 、Binding、input、output;

1、Binder: 跟外部消息中间件集成的组件,用来创建Binding,各消息中间件都有自己的 Binder 实现;

比如 Kafka 的实现 KafkaMessageChannelBinder,RabbitMQ 的实现 RabbitMessageChannelBinder 以及 RocketMQ 的实现 RocketMQMessageChannelBinder;

2、Binding: 包括 Input Binding 和 Output Binding;

Binding 在消息中间件与应用程序提供的 Provider 和 Consumer 之间提供了一个桥梁,实现了开发者只需使用应用程序的 Provider 或 Consumer 生产或消费数据即可,屏蔽了开发者与底层消息中间件的接触;

3、input

应用程序通过input(相当于消费者consumer)与Spring Cloud Stream中Binder交互,而Binder负责与消息中间件交互,因此,我们只需关注如何与Binder交互即可,而无需关注与具体消息中间件的交互。

4、Output

output(相当于生产者producer)与Spring Cloud Stream中Binder交互;

组成

说明

Binder

Binder是应用与消息中间件之间的封装,目前实现了Kafka和RabbitMQ的Binder,通过Binder可以很方便的连接中间件,可以动态的改变消息类型(对应于Kafka的topic,RabbitMQ的exchange),这些都可以通过配置文件来实现;

@Input

该注解标识输入通道,通过该输入通道接收消息进入应用程序

@Output

该注解标识输出通道,发布的消息将通过该通道离开应用程序

@StreamListener

监听队列,用于消费者的队列的消息接收

@EnableBinding

将信道channel和exchange、topic绑定在一起

消息生产者

1、创建SpringBoot应用31-rocket-spring-cloud-stream;

2、添加依赖:

配置文件

Spring Cloud Alibaba - Spring Cloud Stream 整合 RocketMQ

兼容性问题:

注意版本需要使用springboot2.2.5

消息发送:

消息接收:

可以通过调用SenderService中的方法进行发送信息,也可以通过在启动类中的Main方法中进行调用SenderService的方法进行发送信息:

Spring Cloud Alibaba - Spring Cloud Stream 整合 RocketMQ

在前面的案例中,我们已经实现了一个基础的 Spring Cloud Stream 消息传递处理操作,但在操作之中使用的是系统提供的 Source (output)、Sink(input),接下来我们来看一下自定义信道名称;

Apache RocketMQ在4.3.0版中已经支持分布式事务消息,这里RocketMQ采用了2PC的思想来实现了提交事务消息,同时增加一个补偿逻辑来处理二阶段超时或者失败的消息,如下图所示:

Spring Cloud Alibaba - Spring Cloud Stream 整合 RocketMQ

上图说明了事务消息的大致方案,其中分为两个流程:正常事务消息的发送及提交、事务消息的补偿流程;

1.事务消息发送及提交:

(1) 发送消息(half消息);

(2) 服务端响应消息写入结果;

(3) 根据发送结果执行本地事务(如果写入失败,此时half消息对业务不可见,本地逻辑不执行);

(4) 根据本地事务状态执行Commit或者Rollback(Commit操作生成消息索引,消息对消费者可见)

2.补偿流程:

(1) 对没有Commit/Rollback的事务消息(pending状态的消息),从服务端发起一次“回查”;

(2) Producer收到回查消息,检查回查消息对应的本地事务的状态;

(3) 根据本地事务状态,重新Commit或者Rollback;

其中,补偿阶段用于解决消息Commit或者Rollback发生超时或者失败的情况;

事务消息一共有三种状态:提交状态、回滚状态、中间状态;

TransactionStatus.CommitTransaction: 提交事务,代表消费者可以消费此消息;

TransactionStatus.RollbackTransaction: 回滚事务,代表消息将被删除,不能被消费;

TransactionStatus.Unknown: 中间状态,代表需要检查消息队列来确定状态;

MQ内部逻辑:

自定义信道-重写Source

自定义信道-重写Sink

消费者接收消息:

*spring.cloud.stream.rocketmq.binder.name-server*

RocketMQ NameServer 地址(老版本使用 namesrv-addr 配置项);

Default: 127.0.0.1:9876.

*spring.cloud.stream.rocketmq.binder.access-key*

阿里云账号 AccessKey。

Default: null.

*spring.cloud.stream.rocketmq.binder.secret-key*

阿里云账号 SecretKey。

*spring.cloud.stream.rocketmq.binder.enable-msg-trace*

是否为 Producer 和 Consumer 开启消息轨迹功能

Default: true.

*spring.cloud.stream.rocketmq.binder.customized-trace-topic*

消息轨迹开启后存储的 topic 名称。

Default: RMQ_SYS_TRACE_TOPIC.

下面的这些配置是以 spring.cloud.stream.rocketmq.bindings..consumer. 为前缀的 RocketMQ Consumer 相关的配置。

*enable*

是否启用 Consumer;

默认值: true.

*tags*

Consumer 基于 TAGS 订阅,多个 tag 以 || 分割;

默认值: empty.

*sql*

Consumer 基于 SQL 订阅;

*broadcasting*

Consumer 是否是广播消费模式。如果想让所有的订阅者都能接收到消息,可以使用广播模式;

默认值: false.

*orderly*

Consumer 是否同步消费消息模式;

*delayLevelWhenNextConsume*

异步消费消息模式下消费失败重试策略:

-1,不重复,直接放入死信队列

0,broker 控制重试策略

>0,client 控制重试策略

默认值: 0.

*suspendCurrentQueueTimeMillis*

同步消费消息模式下消费失败后再次消费的时间间隔;

默认值: 1000.

下面的这些配置是以 spring.cloud.stream.rocketmq.bindings..producer. 为前缀的 RocketMQ Producer 相关的配置;

是否启用 Producer;

*group*

Producer group name;

*maxMessageSize*

消息发送的最大字节数;

默认值: 8249344.

*transactional*

是否发送事务消息;

*sync*

是否使用同步得方式发送消息;

*vipChannelEnabled*

是否在 Vip Channel 上发送消息;

*sendMessageTimeout*

发送消息的超时时间(毫秒);

默认值: 3000.

*compressMessageBodyThreshold*

消息体压缩阀值(当消息体超过 4k 的时候会被压缩);

默认值: 4096.

*retryTimesWhenSendFailed*

在同步发送消息的模式下,消息发送失败的重试次数;

默认值: 2.

*retryTimesWhenSendAsyncFailed*

在异步发送消息的模式下,消息发送失败的重试次数;

*retryNextServer*

消息发送失败的情况下是否重试其它的 broker;