Listen to heartbeats using JMS

Extend heartbeats using JMS publish and subscribe

1 2 3 Page 3
Page 3 of 3
  public static void main(String args[]) {
    try {
      TopicConnectionFactory tcf = (TopicConnectionFactory)
          getConnectionFactory(args[0], args[1], args[2], args[3],
          args[4], args[5]);
      DependentHeartbeatPublisher publisher = new
          DependentHeartbeatPublisher(tcf, args[6],
          Long.parseLong(args[7]), "TEST", DeliveryMode.NON_PERSISTENT);
      publisher.setDependentParameters(new Object[]
          {"com.pointbase.jdbc.jdbcUniversalDriver",
          "jdbc:pointbase://localhost/sample", "PUBLIC", "PUBLIC"});
      TestPublisherListener tbl = new TestPublisherListener(publisher);
      publisher.registerListener(tbl);
      publisher.startHeartbeatProcess();
    } catch (Exception erx) {
      System.err.println("Error:" + erx);
      System.exit(1);
    }
  }

If you start the publisher with the database running, shut the database down shortly after, and then restart it, the test's output might look like this:

Dependent publisher output

<java com.nickman.jms.heartbeats.DependentHeartbeatPublisher
   smqp://localhost:4001 admin secret com.swiftmq.jndi.
   InitialContextFactoryImpl simple TopicConnectionFactory MY.WORLD
   5000
[Tue Jan 22 08:38:01 EST 2002] Publisher Started
[Tue Jan 22 08:38:05 EST 2002] Publisher Sent Heartbeat
[Tue Jan 22 08:38:08 EST 2002] Publisher Sent Heartbeat
[Tue Jan 22 08:38:11 EST 2002] Publisher Sent Heartbeat
[Tue Jan 22 08:38:14 EST 2002] Publisher Sent Heartbeat
[Tue Jan 22 08:38:18 EST 2002] Publisher Sent Heartbeat
[Tue Jan 22 08:38:21 EST 2002] Publisher Sent Heartbeat
[Tue Jan 22 08:38:24 EST 2002] Publisher Sent Heartbeat
[Tue Jan 22 08:38:27 EST 2002] Publisher Sent Heartbeat
[Tue Jan 22 08:38:32 EST 2002] Publisher Exception:com.nickman.jms.heartbeats.exception.
   PublisherDependencyException: PointBase server rejected
   SQL connection.
[Tue Jan 22 08:38:37 EST 2002] Publisher Exception:com.nickman.jms.heartbeats.exception.
   PublisherDependencyException: PointBase server rejected
   SQL connection.
[Tue Jan 22 08:38:42 EST 2002] Publisher Exception:com.nickman.jms.heartbeats.exception.
   PublisherDependencyException: PointBase server rejected
   SQL connection.
[Tue Jan 22 08:38:46 EST 2002] Publisher Sent Heartbeat
[Tue Jan 22 08:38:49 EST 2002] Publisher Sent Heartbeat
[Tue Jan 22 08:38:52 EST 2002] Publisher Sent Heartbeat
[Tue Jan 22 08:38:52 EST 2002] Publisher Stopped

Subscriber output

java com.nickman.jms.heartbeats.HeartbeatSubscriber
   smqp://localhost:4001 admin secret com.swiftmq.jndi.InitialContextFactoryImpl
   simple TopicConnectionFactory MY.WORLD 3000
[Tue Jan 22 08:38:18 EST 2002] Heartbeat Subscriber Started
[Tue Jan 22 08:38:21 EST 2002] Heartbeat Session Resumed at Tue Jan 22 08:38:21 EST 2002 and 0 ticks.
[Tue Jan 22 08:38:21 EST 2002] Heartbeat Received
[Tue Jan 22 08:38:24 EST 2002] Heartbeat Received
[Tue Jan 22 08:38:27 EST 2002] Heartbeat Received
[Tue Jan 22 08:38:33 EST 2002] Heartbeat Session Failed 1 times.
[Tue Jan 22 08:38:38 EST 2002] Heartbeat Session Failed 2 times.
[Tue Jan 22 08:38:43 EST 2002] Heartbeat Session Failed 3 times.
[Tue Jan 22 08:38:46 EST 2002] Heartbeat Session Resumed at Wed Dec 31 19:00:02 EST 1969 and 3 ticks.
[Tue Jan 22 08:38:46 EST 2002] Heartbeat Received
[Tue Jan 22 08:38:49 EST 2002] Heartbeat Received
[Tue Jan 22 08:38:52 EST 2002] Heartbeat Received

I put a heartbeat publisher in a new Swing application, as Figure 8 illustrates, which I use to ensure that our testers are not slacking off!

Figure 8. A trivial heartbeat subscriber-based application. Click on thumbnail to view full-size image.

Implementation and runtime caveats

Differences among operating environments, implementations, and throughputs might (probably will) mean that you'll need to tweak things to get optimal results from JMS heartbeats. The next sections list issues difficult to address in the framework's code.

Flow control

Be careful with flow control. Some JMS implementations employ flow control to slow down a publisher to a message rate approximating that of the slowest subscriber. Such flow control can be an asset, but one slow consumer (known as a poison subscriber) on a heartbeat topic might cause false heartbeat failures for some or all other heartbeat subscribers.

Unfortunately, I do not have a conclusive solution to this problem. After much struggle with flow control, I have arrived at the opinion that a JMS specification update should address the issue, which it currently dodges.

In a situation where a publisher's rate exceeds that of only one subscriber, there are only three options:

  1. Drop the messages to that subscriber by:
    • Dropping the most recent message
    • Dropping the oldest message
  2. Persist the messages until the slow subscriber catches up
  3. Slow down the publisher to match the slowest subscriber's rate

Your JMS provider's abilities will dictate your options.

Thread pools

The publisher and subscriber implementations use a basic thread pool to asynchronously invoke the listener events, except for stops and exceptions. The default implementation uses a pool size of 2. You may need to adjust the size by either modifying the fireEvent() method, which accepts a Boolean to determine whether to fire the events asynchronously or not, or by adjusting the thread pool size. Your choice will depend on the number and nature of the methods in the registered listeners.

JMS dependency

The framework depends heavily on JMS. Ultimately, the framework should support a more generic implementation in which you can choose the heartbeat's underlying transport protocol.

JMS throughput

I have not implemented any benchmarks to test throughput. The results would vary based on implementation details as well as JMS software and hardware. I participated in a few threads on the JMS Interest forum on the issue of using JMS for alarms, and while most of the content was geared towards broadcasting alerts (sort of the opposite of heartbeats), when I pitched my idea, two people quickly asked if the architecture would support heartbeats with a frequency of 500 ms or less. The answer is yes, but I cannot be sure what impact this will have on your JMS infrastructure and whether or not this will affect your core traffic. Rerouting heartbeats to a secondary JMS server may be a solution; however, if you do this, you'll lose the ability to check the health of your core JMS channels.

Wrap up

Most developers should find JMS publish and subscribe constructs an effective way to implement heartbeats. JMS vendors' increased flexibility and protocol support add to JMS's usefulness in this capacity. For example, HTTP now serves as a common JMS message protocol, so with minimal setup you could place heartbeat publishers in applets. This article's framework will give you an implementation head start.

I would like to thank Jonathan "Xylophone" Simon and many others for their invaluable assistance.

Nicholas Whitehead, a Java architect at finetix LLC, has worked with software since Xenix was popular. He currently works in Manhattan where he has implemented solutions using MQSeries, SwiftMQ, SonicMQ, and TIBCO. He spends some of his free time working on open source projects and is part of a group building an enterprise framework for Java Network Launching Protocol and API (JNLP)-based application deployment. Nicholas, who lives in New Jersey, also enjoys Phish concerts (they will be back).

Learn more about this topic

1 2 3 Page 3
Page 3 of 3