学会RocketMQ这一篇就够了

RocketMQ简介

RocketMQ是由阿里捐赠给Apache的一款低延迟、高并发、高可用、高可靠的分布式消息中间件。经历
了淘宝双十一的洗礼。RocketMQ既可为分布式应用系统提供异步解耦和削峰填谷的能力,同时也具备
互联网应用所需的海量消息堆积、高吞吐、可靠重试等特性。

官方文档: https://rocketmq.apache.org/docs/quick-start/

github中文主页:https://github.com/apache/rocketmq/tree/master/docs/cn

核心概念

  • Topic:消息主题,一级消息类型,生产者向其发送消息。
  • Message:生产者向Topic发送并最终传送给消费者的数据消息的载体。
  • 消息属性:生产者可以为消息定义的属性,包含Message Key和Tag。
  • Message Key:消息的业务标识,由消息生产者(Producer)设置,唯一标识某个业务逻辑。
  • Message ID:消息的全局唯一标识,由消息队列RocketMQ系统自动生成,唯一标识某条消息。
  • Tag:消息标签,二级消息类型,用来进一步区分某个Topic下的消息分类
  • Producer:也称为消息发布者,负责生产并发送消息至Topic。
  • Consumer:也称为消息订阅者,负责从Topic接收并消费消息。
  • 分区:即Topic Partition,物理上的概念。每个Topic包含一个或多个分区。
  • 消费位点:每个Topic会有多个分区,每个分区会统计当前消息的总条数,这个称为最大位点
    MaxOffset;分区的起始位置对应的位置叫做起始位点MinOffset。
  • Group:一类生产者或消费者,这类生产者或消费者通常生产或消费同一类消息,且消息发布或订
    阅的逻辑一致。
  • Group ID:Group的标识。
  • 队列:个Topic下会由一到多个队列来存储消息。
  • Exactly-Once投递语义:Exactly-Once投递语义是指发送到消息系统的消息只能被Consumer处理
    且仅处理一次,即使Producer重试消息发送导致某消息重复投递,该消息在Consumer也只被消费
    一次。
  • 集群消费:一个Group ID所标识的所有Consumer平均分摊消费消息。例如某个Topic有9条消息,
    一个Group ID有3个Consumer实例,那么在集群消费模式下每个实例平均分摊,只消费其中的3条
    消息。
  • 广播消费:一个Group ID所标识的所有Consumer都会各自消费某条消息一次。例如某个Topic有9
    条消息,一个Group ID有3个Consumer实例,那么在广播消费模式下每个实例都会各自消费9条消
    息。
  • 定时消息:Producer将消息发送到消息队列RocketMQ服务端,但并不期望这条消息立马投递,而
    是推迟到在当前时间点之后的某一个时间投递到Consumer进行消费,该消息即定时消息。
  • 延时消息:Producer将消息发送到消息队列RocketMQ服务端,但并不期望这条消息立马投递,而
    是延迟一定时间后才投递到Consumer进行消费,该消息即延时消息。
  • 事务消息:RocketMQ提供类似X/Open XA的分布事务功能,通过消息队列RocketMQ的事务消息
    能达到分布式事务的最终一致。
  • 顺序消息:RocketMQ提供的一种按照顺序进行发布和消费的消息类型,分为全局顺序消息和分区
    顺序消息。
  • 全局顺序消息:对于指定的一个Topic,所有消息按照严格的先入先出(FIFO)的顺序进行发布和
    消费。
  • 分区顺序消息:对于指定的一个Topic,所有消息根据Sharding Key进行区块分区。同一个分区内
    的消息按照严格的FIFO顺序进行发布和消费。Sharding Key是顺序消息中用来区分不同分区的关键
    字段,和普通消息的Message Key是完全不同的概念。
  • 消息堆积:Producer已经将消息发送到消息队列RocketMQ的服务端,但由于Consumer消费能力
    有限,未能在短时间内将所有消息正确消费掉,此时在消息队列RocketMQ的服务端保存着未被消
    费的消息,该状态即消息堆积。
  • 消息过滤:Consumer可以根据消息标签(Tag)对消息进行过滤,确保Consumer最终只接收被
    过滤后的消息类型。消息过滤在消息队列RocketMQ的服务端完成。
  • 消息轨迹:在一条消息从Producer发出到Consumer消费处理过程中,由各个相关节点的时间、地
    点等数据汇聚而成的完整链路信息。通过消息轨迹,您能清晰定位消息从Producer发出,经由消息
    队列RocketMQ服务端,投递给Consumer的完整链路,方便定位排查问题。
  • 重置消费位点:以时间轴为坐标,在消息持久化存储的时间范围内(默认3天),重新设置
    Consumer对已订阅的Topic的消费进度,设置完成后Consumer将接收设定时间点之后由
    Producer发送到消息队列RocketMQ服务端的消息。
  • 死信队列:死信队列用于处理无法被正常消费的消息。当一条消息初次消费失败,消息队列
    RocketMQ会自动进行消息重试;达到最大重试次数后,若消费依然失败,则表明Consumer在正
    常情况下无法正确地消费该消息。此时,消息队列RocketMQ不会立刻将消息丢弃,而是将这条消
    息发送到该Consumer对应的特殊队列中。

应用场景

  • 削峰填谷:诸如秒杀、抢红包、企业开门红等大型活动时皆会带来较高的流量脉冲,或因没做相应
    的保护而导致系统超负荷甚至崩溃,或因限制太过导致请求大量失败而影响用户体验,消息队列
    RocketMQ可提供削峰填谷的服务来解决该问题。
  • 异步解耦:交易系统作为淘宝和天猫主站最核心的系统,每笔交易订单数据的产生会引起几百个下
    游业务系统的关注,包括物流、购物车、积分、流计算分析等等,整体业务系统庞大而且复杂,消
    息队列RocketMQ可实现异步通信和应用解耦,确保主站业务的连续性。
  • 顺序收发:细数日常中需要保证顺序的应用场景非常多,例如证券交易过程时间优先原则,交易系
    统中的订单创建、支付、退款等流程,航班中的旅客登机消息处理等等。与先进先出FIFO(First In
    First Out)原理类似,消息队列RocketMQ提供的顺序消息即保证消息FIFO。
  • 分布式事务一致性:交易系统、支付红包等场景需要确保数据的最终一致性,大量引入消息队列
    RocketMQ的分布式事务,既可以实现系统之间的解耦,又可以保证最终的数据一致性。
  • 大数据分析:数据在“流动”中产生价值,传统数据分析大多是基于批量计算模型,而无法做到实时
    的数据分析,利用阿里云消息队列RocketMQ与流式计算引擎相结合,可以很方便的实现业务数据
    的实时分析。
  • 分布式缓存同步:天猫双11大促,各个分会场琳琅满目的商品需要实时感知价格变化,大量并发访
    问数据库导致会场页面响应时间长,集中式缓存因带宽瓶颈,限制了商品变更的访问流量,通过消
    息队列RocketMQ构建分布式缓存,实时通知商品数据的变化

架构设计

在这里插入图片描述
在这里插入图片描述
RocketMQ架构上主要分为四部分,如上图所示:

  • Producer:消息发布的角色,支持分布式集群方式部署。Producer通过MQ的负载均衡模块选择相
    应的Broker集群队列进行消息投递,投递的过程支持快速失败并且低延迟。
  • Consumer:消息消费的角色,支持分布式集群方式部署。支持以push推,pull拉两种模式对消息
    进行消费。同时也支持集群方式和广播方式的消费,它提供实时消息订阅机制,可以满足大多数用
    户的需求。
  • NameServer:NameServer是一个非常简单的Topic路由注册中心,其角色类似Dubbo中的
    zookeeper,支持Broker的动态注册与发现。主要包括两个功能:Broker管理,NameServer接受
    Broker集群的注册信息并且保存下来作为路由信息的基本数据。然后提供心跳检测机制,检查
    Broker是否还存活;路由信息管理,每个NameServer将保存关于Broker集群的整个路由信息和用
    于客户端查询的队列信息。然后Producer和Conumser通过NameServer就可以知道整个Broker集
    群的路由信息,从而进行消息的投递和消费。NameServer通常也是集群的方式部署,各实例间相
    互不进行信息通讯。Broker是向每一台NameServer注册自己的路由信息,所以每一个
    NameServer实例上面都保存一份完整的路由信息。当某个NameServer因某种原因下线了,
    Broker仍然可以向其它NameServer同步其路由信息,Producer,Consumer仍然可以动态感知
    Broker的路由的信息。
  • BrokerServer:Broker主要负责消息的存储、投递和查询以及服务高可用保证,为了实现这些功
    能,Broker包含了以下几个重要子模块。
  1. Remoting Module:整个Broker的实体,负责处理来自clients端的请求。
  2. Client Manager:负责管理客户端(Producer/Consumer)和维护Consumer的Topic订阅信息
  3. Store Service:提供方便简单的API接口处理消息存储到物理硬盘和查询功能。
  4. HA Service:高可用服务,提供Master Broker 和 Slave Broker之间的数据同步功能。
  5. Index Service:根据特定的Message key对投递到Broker的消息进行索引服务,以提供消息
    的快速查询。
    在这里插入图片描述

RocketMQ Server安装

安装教程

SpringBoot整合RocketMQ实现消息发送和接收

项目结构

在这里插入图片描述

第一步:我们新建一个父项目 rocketmq-test ,pom类型,主要是依赖管理,包括版本的管理,以及管
理module子项目

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <packaging>pom</packaging>
    <modules>
        <module>rocketmq-provider</module>
        <module>rocketmq-consumer</module>
    </modules>

    <groupId>org.example</groupId>
    <artifactId>rocketmq-test</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <springboot.version>2.3.2.RELEASE</springboot.version>
        <rocketmq.version>2.2.0</rocketmq.version>
    </properties>

    <dependencyManagement>

        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${springboot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>org.apache.rocketmq</groupId>
                <artifactId>rocketmq-spring-boot-starter</artifactId>
                <version>${rocketmq.version}</version>
            </dependency>
        </dependencies>

    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

第二步:新建消息生产者 rocketmq-provider 子项目

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>rocketmq-test</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>rocketmq-provider</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.rocketmq</groupId>
            <artifactId>rocketmq-spring-boot-starter</artifactId>
        </dependency>
    </dependencies>
</project>

新建项目配置文件 application.yml ,指定name-server,以及producer-group组

server:
  port: 8081
  servlet:
    context-path: /

rocketmq:
  name-server: *.*.*.*:9876
  producer:
    group: producer-demo1

新建消息生产者Service类 ProducerService
SpringBoot给我们提供了 RocketMQTemplate 模板类

package com.suqi.rocketmq;

import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @author Suqi
 * @version 1.0
 * @date 2022/5/11 11:17
 * @desc
 */
@Component("producerService")
public class ProducerService {
    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    /*** 发送简单消息 */
    public void sendMessage() {
        for (int i = 0; i < 10; i++) {
            rocketMQTemplate.convertAndSend("java1234-rocketmq", "rocketmq大爷,你 好!" + i);
        }
    }
}

第三步:新建消息消费者 rocketmq-consumer 子项目

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>rocketmq-test</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>rocketmq-consumer</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.rocketmq</groupId>
            <artifactId>rocketmq-spring-boot-starter</artifactId>
        </dependency>
    </dependencies>
</project>

新建项目配置文件 application.yml ,指定name-server,以及consumer-group组

server:
  port: 8084
  servlet:
    context-path: /

rocketmq:
  name-server: 120.77.39.136:9876
  consumer:
    group: consumer-demo1

新建消息消费者Service类 ConsumerService ,监听消息,消费消息

@RocketMQMessageListener(topic = "java1234-rocketmq", consumerGroup = "${rocketmq.consumer.group}")
@Component
public class ConsumerService implements RocketMQListener<String> {
    @Override
    public void onMessage(String s) {
        System.out.println("收到消息内容:" + s);
    }
}

启动类直接测试发送消息
先启动消费者,再开启生产者

@SpringBootApplication
public class RocketmqTestApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(RocketmqTestApplication.class, args);
        ProducerService producerService = (ProducerService) run.getBean("producerService");
        producerService.sendMessage();
    }
}

在这里插入图片描述
运行测试OK

RocketMQ发送同步消息

发送同步消息是指producer向 broker 发送消息,执行 API 时同步等待, 直到broker 服务器返回发送结
果;
相对异步发送消息,同步会阻塞线程,性能相对差点,但是可靠性高,这种方式得到广泛使用,比如:
短信通知,邮件通知,站内重要信息通知等。
RocketMQTemplate 给我们提供了syncSend方法(有多个重载),来实现发送同步消息;
这里执行完发送同步消息返回执行结果 SendResult ;

 /*** 发送同步消息 */
    public void sendSyncMessage() {
        for (int i = 0; i < 10; i++) {
            SendResult sendResult = rocketMQTemplate.syncSend("java1234-rocketmq", "rocketmq同步消息!" + i);
            System.out.println(sendResult);
        }
    }

RocketMQ发送异步消息

发送异步消息是指producer向 broker 发送消息时指定消息发送成功及发送异常的回调方法,调用 API
后立即返回,producer发送消息线程不阻塞 ,消息发送成功或失败的回调任务在一个新的线程中执行

相对发送同步消息,异步消息性能更高,可靠性略差。适合对响应时间要求高的业务场景。
RocketMQTemplate 给我们提供了asyncSend方法(有多个重载),来实现发送异步消息;

    /*** 发送异步消息 */
    public void sendAsyncMessage() {
        for (int i = 0; i < 10; i++) {
            rocketMQTemplate.asyncSend("java1234-rocketmq", "rocketmg异步消息!" + i, new SendCallback() {
                @Override
                public void onSuccess(SendResult sendResult) {
                    System.out.println("发送成功!");
                }

                @Override
                public void onException(Throwable throwable) {
                    System.out.println("发送失败!");
                }
            });
        }
    }

类似发送同步消息,多了一个SendCallback回调接口参数,实现onSuccess和onException方法,分别
表示异步发送成功和失败;

RocketMQ发送单向消息

发送单向消息是指producer向 broker 发送消息,执行 API 时直接返回,不等待broker 服务器的结果 。
这种方式主要用在不特别关心发送结果的场景,举例:日志发送;
RocketMQTemplate 给我们提供了sendOneWay方法(有多个重载),来实现发送单向消息;

    /*** 发送单向消息 */
    public void sendOneWayMessage() {
        for (int i = 0; i < 10; i++) {
            rocketMQTemplate.sendOneWay("java1234-rocketmq", "rocketmg单向消息!" + i);
        }
    }

RocketMQ消费者广播模式和负载均衡模式

广播模式是每个消费者,都会消费消息;
负载均衡模式是每一个消息只会被某一个消费者消费一次;

我们可以通过 @RocketMQMessageListener 的 messageModel 属性值来设置,
MessageModel.BROADCASTING 是广播模式,
MessageModel.CLUSTERING 是默认集群负载均衡模式

简单理解: 集群负载模式说白了就是 发10条消息,一人个五条对半
广播模式就是 发10条消息,两个消费者都消费10条
在这里插入图片描述

RocketMQ实现顺序消息

rocketmq默认发送的消息是进入多个消息队列,然后消费端多线程并发消费,所以默认情况,不是顺序
消费消息的;
在这里插入图片描述
RocketMQTemplate 给我们提供了SendOrderly方法(有多个重载),来实现发送顺序消息;包括以下:
syncSendOrderly,发送同步顺序消息;
asyncSendOrderly,发送异步顺序消息;
sendOneWayOrderly,发送单向顺序消息;

发送端

hashKey参数,主要用来计算选择队列的,一般可以把订单ID,
产品ID作为参数值;
在这里插入图片描述

消费者端
监听器的consumeMode = ConsumeMode.ORDERLY设置好

@RocketMQMessageListener(topic = "java1234-rocketmq-orderly", consumerGroup = "${rocketmq.consumer.group}", consumeMode = ConsumeMode.ORDERLY)
@Component
public class ConsumerServiceOrderly implements RocketMQListener<String> {
    @Override
    public void onMessage(String s) {
        System.out.println("消费者:收到消息内容:" + s);
    }
}

在这里插入图片描述

RocketMQ实现延迟消息

延迟消息

对于消息中间件来说,producer 将消息发送到mq的服务器上,但并不希望这条消息马上被消费,
而是推迟到当前时间节点之后的某个时间点,再将消息投递到 queue 中让 consumer 进行消费。
延迟消息的使用场景很多,一种比较常见的场景就是在电商系统中,订单创建后,会有一个等待用
户支付的时间窗口,一般为30分钟,30分钟后 customer 会收到这条订单消息,然后程序去订单表中检
查当前这条订单的支付状态,如果是未支付的状态,则自动清理掉,这样就不需要使用定时任务的方式
去处理了。

Rocket的延迟消息

RocketMQ 支持定时的延迟消息,但是不支持任意时间精度,仅支持特定的 level,例如定时 5s,
10s, 1m 等。其中,level=0 级表示不延时,level=1 表示 1 级延时,level=2 表示 2 级延时,以此类

messageDelayLevel=1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h
timeout=3000 代表的是消息发送超时时间

/*** 发送延迟消息 */
    public void sendDelayMessage() {
        rocketMQTemplate.syncSend("java1234-rocketmq", MessageBuilder.withPayload("rocketmq延迟1秒消息").build(), 3000, 1);
        rocketMQTemplate.syncSend("java1234-rocketmq", MessageBuilder.withPayload("rocketmq延迟5秒消息").build(), 3000, 2);
        rocketMQTemplate.syncSend("java1234-rocketmq", MessageBuilder.withPayload("rocketmq延迟10秒消息").build(), 3000, 3);
    }

在这里插入图片描述

RocketMQ实现事务消息

事务消息是RocketMQ提供的非常重要的一个特性,在4.x版本之后开源,可以利用事务消息轻松地实现
分布式事务。

RocketMQ在其消息定义的基础上,对事务消息扩展了两个相关的概念:
Half(Prepare) Message——半消息(预处理消息)
半消息是一种特殊的消息类型,该状态的消息暂时不能被Consumer消费。当一条事务消息被成功投递
到Broker上,但是Broker并没有接收到Producer发出的二次确认时,该事务消息就处于"暂时不可被消
费"状态,该状态的事务消息被称为半消息。

Message Status Check——消息状态回查
由于网络抖动、Producer重启等原因,可能导致Producer向Broker发送的二次确认消息没有成功送
达。如果Broker检测到某条事务消息长时间处于半消息状态,则会主动向Producer端发起回查操作,查
询该事务消息在Producer端的事务状态(Commit 或 Rollback)。可以看出,Message Status Check主要
用来解决分布式事务中的超时问题。

在这里插入图片描述

  1. 应用模块遇到要发送事务消息的场景时,先发送prepare消息给MQ。
  2. prepare消息发送成功后,应用模块执行数据库事务(本地事务)。
  3. 根据数据库事务执行的结果,再返回Commit或Rollback给MQ。
  4. 如果是Commit,MQ把消息下发给Consumer端,如果是Rollback,直接删掉prepare消息。
  5. 第3步的执行结果如果没响应,或是超时的,启动定时任务回查事务状态(最多重试15次,超过了
    默认丢弃此消息),处理结果同第4步。
  6. MQ消费的成功机制由MQ自己保证
    具体实例:
/*** 发送事务消息 */
    public void sendTransactionMessage() { // 构造消息
        Message msg = MessageBuilder.withPayload("rocketmq事务消息-01").build();
        rocketMQTemplate.sendMessageInTransaction("java1234-transaction-rocketmq", msg, null);
    }

    @RocketMQTransactionListener
    class TransactionListenerImpl implements RocketMQLocalTransactionListener {
        @Override
        public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) {
            // ... local transaction process, return bollback, commit or unknown System.out.println("executeLocalTransaction"); return RocketMQLocalTransactionState.UNKNOWN; }@Override public RocketMQLocalTransactionState checkLocalTransaction(Message msg) { // ... check transaction status and return bollback, commit or unknown
            System.out.println("checkLocalTransaction");
            return RocketMQLocalTransactionState.COMMIT;
        }

        @Override
        public RocketMQLocalTransactionState checkLocalTransaction(Message msg) {
            return null;
        }
    }

定义本地事务处理类,实现 RocketMQLocalTransactionListener 接口,以及加上
@RocketMQTransactionListener 注解,这个类似方法的调用是异步的;
executeLocalTransaction 方法,当我们处理完业务后,可以根据业务处理情况,返回事务执行状
态,有 bollback , commit or unknown 三种,分别是回滚事务,提交事务和未知;根据事务消息执行
流程,如果返回bollback,则直接丢弃消息;如果是返回commit,则消费消息;如果是unknow,则继
续等待,然后调用checkLocalTransaction方法,最多重试15次,超过了默认丢弃此消息;
checkLocalTransaction 方法,是当MQ Server未得到MQ发送方应答,或者超时的情况,或者应答是
unknown的情况,调用此方法进行检查确认,返回值和上面的方法一样;

在这里插入图片描述

所以其实核心就是在executeLocalTransaction()方法中写好本地事务逻辑,如果异常就bollback。
如果因为网络问题迟迟不能确定消息, checkLocalTransaction ()方法就会帮我们回查,

RocketMQ过滤消息

RocketMQ提供了TAG和SQL表达式两种消息过滤方式

根据TAG方式过滤消息

消息发送端只能设置一个tag,消息接收端可以设置多个tag。
接收消息端通过 ‘||’ 设置多个tag,如下:tag1 || tag2 || tag3 || …
上实例,生产端发送三个消息,TAG分别是TAG1,TAG2,TAG3

/*** 发送带Tag消息,测试根据Tag过滤消息 */
    public void sendMessageWithTag() {
        // 构造消息1
        Message msg1 = MessageBuilder.withPayload("rocketmq过滤消息测试-TAG01").build();
        // 构造消息2
        Message msg2 = MessageBuilder.withPayload("rocketmq过滤消息测试-TAG02").build();
        // 构造消息3
        Message msg3 = MessageBuilder.withPayload("rocketmq过滤消息测试-TAG03").build();
        rocketMQTemplate.convertAndSend("java1234-filter-rocketmq" + ":" + "TAG1", msg1);
        rocketMQTemplate.convertAndSend("java1234-filter-rocketmq" + ":" + "TAG2", msg2);
        rocketMQTemplate.convertAndSend("java1234-filter-rocketmq" + ":" + "TAG3", msg3);
    }

消费端,通过selectorExpression = “TAG1 || TAG2”,selectorType = SelectorType.TAG,指定需要消
费的TAG

@RocketMQMessageListener(topic = "java1234-filter-rocketmq", consumerGroup = "${rocketmq.consumer.group}", 
        selectorExpression = "TAG1 || TAG2", selectorType = SelectorType.TAG)
@Component
public class ConsumerService implements RocketMQListener<String> {
    @Override
    public void onMessage(String s) {
        System.out.println("消费者:收到消息内容:" + s);
    }
}

结果
在这里插入图片描述

根据SQL表达式过滤消息

SQL表达式方式可以根据发送消息时输入的属性进行一些计算。

RocketMQ的SQL表达式语法 只定义了一些基本的语法功能。
数字比较,如>,>=,<,<=,BETWEEN,=;
字符比较,如:=,<>,IN;
IS NULL or IS NOT NULL;
逻辑运算符:AND, OR, NOT;

常量类型:
数值,如:123, 3.1415;
字符, 如:‘abc’, 必须使用单引号; }@RocketMQMessageListener(topic = “java1234-filter-rocketmq”,consumerGroup =“${rocketmq.consumer.group}” ,selectorExpression = “TAG1 || TAG2”,selectorType = SelectorType.TAG) @Component public class ConsumerService implements RocketMQListener { @Override public void onMessage(String s) { System.out.println(“消费者:收到消息内容:”+s); } }
NULL,特殊常量
Boolean, TRUE or FALSE;

上实例,发送三个消息,分别带上不同的header头信息


    /*** 发送SQL表达式头信息消息,测试根据SQL表达式过滤消息 */
    public void sendMessageWithSQL() {
        // 构造消息1
        Message msg1 = MessageBuilder.withPayload("rocketmq过滤消息测试01").build();
        Map<String, Object> headers = new HashMap<>();
        headers.put("type", "pay");
        headers.put("a", 10);
        rocketMQTemplate.convertAndSend("java1234-filter-rocketmq", msg1, headers);
        // 构造消息2
        Message msg2 = MessageBuilder.withPayload("rocketmq过滤消息测试02").build();
        Map<String, Object> headers2 = new HashMap<>();
        headers2.put("type", "store");
        headers2.put("a", 4);
        rocketMQTemplate.convertAndSend("java1234-filter-rocketmq", msg2, headers2);
        // 构造消息3
        Message msg3 = MessageBuilder.withPayload("rocketmq过滤消息测试03").build();
        Map<String, Object> headers3 = new HashMap<>();
        headers3.put("type", "user");
        headers3.put("a", 7);
        rocketMQTemplate.convertAndSend("java1234-filter-rocketmq", msg3, headers3);
    }    

消费者端,selectorExpression = “type=‘user’ or a <7”,selectorType = SelectorType.SQL92 ,指定
selectorType 以及设置表达式selectorExpression

@RocketMQMessageListener(topic = "java1234-filter-rocketmq", consumerGroup = "${rocketmq.consumer.group}",
        selectorExpression = "type='user' or a <7", selectorType = SelectorType.SQL92)
@Component
public class ConsumerService implements RocketMQListener<String> {
    @Override
    public void onMessage(String s) {
        System.out.println("消费者:收到消息内容:" + s);
    }
}

默认不支持SQL表达式,启动报错
在这里插入图片描述

找到 broker.conf 配置文件
在这里插入图片描述
加上

enablePropertyFilter=true

重启borker即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值