消息过滤

消息过滤的背景

  从一个特定的队列或主题接收消息时,您可能会希望由更多的选择。如果没有消息过滤技术,主题订阅者就会接收发布到该主题的每一条消息,而队列接收者也会继续接收下一条消息,并不考虑这些消息的内容或类型。

  就主题订阅者来说,它可能要强制处理很多不必要和不想要的消息,这通常导致:编写定制Java代码来人工过滤不想要的消息。

  针对队列的消息过滤更有趣,因为它和主题不同:一旦一条消息被一个队列接收者消费以后,对其他所有接收者来说,该队列就不再可用。这意味着,如果一个队列接收者消费了一条消息,并决定它不应该处理这条消息,此时已经为时太晚了:该消息已经被接收并从该队列中删除。

消息过滤器

  一旦使用了消息选择器,消费者就只会接收能够通过过滤器的那些消息。消息选择器使用消息属性和消息头作为条件表达式的准则。请注意:消息选择器无法参考消息体内的数据;它只能使用消息头和消息属性。这就意味着,MessageProducer必须向消息属性域中添加合适的数据,使得那些消息可以进行逻辑过滤。

  消息选择器是基于SQL-92条件表达式语法的一个子集。消息选择器由三个元素组成:标识符、常量和比较运算符。

标识符

  标识符是表达式中被比较的那一部分。标识符必须来自消息头,或者是来自消息属性。例如,下面表达式中的标识符是Symbol、Side、Shares和JMSPriority:

Symbol = ‘ABC‘ AND Side = ‘BUY‘ AND Shares <=1000.0 AND JMSPriority > 4

  标识符可以使任何应用程序定义的属性、JMS定义的属性或提供者定义的属性,也可以是若干JMS消息头之一。在刚才的例子中,Symbol、Side和Shares来自消息中的应用程序属性。而JMSPriority则来自于消息头。标识符是区分大小写的,而且它必须和属性或JMS消息头名称精确匹配。

  可以用作标识符的JMS消息头包括下列几种:

  • JMSDeliveryMode
  • JMSPriority
  • JMSMessageID
  • JMSTimestamp
  • JMSCorrelationID
  • JMSType

  JMSDestination和JMSReplyTo消息头无法用作标识符,因为它们对应的值是Destination对象,这些对象的实际值是私有的,因而也是未定义的(undefined)。

  JMSRedelivered值可以在传送期间修改,因此不许子啊选择器中使用。

常量

  常量是使用硬编码方式写入消息选择器的表达式值。在下面的消息选择器中,所有的常量有‘ABC‘、‘SELL‘和1000:

Symbol = ‘ABC‘ AND Side = ‘BUY‘ AND Shares <=1000.0

  String常量使用单引号括起来。如果String常量中含有撇号或单引号,则使用两个单引号表示(例如,‘Smith‘‘s‘)。

  数值常量使用精确数值表示法(+22、30、-54121)、近似数值表示法(-33.22、100.00、+7.0)或科学计数法(-9E4、3.4E6)来表示。

  Boolean常量用true或false来表示

比较运算符

  比较运算符对标识符和boolean表达式中的常量进行比较,这个boolean表达式的值为true或false。使用逻辑运算符AND和OR,可以将比较运算符组合成更复杂的表达式。消息选择器使用的比较运算符包括:

  • 算术比较运算符
  • LIKE运算符
  • BETWEEN运算符
  • IN运算符
  • NOT运算符
  • IS NULL运算符

  消息选择器表达式从左到右赋值:    

Symbol = ‘ABC‘ AND Side = ‘BUY‘ AND Shares <=1000.0

  在这个例子中,表达式在求值时,就好像加了下面的圆括号一样:

(Symbol = ‘ABC‘ AND Side = ‘BUY‘) OR Shares <=1000.0

  消息选择器支持6个算术比较运算符,也就是=、>、>=、<、<=和<>(不等于)。这些算术比较运算符,可以使用在除boolean以外的任何基本属性类型上。Boolean和String属性类型限定使用=或<>这两种算术运算符。

  String类型可以使用LIKE比较运算符进行比较。例如:

Shares > 1000.0 AND Symbol LIKE ‘A%C‘

  LIKE运算符试图将常量中的每个字符和属性字符相匹配。LIKE比较还可以使用两个特殊的通配符:_和%。下划线代表所有的单个字符。百分号代表所有的字符串。

  BETWEEN运算符可以用于指定一个范围(包括端点在内)。例如:

Shares BETWEEN 1000 and 2000

  这个表达式等价于:

(Shares >= 1000) AND (Shares <= 2000)

  IN运算符可以用于指定一个组的成语:  

Symbol IN (‘ABC‘,‘AQC‘,BCD‘)

  这个表达式等价于:

(Symbol = ‘ABC‘) OR (Symbol = ‘AQC‘) OR (Symbol = ‘BCD‘)

声明一个消息选择器

  创建使用消息选择器的消费者时,JMS提供者必须确认该选择器语句句法正确。如果选择器句法错误,该运算会抛出javax.jms.InvalidSelectorException。示例如下:

String selector = "InventoryID = ‘s93740232-02‘ ADN Quantity BETWEEN 1000 AND 13000";

TopicSubscriber subscriber = session.createSubscriber(topic,selector,false);

QueueReceiver receiver = session.createReceiver(queue,selector);

  请注意:发布/订阅模型中,当创建订阅者时,要指定消息选择器,还必须为noLocal参数指定一个boolean值。noLocal参数仅仅适用于主题,并指明了消息生产者发布的消息是否应该传送给这个生产者自身。true表示禁止将消息传送给发布这条消息的同一连接。

设计注意事项

  在设计基于消息的解决方案时,主要有两种消息过滤方式。您可以向单个JMS目的地发送所有相关的消息,并对消息消费者使用消息过滤来选择特定的消息,或者使用包含预过滤消息的多个JMS目的地。第一种方式,我们称之为Message Filtering(消息过滤)方式,而第二种方式,则成为Multiple Destination(多目的地)方式。迄今为止,我们重点讲述的是Message Filtering方式,使用这种方式,消息会发送给单个JMS目的地,并由消息过滤者过滤,如图所示:

  请注意:在Msssage Filtering方式中,是消息消费者控制了消息过滤,并决定它要接收什么消息。这种方式为消息生产者组件和消息消费者组件提供了更高程度的解耦,因为消息生产者只需了解更少的关于如何处理消息的信息。这对发布/订阅者模型来说更是如此,因为主题发布者通常不会注意某个特定主题订阅者的数量和类型。

  

  Multiple Destination方式在消息发送到目的地之前使用消息过滤。它使用的不是消息选择器,取而代之的则是包含特定消息的多目的地方式。消息生产者通常使用Java代码应用逻辑来判断消息应该被发送到哪一个目的地。由于每个队列或主题包含了一个特定类型的预过滤消息,消息消费者就不必使用消息过滤来接收它所感兴趣的消息。如图6-2:

  如图6-2所示,使用Multiple Destination方式时,是消息生产者控制着过滤,同时还控制着哪一个目的地接收哪一条消息。这就是两种过滤方式之间的一个根本区别。使用Multiple Destination方式要考虑的一个关键因素就是,消息生产者对于消息的处理过程是否足够了解,以决定将消息路由到哪一个目的地。至于消息将如何消费,消息生产者了解得越多,它和消息消费者之间的耦合就会越紧密。当然,仅仅因为使用Multiple Destination方式,并不意味着您就无法进一步对消息消费者进行基于消息选择器的过滤。这两种方式的混合方式如图6-3所示:

  这种混合方式在许多方面实现了上述两种方式的最佳平衡。它解决了Message Filtering方式和Multiple Destination方式面临的许多问题。对任何一种方式的过量使用都是一个很好的暗示:您的队列和主题的整体设计还存在问题,而主要问题就在于JMS目的地的粒度级别。要进行大量消息过滤的主题订阅者会提出该主题力度太粗,它们或许应该被划分为多个主题。而另一方面,被强制订阅多个主题以找回(retrieve)所需信息的主题订阅者,则会提出该主题粒度太细,应该将它们合并起来,以适用于主题订阅者使用的大多数用例。一般来说,队列或主题所代表的粒度等级及队列或主题的总体设计,应该反映信息的使用方式。

消息过滤

时间: 2024-10-28 08:23:15

消息过滤的相关文章

ActiveMQ消息过滤

前言 ActiveMQ提供了一种机制,使用它,消息服务可根据消息选择器中的标准来执行消息过滤.生产者可在消息中放入应用程序特有的属性,而消费者可使用基于这些属性的选择标准来表明对消息是否感兴趣.这就简化了客户端的工作,并避免了向不需要这些消息的消费者传送消息的开销.然而,它也使得处理选择标准的消息服务增加了一些额外开销. 消息选择器是用于MessageConsumer的过滤器,可以用来过滤传入消息的属性和消息头部分(但不过滤消息体),并确定是否将实际消费该消息.消息选择器是一些字符串,它们基于某

Windows消息过滤

在C#编程中,经常会遇到一些场景,如禁止鼠标拖动窗体,启用某些快捷键,禁止鼠标移动等.遇到这些需求,可以通过窗体的MouseMove事件,OnDragDrop,OnMove等事件来解决问题, 但是该方法有个缺点是,只能在当前窗体或控件上起作用,如果窗体或控件被覆盖,就不起作用了.而我们在开发时经常会碰到一个Form上有很多控件的情形,本节将讲述如何通过捕捉windows消息的方式来实现这个功能. 一般来讲,实现该功能有两种方法, 1. 通过重写WndProc(ref Message m)来实现,

JMS学习四(ActiveMQ消息过滤)

消息的过期.消息的选择器和消息的优先级. 一.消息的过期 允许消息过期 .默认情况下,消息永不会过期.如果消息在特定周期内失去意义,那么可以设置过期时间. 有两种方法设置消息的过期时间,时间单位为毫秒: 1.使用消息生产者的setTimeToLive 方法为所有的消息设置过期时间.2.使用消息生产者的send 方法为每一条消息设置过期时间. 消息过期时间,send 方法中的 timeToLive 值加上发送时刻的 GMT 时间值.如果 timeToLive 值等于零,则 JMSExpiratio

消息队列如何利用标签实现消息过滤

场景介绍 一个消息队列(MQ)存储的消息,可以包含不同实际用途.如果这些消息不加区分,消费者每次消费都会按顺序拉取消息,直到完成对所有消息的消费.如果消费者只对某一类型的消息感兴趣,那么将所有消息都消费一遍必会影响消费者处理效率. 解决方案 分布式消息服务DMS是稳定可靠的消息队列服务,提供普通队列.有序队列.Kafka.ActiveMQ.RabbitMQ,兼容HTTP.TCP.AMQP协议,应用于系统解耦.异步通信.流量削峰去谷.第三方集成等场景.DMS提供消息标签的能力,支持生产者为每条消息

Spring Cloud Stream实现消息过滤的三种主要方式

消息过滤 消息过滤是指消费者不希望消费topic里的所有消息,而是只消费部分特定的消息.从topic中挑选出这些特定的消息,就是所谓的消息过滤.通过消息过滤可以实现消息的分流处理,例如生产者生产的消息,header可能都是不尽相同的,这样我们就可以编写两个或多个消费者,对不同header的消息进行针对性的处理. Spring Cloud Stream实现消息过滤的方式主要有三种,一是使用@StreamListener注解的condition属性指定条件表达式,二是在消息的header中设置TAG

C#发送消息过滤关键字

TrieFilter类 using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace SaaS.Web.Base { public class TrieNode { public bool m_end; public Dictionary<Char, TrieNode> m_values; public TrieNode() { m_values = new Dict

rocketmq的消息过滤

通常我们会使用Tag过滤 特殊情况下我们也可以使用userproperties过滤 , sql92定义 这两种都是在服务器端完成过滤, 对于超大数据量的场景(1小时4000W+)不要在客流端过滤 https://rocketmq.apache.org/docs/filter-by-sql92-example/ https://www.kunzhao.org/blog/2018/04/02/rocketmq-message-filter-flow/ 原文地址:https://www.cnblogs

分布式开放消息系统(RocketMQ)的原理与实践

分布式消息系统作为实现分布式系统可扩展.可伸缩性的关键组件,需要具有高吞吐量.高可用等特点.而谈到消息系统的设计,就回避不了两个问题: 消息的顺序问题 消息的重复问题 RocketMQ作为阿里开源的一款高性能.高吞吐量的消息中间件,它是怎样来解决这两个问题的?RocketMQ 有哪些关键特性?其实现原理是怎样的? 关键特性以及其实现原理 一.顺序消息 消息有序指的是可以按照消息的发送顺序来消费.例如:一笔订单产生了 3 条消息,分别是订单创建.订单付款.订单完成.消费时,要按照顺序依次消费才有意

C#捕获鼠标消息

在C#中怎样禁用鼠标按键,我们可以通过ImessageFilter接口下的PreFilterMessage方法.Application类的AddMessageFilter方法,RemoveMessageFilter方法和Message结构的Msg属性来禁用鼠标左键.Message结构包装Windows发送的消息,可使用该结构包装消息,并将其分配给窗口过程以进行调度,还可以使用该结构获取系统向应用程序或控件发送的关于某个消息的信息. 使用PreFilterMessage方法在调度消息之前将其筛选出