RocketMQ消息过滤

RocketMQ分布式消息队列的消息过滤方式有别于其它MQ中间件,是在Consumer端订阅消息时再做消息过滤的。
RocketMQ这么做是在于其Producer端写入消息和Consumer端订阅消息采用分离存储的机制来实现的,Consumer端订阅消息是需要通过ConsumeQueue这个消息消费的逻辑队列拿到一个索引,然后再从CommitLog里面读取真正的消息实体内容,所以说到底也是还绕不开其存储结构。
其ConsumeQueue的存储结构如下,可以看到其中有8个字节存储的Message Tag的哈希值,基于Tag的消息过滤正式基于这个字段值的。


image.png

主要支持如下2种的过滤方式
(1) Tag过滤方式:Consumer端在订阅消息时除了指定Topic还可以指定TAG,如果一个消息有多个TAG,可以用||分隔。

  1. Consumer端会将这个订阅请求构建成一个 SubscriptionData,发送一个Pull消息的请求给Broker端。
  2. Broker端从RocketMQ的文件存储层—Store读取数据之前,会用这些数据先构建一个MessageFilter,然后传给Store。 3. Store从 ConsumeQueue读取到一条记录后,会用它记录的消息tag hash值去做过滤。
  3. 在服务端只是根据hashcode进行判断,无法精确对tag原始字符串进行过滤,在消息消费端拉取到消息后,还需要对消息的原始tag字符串进行比对,如果不同,则丢弃该消息,不进行消息消费。
    (2) SQL92的过滤方式:
    仅对push的消费者起作用。
    Tag方式虽然效率高,但是支持的过滤逻辑比较简单。
    SQL表达式可以更加灵活的支持复杂过滤逻辑,这种方式的大致做法和上面的Tag过滤方式一样,只是在Store层的具体过滤过程不太一样
    真正的 SQL expression 的构建和执行由rocketmq-filter模块负责的。
    每次过滤都去执行SQL表达式会影响效率,所以RocketMQ使用了BloomFilter避免了每次都去执行。
    SQL92的表达式上下文为消息的属性。


    image.png

    conf/broker.conf


    image.png

    image.png

    首先需要开启支持SQL92的特性,然后重启broker:
mqbroker -n localhost:9876 -c /opt/rocket/conf/broker.conf 1

RocketMQ仅定义了几种基本的语法,用户可以扩展:

  1. 数字比较: >, >=, <, <=, BETWEEN, =
  2. 字符串比较: =, <>, IN; IS NULL或者IS NOT NULL;
  3. 逻辑比较: AND, OR, NOT;
  4. Constant types are: 数字如:123, 3.1415; 字符串如:'abc',必须是单引号引起来 NULL,特殊常量 布尔型如:TRUE or FALSE;


    image.png

    image.png

    image.png

    (3) Filter Server方式。这是一种比SQL表达式更灵活的过滤方式,允许用户自定义Java函数,根据Java函数的逻辑对消息进行过滤。
    要使用Filter Server,首先要在启动Broker前在配置文件里加上 filterServer-Nums=3 这样的配置,Broker在启动的时候,就会在本机启动3个Filter Server进程。Filter Server类似一个RocketMQ的Consumer进程,它从本机Broker获取消息,然后根据用户上传过来的Java函数进行过滤,过滤后的消息再传给远端的Consumer。
    这种方式会占用很多Broker机器的CPU资源,要根据实际情况谨慎使用。上传的java代码也要经过检查,不能有申请大内存、创建线程等这样的操作,否则容易造成Broker服务器宕机。

你可能感兴趣的:(RocketMQ消息过滤)