消費者通過用戶屬性進行過濾
生產者在發送消息的時候可以通過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所寫)