Skip to content
kasemir edited this page Jun 27, 2013 · 5 revisions

Java Message Server

The CSS MessageLog and the Best Ever Alarm System Toolkit use a Java Message Server. Specifically, the Apache ActiveMQ implementation of JMS. Download it from http://activemq.apache.org.

JMS and the Apache ActiveMQ are very flexible.

Fundamentally, JMS is a publish/subscribe mechanism: Publish messages to a named Topic, subscribe to receive updates from a topic. There are many modes: a. All subscribers get updates to topics of interest. When there's no subscriber, the messages are lost. b. Each subscriber has a specific queue. While the subscriber is down, JMS buffers the messages until the subscriber connects again to read the messages.

CSS uses mode (a), and the messages are MapMessages, i.e. tag/value maps.

ActiveMQ supports several setups: a. Single server b. Master/Slave servers c. Message forwarding between servers in various topologies

For CSS use, (a) is all you need.

Minimal Setup

Unpack the ActiveMQ package from the Apache web site, then

cd apache-activemq-*/bin
./activemq start

On success, you should see it LISTENing on port 61616:

netstat -an | fgrep 616161

You might want to copy the default configuration file, conf/activemq.xml, into something like conf/my_activemq_setup and then use that configuration file:

./activemq start xbean:conf/my_activemq_setup.xml

The default configuration enables a web interface for a default user/password of admin/admin, to be changed in the file conf/jetty-realm.properties:

http://localhost:8161/admin

When using your own configuration file, you can disable things that you don't need, like the web monitor, or enable HTTPTransport to allow tunneling though web proxies.

Markus Moeller (DESY) suggested disabling the "multicast" option in the "networkConnectors" section to prevent multiple JMS servers from magically finding each other and causing more confusion than good. To start out, your "networkConnectors" and "transportConnectors" sections should look like this:

    <!-- Do not connect to other JMS servers -->
    <networkConnectors>
    </networkConnectors>

    <!-- Serve only with the default protocol on default port -->
    <transportConnectors>
        <transportConnector name="openwire" uri="tcp://0.0.0.0:61616"/>
    </transportConnectors>

Client (CSS) Configuration

When you configure CSS tools to use your JMS server, use a "failover:" URL:

 failover:(tcp://your_jms_host:61616)

Failover with a single server means: clients re-connect automatically after network problems.

Multiple JMS Servers, Master/Slave

In operational SNS experience, a basic JMS setup with a single server on the accelerator network has been very reliable. A basic master/slave failover setup is actually discouraged because it adds complexity without gain in reliability. Still, if you offer multiple JMS servers, clients then use a URL like

 failover:(tcp://first_jms_host:61616,tcp://second_jms_host:61616)

Note: Only use multi-host failover URLs if you specifically configured those JMS hosts for master/slave failover or message forwarding, or if they are on different networks!

If a client could potentially reach either of the hosts in a failover URL, you cannot predict which one it will reach! If the JMS servers were not configured for master/slave or message forwarding, one CSS component will end up connecting to the first JMS host, another to the second, and they effectively don't talk to each other!

Message Forwarding, Network of Brokers

There can be situations where multiple JMS servers need to be connected as a cluster, for example to bridge firewalls. A "Network of Brokers" will cause multiple JMS servers to exchange their messages. Clients can connect to any of the JMS brokers, publish and subscribe to any of them.

In the easiest setup, the JMS brokers will simply mirror all messages. For example, an alarm update posted by an alarm server to one JMS broker will be forwarded to all other brokers and their clients within the network. For bigger installations, this will result in a lot of unnecessary traffic, since not all brokers really need to receive all traffic. For such setups, study http://activemq.apache.org/networks-of-brokers.html

As an example to get started with just two JMS server, start the first one as usual on one host:

   <!-- Name the broker so that it's easier to spot when monitoring the configuration --> 
   <broker ... brokerName="number1" dataDirectory=...
      <!-- Do not initiate a network with other JMS server -->
      <networkConnectors>
      </networkConnectors>

      <!-- Serve default protocol and port -->
      <transportConnectors>
         <transportConnector name="openwire" uri="tcp://0.0.0.0:61616"/>
      </transportConnectors>

On the second host, start JMS such that it establishes a Network of Brokers with the first setup:

   <!-- Name the broker so that it's easier to spot when monitoring the configuration --> 
   <broker ... brokerName="number2" dataDirectory=...
      <!-- Do not initiate a network with other JMS server -->
      <networkConnectors>
        <networkConnector name="number1" uri="static:(tcp://host1:61616)" duplex="true"/>
      </networkConnectors>

      <!-- Serve default protocol and port -->
      <transportConnectors>
         <transportConnector name="openwire" uri="tcp://0.0.0.0:61616"/>
      </transportConnectors>

HTML Tunneling

The default ActiveMQ OpenWire protocol, defaulting to port 61616, works best.

The alternate/additional HTTP Transport can be useful for HTTP tunneling, to allow access to JMS on your control system network through a firewall, but it is not suggested for an operational setup.

To enable HTTP Transport, add these 2 jars from the xstream ZIP file to the JMS server:

  xstream and xmlpull for JMS 5.2,
  xstream and xpp3_min for JMS 5.1

JMS clients that use the HTTP Transport need commons-httpclient in addition to activemq-all.

Add this to the JMS server activemq.xml file:

<transportConnectors>
...
            <transportConnector name="http" uri="http://host-name:61618"/>

Your JMS server will now offer a http transport that clients can access under

   failover:(http://host-name:61618)

Use the real host name! 'localhost' will not work as a host-name, unless you really only want local clients which use "!http://localhost:61618" to connect!

When using JMS with HTTP transport, it's then easy to configure an Apache HTTPD as a Proxy to that JMS server, so no firewall exception is needed for JMS.

In the httpd.conf, do this:

# Assert that the proxy modules are loaded
[[LoadModule]] ..mod_proxy..
[[LoadModule]] ..mod_proxy_http..

# Configure gateway to JMS server:
# Access to
#    http://web_server/jms
# gets redirected to
#    http://jms_server:61618

# Disable 'forward' proxy
[[ProxyRequests]] Off
<Proxy *>
   Order deny,allow
   Allow from all
</Proxy>

[[ProxyPass]] /jms http://localhost:61618
[[ProxyPassReverse]] /jms http://localhost:61618

CSS clients can now use this URL, and the web server will forward the traffic to the HTTP Transport of your JMS server:

   failover:(http://your.web.server.org/jms)
Clone this wiki locally