「springcloud 2021 系列」RocketMQ 如何快速实现微服务消息机制

RocketMQ 介绍

详解了解可以查看如下文档:rocketmq 基础知识

RocketMQ 是一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。同时,广泛应用于多个领域,包括异步通信解耦、企业解决方案、金融支付、电信、电子商务、快递物流、广告营销、社交、即时通信、移动应用、手游、视频、物联网、车联网等。

具有以下特点:

  • 能够保证严格的消息顺序
  • 提供丰富的消息拉取模式
  • 高效的订阅者水平扩展能力
  • 实时的消息订阅机制
  • 亿级消息堆积能力

如何选择 RocketMQ 实现

6.png

Spring Cloud Stream

Spring Cloud Stream 是一个用于构建基于消息的微服务应用框架,使用 Spring Integration 与 Broker 进行连接。

一般来说,消息队列中间件都有一个 Broker Server(代理服务器),消息中转角色,负责存储消息、转发消息

例如在 RocketMQ 中,Broker 负责接收从生产者发送来的消息并存储、同时为消费者的拉取请求作准备。另外,Broker 也存储消息相关的元数据,包括消费者组、消费进度偏移和主题和队列消息等

Spring Cloud Stream 提供了消息中间件的统一抽象,推出了 publish-subscribe、consumer groups、partition 这些统一的概念。

Spring Cloud Stream 内部有两个概念:BinderBinding

  • Binder,跟消息中间件集成的组件,用来创建对应的 Binding。各消息中间件都有自己的 Binder 具体实现

    • Kafka 实现了 KafkaMessageChannelBinder
    • RabbitMQ 实现了 RabbitMessageChannelBinder
    • RocketMQ 实现了 RocketMQMessageChannelBinder
  • Binding,包括 Input Binding 和 Output Binding。Binding 在消息中间件与应用程序提供的 Provider 和 Consumer 之间提供了一个桥梁,实现了开发者只需使用应用程序的 Provider 或 Consumer 生产或消费数据即可,屏蔽了开发者与底层消息中间件的接触

    img

TB1v8rcbUY1gK0jSZFCXXcwqXXa 1236 773

RocketMQ 基本使用

本项目演示如何使用 RocketMQ Binder 完成 Spring Cloud 应用消息的订阅和发布。

源码地址:https://github.com/langyastudio/langya-tech/tree/master/spring-cloud

依赖环境

引入 Spring Cloud Alibaba RocketMQ 相关依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-stream-rocketmq</artifactId>
</dependency>

Producer 生产者

配置文件
server:
  port: 28081

spring:
  application:
    name: rocketmq-produce

  cloud:
    stream:
      # 对应 BindingProperties Map
      bindings:
        output-common:
          #RocketMQ Topic
          destination: topic-common-01
          content-type: application/json
        output-tx:
          destination: topic-tx-01
          content-type: application/json

      # Spring Cloud Stream RocketMQ 配置项
      rocketmq:
        # 对应 RocketMQBinderConfigurationProperties 类
        binder:
          name-server: 192.168.123.22:9876

        # RocketMQ 自定义 Binding 配置项,对应 RocketMQBindingProperties Map
        bindings:
          output-common:
            # RocketMQ Producer 配置项,对应 RocketMQProducerProperties 类
            producer:
              #生产者分组
              group: group-common
              #同步发送消息
              sync: true
              #最大字节数
              maxMessageSize: 8249344
              #超时时间
              sendMessageTimeout: 3000
          tx-output:
            producer:
              #group name
              group: group-tx
              #发送事务消息
              transactional: true

logging:
  level:
    com:
      alibaba:
        cloud:
          stream:
            binder:
              rocketmq: DEBUG
  • spring.cloud.stream.bindings 为 Binding 配置项

    Binding 分成 Input 和 Output 两种类型,但是在配置项中并不能体现出来,而是要在稍后搭配 @Input or @Output 注解,才会区分

  • spring.cloud.stream.rocketmq.binder 为 RocketMQ Binder 配置项。

    name-server:RocketMQ Namesrv 地址。名称服务充当路由消息的提供者。生产者或消费者能够通过名字服务查找各主题相应的 Broker IP 列表。多个 Namesrv 实例组成集群,但相互独立,没有信息交换。

@Output 发送消息
public interface OutputSource
{
    @Output("output-common")
    MessageChannel sendCommon();

    @Output("output-tx")
    MessageChannel sendTx();
}

通过 @Output 注解,声明了一个名字为 output-common 的 Output Binding。注意,这个名字要和配置文件中的 spring.cloud.stream.bindings 配置项对应上

同时,@Output 注解的方法的返回结果为 MessageChannel 类型,可以使用它发送消息

SenderService 消息发送服务

通过组装 Message 消息体并调用 OutputSource 接口,实现消息发送的逻辑

@Service
public class SenderService
{
    @Autowired
    private OutputSource source;

    /**
     * 发送消息
     *
     * @param msg 消息内容
     * @param tag 标签
     * @param delay 设置延迟级别为x秒后消费
     * @return
     * @throws Exception
     */
    public <T> boolean sendObject(T msg, String tag, Integer delay) throws Exception
    {
        Message<T> message = MessageBuilder.withPayload(msg)
                .setHeader(MessageConst.PROPERTY_TAGS, tag)
                .setHeader(MessageConst.PROPERTY_DELAY_TIME_LEVEL, delay)
                .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON)
                .build();

        return source.sendCommon().send(message);
    }

    public <T> boolean sendTransactionalMsg(T msg, int num) throws Exception
    {
        Message<T> message  = MessageBuilder.withPayload(msg)
                .setHeader("tx-state", String.valueOf(num))
                .setHeader(MessageConst.PROPERTY_TAGS, "binder")
                .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON)
                .build();

        return source.sendTx().send(message);
    }
}
Controller 接口定义

提供发送消息的 HTTP 接口。代码如下:

@RestController
@RequestMapping("/produce")
public class ProduceController
{
    @Autowired
    private SenderService senderService;

    @GetMapping("/send1")
    public boolean output1(@RequestParam("msg") String msg) throws Exception
    {
        int msgId = new SecureRandom().nextInt();
        return senderService.sendObject(new FooMsg(msgId, msg), "tagObj", 0);
    }

    @GetMapping("/send3")
    public boolean output3() throws Exception
    {
        // unknown message
        senderService.sendTransactionalMsg("transactional-msg1", 1);
        // rollback message
        senderService.sendTransactionalMsg("transactional-msg2", 2);
        // commit message
        senderService.sendTransactionalMsg("transactional-msg3", 3);

        return true;
    }
}
Application 入口

启动应用。代码如下:

@SpringBootApplication
@EnableBinding({OutputSource.class})
public class RocketMQProduceApplication
{
    public static void main(String[] args)
    {
        SpringApplication.run(RocketMQProduceApplication.class, args);
    }
}

使用 @EnableBinding注解,声明指定接口开启 Binding 功能,扫描其 @Input@Output 注解。

消费者

配置文件
server:
  # 随机端口,方便启动多个消费者
  port: ${random.int[10000,19999]}

spring:
  application:
    name: rocketmq-consume

  cloud:
    # Spring Cloud Stream 配置项,对应 BindingServiceProperties 类
    stream:
      # Binding 配置项,对应 BindingProperties Map
      bindings:
        input-common-1:
          # 目的地。这里使用 RocketMQ Topic
          destination: topic-common-01
          content-type: application/json
          ## 消费者分组, 命名规则:group+topic名+xx
          group: group-common-1
        input-common-2:
          destination: topic-common-01
          content-type: application/json
          consumer:
            concurrency: 20
            maxAttempts: 1
          group: group-common-2
        input-common-3:
          destination: topic-common-01
          content-type: application/json
          consumer:
            concurrency: 20
          group: group-common-3
        input-tx-1:
          destination: topic-tx-01
          content-type: text/json
          consumer:
            concurrency: 5
          group: group-tx-1

      # Spring Cloud Stream RocketMQ 配置项
      rocketmq:
        binder:
          name-server: 192.168.123.22:9876

        bindings:
          input-common-1:
            # RocketMQ Consumer 配置项
            consumer:
              # 是否开启消费,默认为 true
              enabled: true
              # 是否使用广播消费,默认为 false 使用集群消费,如果要使用广播消费值设成true
              broadcasting: false
              orderly: true
          input-common-2:
            consumer:
              orderly: false
          input-common-3:
            consumer:
              tags: tagObj

spring.cloud.stream.rocketmq.bindings

  • enabled:是否开启消费,默认为 true。在日常开发时,如果在本地环境不想消费,可以通过设置 enabledfalse 进行关闭

  • broadcasting: 是否使用广播消费,默认为 false 使用的是集群消费。

    集群消费(Clustering):集群消费模式下,相同 Consumer Group 的每个 Consumer 实例平均分摊消息

    广播消费(Broadcasting):广播消费模式下,相同 Consumer Group 的每个 Consumer 实例都接收全量消息

@Input 接收消息
public interface InputBinding
{
    @Input("input-common-1")
    SubscribableChannel inputCommon1();

    @Input("input-common-2")
    SubscribableChannel inputCommon2();

    @Input("input-common-3")
    SubscribableChannel inputCommon3();

    @Input("input-tx-1")
    SubscribableChannel inputTx1();
}

通过 @Input 注解,声明了一个名字为 input-common-1 Input Binding。注意,这个名字要和配置文件中的spring.cloud.stream.bindings 配置项对应上。

同时,@Input 注解的方法的返回结果为 SubscribableChannel 类型,可以使用它订阅消息来消费。

public interface SubscribableChannel extends MessageChannel {

 boolean subscribe(MessageHandler handler); // 订阅
 boolean unsubscribe(MessageHandler handler); // 取消订阅

}
ReceiveService 接收消息服务

通过组装 StreamListener ,实现消息接收的逻辑

@Service
public class ReceiveService
{
    @StreamListener("input-common-1")
    public void receiveInput1(@Payload FooMsg receiveMsg)
    {
        System.out.println("input1 receive: " + receiveMsg);
    }

    @StreamListener("input-common-2")
    public void receiveInput2(@Payload FooMsg receiveMsg)
    {
        System.out.println("input2 receive: " + receiveMsg);
    }

    @StreamListener("input-common-3")
    public void receiveInput3(@Payload FooMsg receiveMsg)
    {
        System.out.println("input3 receive: " + receiveMsg);
    }

    @StreamListener("input-tx-1")
    public void receiveTransactionalMsg(String transactionMsg)
    {
        System.out.println("input tx receive transaction msg: " + transactionMsg);
    }

}

在方法上,添加 @StreamListener 注解,声明对应的 Input Binding。

因为消费的消息是 POJO 类型,所以需要添加 @Payload 注解,声明需要进行反序列化成 POJO 对象。

Application 入口

启动应用。代码如下:

@SpringBootApplication
@EnableBinding({InputBinding.class})
public class RocketMQConsumerApplication
{
    public static void main(String[] args)
    {
        SpringApplication.run(RocketMQConsumerApplication.class, args);
    }
}

使用 @EnableBinding 注解,声明指定接口开启 Binding 功能,扫描其 @Input@Output 注解

测试单集群多实例的场景

  • 执行 ProducerApplication,启动生产者的实例
  • 执行 RocketMQConsumerApplication,启动消费者的实例

之后,请求 http://localhost:28081/produce/send1?msg=发送短信-0248 接口三次,发送三条消息。此时在 IDEA 控制台看到消费者打印日志如下:

[onMessage][input-common-2 线程编号:99 消息内容:FooMsg(id=-1996543838, bar=发送短信-0248)] 
[onMessage][input-common-3 线程编号:98 消息内容:FooMsg(id=-1996543838, bar=发送短信-0248)] 
[onMessage][input-common-1 线程编号:97 消息内容:FooMsg(id=-1996543838, bar=发送短信-0248)] 

符合预期。从日志可以看出,每条消息被同一个分组仅被消费一次

定时消息

定时消息,是指消息发到 Broker 后,不能立刻被 Consumer 消费,要等待特定的时间后才能被消费

RocketMQ 暂时不支持任意的时间精度的延迟,而是固化了 18 个延迟级别。如下表格:

延迟级别时间延迟级别时间延迟级别时间
11s73m139m
25s84m1410m
310s95m1520m
430s106m1630m
51m117m171h
62m128m182h

消费重试

不过要注意,只有 集群消费 模式下,才有消息重试

RocketMQ 提供消费重试的机制。在消息消费失败的时候,RocketMQ 会通过消费重试机制,重新投递该消息给 Consumer ,让 Consumer 有机会重新消费消息,实现消费成功。

当然,RocketMQ 并不会无限重新投递消息给 Consumer 重新消费,而是在默认情况下,达到 16 次重试次数时,Consumer 还是消费失败时,该消息就会进入到死信队列

max-attempts 次数

因为 Spring Cloud Stream 提供的重试间隔,是通过 sleep 实现,会占掉当前线程,影响 Consumer 的消费速度,所以这里并不推荐使用,因此设置 max-attempts 配置项为 1,禁用 Spring Cloud Stream 提供的重试功能,使用 RocketMQ 提供的重试功能。

delay-level-when-next-consume 策略

  • -1:不重复,直接放入死信队列
  • 0:RocketMQ Broker 控制重试策略
  • >0:RocketMQ Consumer 控制重试策略

每条消息的失败重试,是有一定的间隔时间。第一次重试消费按照延迟级别为 3 开始。所以,默认为 16 次重试消费,也非常好理解,毕竟延迟级别最高为 18 呀。

消费异常处理机制

如果异常处理方法成功,没有重新抛出异常,会认定为该消息被消费成功,所以就不会进行消费重试。

在 Spring Cloud Stream 中,提供了通用的消费异常处理机制,可以拦截到消费者消费消息时发生的异常,进行自定义的处理逻辑。

两种方式来实现异常处理:

  • 局部的异常处理:通过订阅指定错误 Channel - <destination>.<group>.errors
  • 全局的异常处理:通过订阅全局错误 Channel - errorChannel

消费消息发生异常时,会发送错误消息 ErrorMessage 到对应的错误 Channel 中。同时,所有错误 Channel 都桥接到了 Spring Integration 定义的全局错误 Channel。

    //<destination>.<group>.errors
    //局部错误
    @ServiceActivator(inputChannel = "topic-common-01.group-common-3.errors")
    public void handleError(ErrorMessage errorMessage)
    {
        System.out.printf("[handleError][payload:%s] %n", ExceptionUtils.getRootCauseMessage(errorMessage.getPayload()));
        System.out.printf("[handleError][originalMessage:%s] %n", errorMessage.getOriginalMessage());
        System.out.printf("[handleError][headers:%s] %n", errorMessage.getHeaders());
    }
    // errorChannel
    // 全局错误
    @StreamListener(IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME)
    public void globalHandleError(ErrorMessage errorMessage)
    {
        System.out.printf("[globalHandleError][payload:%s] %n",
                          ExceptionUtils.getRootCauseMessage(errorMessage.getPayload()));
        System.out.printf("[globalHandleError][originalMessage:%s] %n", errorMessage.getOriginalMessage());
        System.out.printf("[globalHandleError][headers:%s] %n", errorMessage.getHeaders());
    }

广播消息

广播消费模式下,相同 Consumer Group 的每个 Consumer 实例都接收全量的消息。

例如说,我们基于 WebSocket 实现了 IM 聊天,在我们给用户主动发送消息时,因为我们不知道用户连接的是哪个提供 WebSocket 的应用,所以可以通过 RocketMQ 广播消费,每个应用判断当前用户是否是和自己提供的 WebSocket 服务连接,如果是,则推送消息给用户。

设置 broadcasting 配置项为 true

顺序消息

RocketMQ 提供了两种顺序级别:

  • 普通顺序消息:Producer 将相关联的消息发送到相同的消息队列
  • 完全严格顺序:在【普通顺序消息】的基础上,Consumer 严格顺序消费

消息有序,指的是一类消息消费时,能按照发送的顺序来消费。例如:一个订单产生了三条消息分别是订单创建、订单付款、订单完成。消费时要按照这个顺序消费才能有意义,但是同时订单之间是可以并行消费的。RocketMQ 可以严格的保证消息有序。

分区顺序就是普通顺序消息,全局顺序就是完全严格顺序

  • 全局顺序:对于指定的一个 Topic,所有消息按照严格的先入先出(FIFO)的顺序进行发布和消费。适用场景:性能要求不高,所有的消息严格按照 FIFO 原则进行消息发布和消费的场景
  • 分区顺序:对于指定的一个 Topic,所有消息根据 Sharding key 进行区块分区。 同一个分区内的消息按照严格的 FIFO 顺序进行发布和消费。Sharding key 是顺序消息中用来区分不同分区的关键字段,和普通消息的 Key 是完全不同的概念。适用场景:性能要求高,以 Sharding key 作为分区字段,在同一个区块中严格的按照 FIFO 原则进行消息发布和消费的场景

分区顺序:

  • 生产者

    添加 partition-key-expression 配置项,设置 Producer 发送顺序消息的 Sharding key

    sync: true 是否同步发送消息,默认为 false 异步

    server:
      port: 28081
    
    spring:
      application:
        name: rocketmq-produce
    
      cloud:
        stream:
          # Spring Cloud Stream 配置项,对应 BindingProperties Map
          bindings:
            output-common:
              #RocketMQ Topic
              destination: topic-common-01
              content-type: application/json
    
              # Producer 配置项,对应 ProducerProperties 类
              producer:
                # 分区 key 表达式。该表达式基于 Spring EL,从消息中获得分区 key
                partition-key-expression: payload['id']
    
          # Spring Cloud Stream RocketMQ 配置项
          rocketmq:
            # RocketMQ Binder 配置项,对应 RocketMQBinderConfigurationProperties 类
            binder:
              name-server: 192.168.123.22:9876
    
            # RocketMQ 自定义 Binding 配置项,对应 RocketMQBindingProperties Map
            bindings:
              output-common:
                # RocketMQ Producer 配置项,对应 RocketMQProducerProperties 类
                producer:
                  #生产者分组
                  group: group-common
                  #同步发送消息
                  sync: true
    
  • 消费者

    添加 orderly 配置项,设置 Consumer 顺序消费消息

    server:
      # 随机端口,方便启动多个消费者
      port: ${random.int[10000,19999]}
    
    spring:
      application:
        name: rocketmq-consume
    
      cloud:
        # Spring Cloud Stream 配置项,对应 BindingServiceProperties 类
        stream:
          # Binding 配置项,对应 BindingProperties Map
          bindings:
            input-common-1:
              #重试次数
              max-attempts: 1
              # 目的地。这里使用 RocketMQ Topic
              destination: topic-common-01
              content-type: application/json
              ## 消费者分组, 命名规则:group+topic名+xx
              group: group-common-1
    
          # Spring Cloud Stream RocketMQ 配置项
          rocketmq:
            binder:
              name-server: 192.168.123.22:9876
    
            bindings:
              input-common-1:
                # RocketMQ Consumer 配置项
                consumer:
                  # 顺序接收消息
                  orderly: true
    

消息过滤

RocketMQ 提供了两种方式给 Consumer 进行消息的过滤:

  • 基于 Tag 过滤

    标签(Tag):为消息设置的标志,用于同一主题下区分不同类型的消息。来自同一业务单元的消息,可以根据不同业务目的在同一主题下设置不同标签。标签能够有效地保持代码的清晰度和连贯性,并优化 RocketMQ 提供的查询系统。消费者可以根据 Tag 实现对不同子主题的不同消费逻辑,实现更好的扩展性

  • 基于 SQL92 过滤,示例:https://www.jianshu.com/p/5b13868f4451

Tag 过滤比较常见,需要设置如下:

  • 生产者

    发送带 tag 的消息,如:

    public <T> boolean sendObject(T msg, String tag) throws Exception
    {
        Message<T> message = MessageBuilder.withPayload(msg)
                .setHeader(MessageConst.PROPERTY_TAGS, tag)
                .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON)
                .build();
    
        return source.sendCommon().send(message);
    }
    
  • 消费者

    订阅 tag 过滤的消息,如:

    server:
      # 随机端口,方便启动多个消费者
      port: ${random.int[10000,19999]}
    
    spring:
      application:
        name: rocketmq-consume
    
      cloud:
        # Spring Cloud Stream 配置项,对应 BindingServiceProperties 类
        stream:
          # Binding 配置项,对应 BindingProperties Map
          bindings:
            input-common-3:
              destination: topic-common-01
              content-type: application/json
              consumer:
                concurrency: 20
              group: group-common-3
    
          # Spring Cloud Stream RocketMQ 配置项
          rocketmq:
            binder:
              name-server: 192.168.123.22:9876
    
            bindings:
              input-common-3:
                consumer:
                  # 基于 Tag 订阅,多个 Tag 使用 || 分隔,默认为空
                  tags: tagObj
    

事务消息

在分布式消息队列中,目前唯一提供完整的事务消息的,只有 RocketMQ 。关于这一点,还是可以鼓吹下的。

考虑一个极端的情况,在本地数据库事务已经提交的时时候,如果因为网络原因,又或者崩溃等等意外,导致事务消息没有被 commit ,最终导致这条事务消息丢失,分布式事务出现问题。

相比来说,RocketMQ 提供事务回查机制,如果应用超过一定时长未 commit 或 rollback 这条事务消息,RocketMQ 会主动回查应用,询问这条事务消息是 commit 还是 rollback ,从而实现事务消息的状态最终能够被 commit 或是 rollback ,达到最终事务的一致性。

配置选项

RocketMQ Binder Properties

  • 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。Default: null

  • 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

RocketMQ Provider Properties

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

  • enable

    是否启用 Producer。默认值: true

  • group

    Producer group name。默认值: empty

  • maxMessageSize

    消息发送的最大字节数。默认值: 8249344

  • transactional

    是否发送事务消息。默认值: false

  • sync

    是否使用同步得方式发送消息。默认值: false

  • vipChannelEnabled

    是否在 Vip Channel 上发送消息。默认值: true

  • sendMessageTimeout

    发送消息的超时时间(毫秒)。默认值: 3000

  • compressMessageBodyThreshold

    消息体压缩阀值(当消息体超过 4k 的时候会被压缩)。默认值: 4096

  • retryTimesWhenSendFailed

    在同步发送消息的模式下,消息发送失败的重试次数。默认值: 2

  • retryTimesWhenSendAsyncFailed

    在异步发送消息的模式下,消息发送失败的重试次数。默认值: 2

  • retryNextServer

    消息发送失败的情况下是否重试其它的 broker。默认值: false

RocketMQ Consumer Properties

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

  • enable

    是否启用 Consumer。默认值: true.

  • tags

    Consumer 基于 TAGS 订阅,多个 tag 以 || 分割。默认值: empty.

  • sql

    Consumer 基于 SQL 订阅。默认值: empty.

  • broadcasting

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

  • orderly

    Consumer 是否同步消费消息模式。默认值: false.

  • delayLevelWhenNextConsume

    异步消费消息模式下消费失败重试策略:-1,不重复,直接放入死信队列0,broker 控制重试策略>0,client 控制重试策略默认值: 0.

  • suspendCurrentQueueTimeMillis

    同步消费消息模式下消费失败后再次消费的时间间隔。默认值: 1000.

参考

RocketMQ-Docker安装

Spring Cloud Alibaba RocketMQ

RocketMQ Example

RocketMQ 与 Spring Cloud Stream整合

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Spring Cloud Stream 是 Spring Cloud 生态系统中的一部分,它提供了一种简单且可扩展的方式来构建消息驱动的微服务应用程序。而 RocketMQ 是一款开源的分布式消息中间件,它具有高可靠、高吞吐量、高可扩展性等特点。在 Spring Cloud Stream 中,我们可以通过集成 RocketMQ实现消息驱动的微服务应用程序。 下面是 Spring Cloud Stream 集成 RocketMQ 的详细文档: 1. 添加依赖 首先,我们需要添加 Spring Cloud Stream 和 RocketMQ 的相关依赖。在 pom.xml 文件中添加以下依赖: ``` <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-stream</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-stream-binder-rocketmq</artifactId> </dependency> <dependency> <groupId>org.apache.rocketmq</groupId> <artifactId>rocketmq-spring-boot-starter</artifactId> <version>2.2.0</version> </dependency> ``` 2. 配置 RocketMQ 在 application.properties 文件中添加 RocketMQ 的相关配置,例如: ``` spring.cloud.stream.rocketmq.binder.namesrv-addr=127.0.0.1:9876 spring.cloud.stream.rocketmq.binder.group=rocketmq-group rocketmq.name-server=127.0.0.1:9876 rocketmq.producer.group=rocketmq-producer-group rocketmq.consumer.group=rocketmq-consumer-group ``` 3. 定义消息通道 在 Spring Cloud Stream 中,消息是通过消息通道来传递的。我们需要定义输入通道和输出通道,例如: ``` public interface MyChannel { String INPUT = "my_input"; String OUTPUT = "my_output"; @Input(INPUT) SubscribableChannel input(); @Output(OUTPUT) MessageChannel output(); } ``` 4. 发送消息 我们可以通过注入 MessageChannel 来发送消息,例如: ``` @Autowired @Qualifier(MyChannel.OUTPUT) private MessageChannel myOutput; public void sendMessage(String message) { myOutput.send(MessageBuilder.withPayload(message).build()); } ``` 5. 接收消息 我们可以通过注入 SubscribableChannel 来接收消息,例如: ``` @StreamListener(MyChannel.INPUT) public void handleMessage(Message<String> message) { log.info("Received message: {}", message.getPayload()); } ``` 6. 集成 RocketMQ 消费者 我们也可以通过集成 RocketMQ 的消费者来接收消息,例如: ``` @Slf4j @Component @RocketMQMessageListener(consumerGroup = "${rocketmq.consumer.group}", topic = MyChannel.INPUT) public class MyRocketMQConsumer implements RocketMQListener<String> { @Override public void onMessage(String message) { log.info("Received message: {}", message); } } ``` 7. 集成 RocketMQ 生产者 我们也可以通过集成 RocketMQ 的生产者来发送消息,例如: ``` @Slf4j @Component public class MyRocketMQProducer { @Autowired private RocketMQTemplate rocketMQTemplate; public void sendMessage(String message) { rocketMQTemplate.convertAndSend(MyChannel.OUTPUT, message); } } ``` 以上就是 Spring Cloud Stream 集成 RocketMQ 的详细文档。通过这种方式,我们可以快速构建消息驱动的微服务应用程序,并且具有高可靠、高吞吐量、高可扩展性等特点。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

郎涯技术

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值