从图中可以看出,如果使用了类模式过滤,Consumer 不是直接从Broker拉取,而是从FilterServer上拉取。那么问题来了,FilterServer 是什么、Consume 如何与 FilterServer 打交道。
我们知道,一个客户端,一个专门的消息拉取线程(PullMessageService)专门负责拉取消息,多种过滤模式公用一套消息拉取机制【消息队列负载机制】,那 ClassFilter 模式是如何工作呢?首先,ClassFilter 模式,顾名思义就是消费端可以上传一个Class类文件到 FilterServer, 然后 FilterServer 从 Broker 拉取消息,执行过滤逻辑然后再返回给Consumer。
ClassFilter模式过滤机制,本文从如下三个方面展开。
1)ClassFilter注册(消费端如何提交自己的消息过滤实现类、以及消费订阅信息注册)。
2)消费端如何路由到FilterServer上拉取消息。
3)FilterServer消息拉取与消息消费。
2.1 ClassFilter模式 消息过滤类注册机制
DefaultMQPushConsumerImpl#subscribe
public void subscribe(String topic, String fullClassName, String filterClassSource) throws MQClientException { // @1
try {
SubscriptionData subscriptionData = FilterAPI.buildSubscriptionData(this.defaultMQPushConsumer.getConsumerGroup(),
topic, “*”);
subscriptionData.setSubString(fullClassName);
subscriptionData.setClassFilterMode(true); // @2
subscriptionData.setFilterClassSource(filterClassSource);
this.rebalanceImpl.getSubscriptionInner().put(topic, subscriptionData); // @3
if (this.mQClientFactory != null) {
this.mQClientFactory.sendHeartbeatToAllBrokerWithLock(); // @4
}
} catch (Exception e) {
throw new MQClientException(“subscription exception”, e);
}
}
代码@1:topic : 主题,fullClassName : 过滤类全类路径名,filterClassSource: 过滤类内容。
代码@2:设置 classFilterMode 为 true,表示类过滤机制。
代码@3:将该主题的订阅信息放入到 RebalanceImp l对象中,一个消费者各自维护一个 RebalanceImpl 对象,用于创建消息拉取任务。
代码@4:sendHeartbeatToAllBrokerWithLock,关键,发送心跳到所有Broker。
MQClientInstance#sendHeartbeatToAllBrokerWithLock
重点关注MQClientInstance#uploadFilterClassSource方法:
继续进入MQClientInstance#uploadFilterClassToAllFilterServer方法。
private void uploadFilterClassToAllFilterServer(final String consumerGroup, f