RocketMQ 执行过滤是在 Broker 端,Broker 所在的机器会启动多个 FilterServer 过滤进程;Consumer 启动后,会向 FilterServer 上传一个过滤的 Java 类;Consumer 从 FilterServer 拉消息,FilterServer 将请求转发给 Broker,FilterServer 从 Broker 收到消息后,按照 Consumer 上传的 Java 过滤程序做过滤,过滤完成后返回给 Consumer。这种过滤方法可以节省网络流量,但是增加了 Broker 的负担
首先我们需要在rocketmq 的我们需要在broker-*.properties文件里添加一句话filterServerNums=1
生产者代码:
public class FilterProducer {
public static void main(String[] args) throws MQClientException {
DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName");
producer.setNamesrvAddr("192.168.1.244:9876;192.168.1.245:9876;192.168.1.242:9876;192.168.1.243:9876");
producer.start();
try {
for (int i = 0; i < 100; i++) {
Message msg = new Message("TopicFilter7",// topic
"TagA",// tag
("Hello MetaQ").getBytes());// body
//这个属性作为过滤的条件
msg.putUserProperty("SequenceId", String.valueOf(i));
SendResult sendResult = producer.send(msg);
System.out.println(sendResult+","+String.valueOf(i));
Thread.sleep(100);
}
}catch (Exception e) {
e.printStackTrace();
}
producer.shutdown();
}
消费者代码:
public class FilterConsumer {
public static void main(String[] args) throws InterruptedException,
MQClientException {
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(
"ConsumerGroupNamecc4");
consumer.setNamesrvAddr("192.168.1.244:9876;192.168.1.245:9876;192.168.1.242:9876;192.168.1.243:9876");
// 使用Java代码,在服务器做消息过滤
String filterCode = MixAll.file2String("D:/Workspaces/rocket-simple/src/main/java/com/sun/activemq/filter/MessageFilterImpl.java");
System.out.println(filterCode);
//有了filter不用指定tag了 其实tag也可以作为过滤
consumer.subscribe("TopicFilter7",
"com.sun.activemq.filter.MessageFilterImpl", filterCode);
consumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(
List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
for(MessageExt mext : msgs) {
try {
System.out.println("消费了一条消息:"+new String(mext.getBody(),"utf-8")+mext.getUserProperty("SequenceId"));
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
//消费失败告诉mq重新发送继续消费
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
}
}
/*
* 告诉mq消费成功
*/
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
/**
* Consumer对象在使用之前必须要调用start初始化,初始化一次即可<br>
*/
consumer.start();
System.out.println("Consumer Started.");
}
}
过滤器:
package com.sun.activemq.filter;
import com.alibaba.rocketmq.common.filter.MessageFilter;
import com.alibaba.rocketmq.common.message.MessageExt;
public class MessageFilterImpl implements MessageFilter {
@Override
public boolean match(MessageExt msg) {
String property = msg.getUserProperty("SequenceId");
System.out.println(property);
if (property != null) {
int id = Integer.parseInt(property);
if((id % 2) == 0) {
return true;
}
}
return false;
}
}
先启动消费者 ,再启动生产者,打印结果如下:
生产者打印部分结果:
消费者打印部分结果: