Guide to Queuing

Best Practices

When you use queuing, you should follow best practices to ensure optimal performance, reliability, and efficient use of resources.

When you write client applications, consider how you create and use contexts, how you time connection initiation, and the use of message persistence. When you set configuration options, consider whether to do this with configuration files or programmatically. Configuration options can help you tune applications for the appropriate balance between performance and reliability. When you deploy a queuing system, consider using a high availability deployment.

# Application Development Best Practices <-

To ensure reliable operation of UMQ source and receiver applications, consider the following best practices.

## Use the Appropriate Number of Contexts <-

Usually a client application needs only one context. However, a client application might need more than one context, as in the following examples:

- You cannot use the same context for UMQ sources and receivers and UMS or UMP sources and receivers. If your applications uses both types of source and receiver, create a separate context for each type.
- Because a brokered context can make only one connection to a broker, you might want to configure multiple sources or receivers with separate connections to a broker to increase throughput. To do this, create a separate context for each source or receiver.

Define a context and set default attributes with a configuration file. Then define additional contexts and set their attributes in the client application code.

## If Performance Is Important, Consider Not Persisting Messages <-

By default, source applications flag messages to the broker as persisted messages. You can unset this flag to send the messages as non-persisted. Non-persisted messages do not provide as much reliability, but tend to reach their destination faster because they do not need to wait for persistence operations to complete. Thus, the decision to persist messages or not can be a choice of performance versus reliability.

## Wait for Registration <-

To avoid start-up errors, do not start sending messages immediately after source creation. Instead, wait for sources to register with the broker.

After you create the source, wait for the LBM_SRC_EVENT_UMQ_REGISTRATION_COMPLETE_EX event before sending messages.

## Plan For Possible Connection Interruptions <-

A broker might stop or lose connection to a client application while an operation is in progress. Plan for this possibility when writing source or receiver applications.

If a broker stops and then restarts, a source application might not receive stability acknowledgements for in-flight messages. In this situation the source application must resend the message if needed, and possibly mark the message as previously sent.

If a broker or a receiver stops and then restarts, a receiver application might receive duplicate redelivered messages, and must handle these appropriately.

## Java and C# Receivers: Call dispose() <-

For Java and C# applications, when you complete processing a message, call the dispose() method to reuse the LBMMessage object. This can significantly increase performance.

# Configuration Best Practices <-

You can configure queuing application attributes by setting default values in a configuration file, then, if needed, setting values in the code to override these defaults.

## Use Configuration Files <-

Ultra Messaging configuration files set attributes for contexts, sources, or receivers. As a client application launches, it reads these files. Within client application code you can set attribute values to override those set by the configuration file. For non-default attributes within objects, you must decide whether to set them in a configuration file or within the client application code.

Use a UM configuration file to set attributes with the following characteristics:

- settings that are generic or common to most objects
- settings that are likely to change, such as broker IP address and port number

When using configuration files to set attributes for client applications, you can use either plain text configuration files or XML configuration files. Become familiar with the advantages of both types before deciding which type to use. For complete information about how to use both types of configuration files, see Configuration Overview.

The plain text configuration file, when invoked, writes option values into Ultra Messaging current default attributes. Ultra Messaging then uses these values in the creation of all objects. The format is simple, and Ultra Messaging does not validate the file syntax.

XML configuration files override default attributes and have more flexibility than a plain text configuration file. A single XML file can contain options for multiple client applications. For a single application, you can configure multiple named contexts, event queues, and so on, with different values for the same options. Also, Ultra Messaging Manager (UMM) can manage XML configuration files.

## Set Permanent Attributes Within the Code <-

Use function calls in the client application to set attributes that are not expected to change. Also use function calls in the client application to set attributes that are unique to the object.

## Consider Nonblocking Sources <-

Decide if you want client application sources to be blocking or nonblocking.

Problems with the broker or transport, such as when flight size is exceeded, can cause sources to block, and to stop sending messages. You can configure client applications such that when Ultra Messaging instructs a source to block, the source does not block or send, but instead returns with an LBM_EWOULDBLOCK error.

# Deployment Best Practices <-

When deploying a UMQ queuing, consider such things as whether to use a high-availability system and how to manage configuration files.

## Use a Three-Node System for Greater Reliability <-

If persisted or queued data is critical, or if continuity of service is critical, use a three-broker high availability deployment. The high-availability configuration can protect against such problems as a host restart, hard- drive failure or entire system failure.

Note
  A high availability UMQ queuing system is available in only a three-node configuration.

## Keep Track of Configuration Files <-

Brokered client application configuration file management is more complex than for non-brokered client applications. Queuing systems might require some or all of the following configuration files:

- An Ultra Messaging configuration file for each client application.
- An ActiveMQ configuration file for each broker.
- An Ultra Messaging configuration file for each broker. The ActiveMQ configuration file references this Ultra Messaging configuration file.

Ensure that configuration files reside in a manageable location. Keep records and backups of the entire set of configuration files for a queuing system. Also consider using a configuration management tool such as Ultra Messaging Manager or a content management system.

# Memory Usage <-

Many UM users need to modify ActiveMQ's default memory allocations.

## JVM Size <-

The ActiveMQ broker defaults to having a minimum and maximum JVM size of 1GB. Many UM users will find that this size restriction is inadequate. This can be configured by overriding the ACTIVEMQ_OPTS_MEMORY environment variable. For example, to set it to 1GB minimum and 2GB maximum, set the following prior to invoking ActiveMQ's startup script:

    export ACTIVEMQ_OPTS_MEMORY="-Xms1G -Xmx2G"

## JVM Reserved Space <-

By default, ActiveMQ is allowed to use 70% of the JVM heap space, with the remaining reserved for headroom. You can modify the activemq.xml file's systemUsage element to modify that percentage. See below for advice on setting reserved space.

## Message Paging <-

When a destination is initialized, ActiveMQ defaults to paging in 200 messages for that destination. If your messages are so large that paging in 200 messages from a destination will cause you to exceed the configured JVM limit, you should lower the number of messages to page in per destination. This can be done by adding the following attribute to any policy entries that have large messages in the activemq.xml file:

<policyEntry queue=">" persistJMSRedelivered="true" maxPageSize="20"></policyEntry>

The values you use will depend on your maximum message size. Using the default configured values, the JVM gets 1GB of memory and ActiveMQ is allowed to use 70% of that memory (700MB) with 300MB reserved for headroom. Knowing that ActiveMQ could page in 200 messages on startup, you need to make sure that your 200 messages will fit inside the 30% headroom. This is because when ActiveMQ begins paging in messages it does a one time memory check. If you were at 69% of the JVM limit, it will see that you have space and then page in 200 pages. If the 200 messages it pages in don't fit in the remaining headroom space, you will encounter memory errors.

For example, consider a case where you are sending 10MB messages. With the default page size of 200, you would need 2GB of available to page in all of those messages. This value is much greater than the 30% headroom available, so you could get memory errors.

This can be handled in two ways:

1. Reducing the page size to 20 messages will lower the memory requirement to 200MB (20 messages * 10MB each), which will fit in the 30% headroom space of the 1GB JVM size.
2. Increasing the JVM size to 8GB will allow you to page in all 200 messages, because the 30% reserved space of an 8GB JVM is 2.4GB.

It would also be possible to change the systemUsage element to modify the 30% default for reserved space.