消费者通过用户属性进行过滤
生产者在发送消息的时候可以通过Message的putUserProperty()
放Message中放一些用户自定义属性,比如下面这样。
@Test
public void testFilterSend() throws Exception {
DefaultMQProducer producer = new DefaultMQProducer("group1");
producer.setNamesrvAddr(this.nameServer);
producer.start();
String topic = "topic1";
String tag = "tag6";
for (int i=0; i<1000; i++) {
Message message = new Message(topic, tag, String.valueOf(i).getBytes());
message.putUserProperty("abc", String.valueOf(i));
producer.send(message);
}
producer.shutdown();
}
上面代码发送的消息都包含了一个用户自定义属性abc,其值对应一个数字。在之前的示例中消费者在订阅消息时都是通过Topic+Tag来订阅的。其实消费者也支持通过Topic+用户自定义属性来订阅。用户自定义属性需要基于SQL92标准表示为一个表达式,比如abc > 300 and abc <500
等。RocketMQ默认是不支持通过用户自定义属性来进行消息过滤的,如果需要启用该机制,需要在Broker的broker.conf文件中加上enablePropertyFilter=true
。而且只有Push类型的Consumer支持使用自定义属性过滤。下面代码中消费者在进行消息订阅时就基于SQL92标准提供了一个消息过滤的表达式。
@Test
public void testFilterConsume() throws Exception {
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("group1");
consumer.setNamesrvAddr(this.nameServer);
//默认是不支持通过sql92过滤的,需要在broker.conf中指定enablePropertyFilter=true。
consumer.subscribe("topic1", MessageSelector.bySql("abc > 300 and abc between 250 and 381 "));
consumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
System.out.println("消费消息:" + msgs.get(0).getUserProperty("abc"));
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
consumer.start();
TimeUnit.SECONDS.sleep(30);
consumer.shutdown();
}
通过用户自定义属性来过滤消息的好处是表达式中可以同时包含多个条件,包括多个自定义属性。而传统的通过Tag来过滤的有一个缺陷是一条消息只能属于一个Tag。具体使用何种方式读者朋友可以根据实际业务需要进行选择。
RocketMQ只实现了一些基础的语法,支持
=、>、<、>=、<=、between and、<>、in、is null、is not null、and、or、not
。字符串需要使用单引号包起来。
(注:本文是基于RocketMQ4.5.0所写)