Title: Hedwig Message Filter
Notice: Licensed under the Apache License, Version 2.0 (the “License”);
you may not use this file except in compliance with the License. You may
obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an “AS IS”
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied. See the License for the specific language governing permissions
and limitations under the License.
Apache Hedwig provides an efficient mechanism for supporting application-defined message filtering.
Most message-oriented middleware (MOM) products treat messages as lightweight entities that consist of a header and a payload. The header contains fields used for message routing and identification; the payload contains the application data being sent.
Hedwig messages follow a similar template, being composed of following parts:
Header– All messages support both system defined fields and application defined property values. Properties provide an efficient mechanism for supporting application-defined message filtering.
Body– Hedwig considers the message body as a opaque binary blob.
SrcRegion– Indicates where the message comes from.
MessageSeqId– The unique message sequence id assigned by Hedwig.
Message Header Properties
A Message object contains a built-in facility for supporting application-defined property values. In effect, this provides a mechanism for adding application-specific header fields to a message.
By using properties and message filters, an application can have Hedwig select, or filter, messages on its behalf using application-specific criteria.
Property names must be a String and must not be null, while property values are binary blobs. The flexibility of binary blobs allows applications to define their own serialize/deserialize functions, allowing structured data to be stored in the message header.
A Message Filter allows an application to specify, via header properties, the messages it is interested in. Only messages which pass validation of a Message Filter, specified by a subscriber, are be delivered to the subscriber.
A message filter could be run either on the server side or on the client side. For both server side and client side, a Message Filter implementation needs to implement the following two interfaces:
setSubscriptionPreferences(topic, subscriberId, preferences): The subscription preferences of the subscriber will be passed to message filter when it was attached to its subscription either on the server-side or on the client-side.
testMessage(message): Used to test whether a particular message passes the filter or not.
The subscription preferences are used to specify the messages that the user is interested in. The message filter uses the subscription preferences to decide which messages are passed to the user.
Take a book store(using topic BookStore) as an example:
- User A may only care about History books. He subscribes to BookStore with his custom preferences : type=“History”.
- User B may only care about Romance books. He subscribes to BookStore with his custom preferences : type=“Romance”.
- A new book arrives at the book store; a message is sent to BookStore with type=“History” in its header
- The message is then delivered to __BookStore__’s subscribers.
- Subscriber A filters the message by checking messages’ header to accept those messages whose type is “History”.
- Subscriber B filters out the message, as the type does not match its preferences.
Client Message Filter.
A ClientMessageFilter runs on the client side. Each subscriber can write its own filter and pass it as a parameter when starting delivery ( startDelivery(topic, subscriberId, messageHandler, messageFilter) ).
Server Message Filter.
A ServerMessageFilter runs on the server side (a hub server). A hub server instantiates a server message filter, by means of reflection, using the message filter class specified in the subscription preferences which are provided by the subscriber. Since __ServerMessageFilter__s run on the hub server, all filtered-out messages are never delivered to client, reducing unnecessary network traffic. Hedwig uses a implementation of ServerMessageFilter to filter unnecessary message deliveries between regions.
Since hub servers use reflection to instantiate a ServerMessageFilter, an implementation of ServerMessageFilter needs to implement two additional methods:
initialize(conf): Initialize the message filter before filtering messages.
uninitialize(): Uninitialize the message filter to release resources used by the message filter.
For the hub server to load the message filter, the implementation class must be in the server’s classpath at startup.
Which message filter should be used?
It depends on application requirements. Using a ServerMessageFilter will reduce network traffic by filtering unnecessary messages, but it would compete for resources on the hub server(CPU, memory, etc). Conversely, __ClientMessageFilter__s have the advantage of inducing no extra load on the hub server, but at the price of higher network utilization. A filter can be installed both at the server side and on the client; Hedwig does not restrict this.