消息中间件RocketMQ的过滤消息

在RocketMQ中,TAG是一个简单而有用的设计,其可以来选择您想要的消息。例如:

DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("defultGroup");
consumer.subscribe("Topic", "TagA || TagB || TagC");

消费者将接收包含 TagA 或 TagB 或 TagC 的消息。但是限制是一个消息只能有一个标签,这对于复杂的场景可能不起作用。

在这种情况下,可以使用SQL92表达式筛选消息。SQL92特性可以通过发送消息时的属性来进行计算。在RocketMQ定义的语法下,可以实现一些简单的逻辑。下面是一个例子:

------------
| message  |
|----------|  a > 5 AND b = 'abc'
| a = 10   |  --------------------> Gotten
| b = 'abc'|
| c = true |
------------
------------
| message  |
|----------|   a > 5 AND b = 'abc'
| a = 1    |  --------------------> Missed
| b = 'abc'|
| c = true |
------------

SQL92基本语法

RocketMQ只定义了一些基本语法来支持这个特性。你也可以很容易地扩展它。

  • 数值比较,比如:>,>=,<,<=,BETWEEN,=;
  • 字符比较,比如:=,<>,IN;
  • IS NULL 或者 IS NOT NULL;
  • 逻辑符号 AND,OR,NOT;

常量支持类型为:

  • 数值,比如:123,3.1415;
  • 字符,比如:‘abc’,必须用单引号包裹起来;
  • NULL,特殊的常量
  • 布尔值,TRUEFALSE

使用限制

只有push模式的消费者支持使用 SQL92 进行消息过滤,接口信息如下:

public void subscribe(finalString topic, final MessageSelector messageSelector)

示例

过滤消息的生产者-Producer

public static void main(String[] args) throws MQClientException, RemotingException, InterruptedException, MQBrokerException {
	// 创建 producer 实例,并设置生产者组名
	DefaultMQProducer producer = new DefaultMQProducer("filterGroup");
	// 设置 NameServer 地址
	producer.setNamesrvAddr("127.0.0.1:9876");
	// 启动生产者
	producer.start();
	for (int i = 0; i < 10; i++) {
		Message message = new Message("filterTopic",  "TagA", ("Hello filter message-" + i).getBytes());
		// 发送消息时,通过`putUserProperty`来设置消息的属性
		message.putUserProperty("num", String.valueOf(i));

		SendResult sendResult = producer.send(message);

		System.out.println(String.format("SendResult status:%s, queueId:%d",
				sendResult.getSendStatus(),
				sendResult.getMessageQueue().getQueueId()));
	}
	// 关闭生产者
	producer.shutdown();
}

生成消息的时候,message.putUserProperty("num", String.valueOf(i)); 设置一个属性,这个属性在消费的时候会拿来写SQL语句,详情见下方消费示例。

过滤消息的消费者者-Consumer

public static void main(String[] args) throws MQClientException {
	// 实例化消费者,并设置组名
	DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("filterGroup");
	// 设置 NameServer 地址
	consumer.setNamesrvAddr("127.0.0.1:9876");
	// 订阅 Topic
	consumer.subscribe("filterTopic", MessageSelector.bySql("TAGS = 'TagA' and num between 2 and 5"));
	// 注册消息监听者
	consumer.registerMessageListener(new MessageListenerConcurrently() {
		@Override
		public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> messages, ConsumeConcurrentlyContext context) {
			for (MessageExt message : messages) {
				// 打印消息内容
				System.out.println("Receive message[msgBody=" + new String(message.getBody()) + "] ");
			}
			return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
		}
	});
	// 启动消费者
	consumer.start();
}

消息订阅的时候使用了 MessageSelector.bySql(); 表明使用 SQL92 的过滤模式,然后传入的字符串是符合 SQL92 语法的语句。

对消息进行过滤的SQL表达式由2个条件组成:

  • TAGS = ‘TagA’
  • num between 2 and 5

这个“TAGS”是关键字,为了兼容tag过滤,在SQL92过滤中,使用TAGS替代tag,然后“num”是消息生产时 message.putUserProperty("num", String.valueOf(i));设置的属性。

如果我的生产者有多个tag:

String[] tags = new String[] {"TagA", "TagB", "TagC"};
// 依次选择 tag
Message message = new Message("filterTopic",  tags[i % tags.length], ("Hello filter message-" + i).getBytes());
// 发送消息时,通过`putUserProperty`来设置消息的属性
message.putUserProperty("num", String.valueOf(i));

那么消费者可以这样过滤:

// 订阅 Topic
consumer.subscribe("filterTopic", MessageSelector.bySql("TAGS in ('TagA', 'TagB') and num between 2 and 5"));

灵活的使用 SQL 表达式

如果在启动消费者时,出现下面这错误,

Exception in thread "main" org.apache.rocketmq.client.exception.MQClientException: CODE: 1  DESC: The broker does not support consumer to filter message by SQL92
For more information, please visit the url, http://rocketmq.apache.org/docs/faq/

则表示当前broker没有开启过滤支持,需要开启。

如果部署了监控平台,也可以在监控平台上查看有没有开启过滤支持,如下图所示:
在这里插入图片描述

开启 broker 过滤支持,只需要在 broker 的配置文件中增加一项配置即可:

enablePropertyFilter=true

如果有主从,也就是有多个 broker的话,需要在没一个 broker 配置文件里面都加上这句话。

vim /usr/local/rocketmq/conf/2m-2s-sync/broker-a.properties
vim /usr/local/rocketmq/conf/2m-2s-sync/broker-a-s.properties
vim /usr/local/rocketmq/conf/2m-2s-sync/broker-b.properties
vim /usr/local/rocketmq/conf/2m-2s-sync/broker-b-s.properties

最后再重启 broker 就行了。

在监控平台上可以看见开启状态,如下图示:
在这里插入图片描述


技 术 无 他, 唯 有 熟 尔。
知 其 然, 也 知 其 所 以 然。
踏 实 一 些, 不 要 着 急, 你 想 要 的 岁 月 都 会 给 你。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值