Skip Navigation Links | |
Exit Print View | |
Oracle GlassFish Server Message Queue 4.5 Developer's Guide for Java Clients |
3. Message Queue Clients: Design and Features
Balancing Reliability and Performance
Thread Allocation for Connections
Programming Issues for Message Consumers
Using the Client Runtime Ping Feature
Preventing Message Loss for Synchronous Consumers
Synchronous Consumption in Distributed Applications
Delivery Mode (Persistent/Nonpersistent)
Durable vs. Nondurable Subscriptions
Use of Selectors (Message Filtering)
Creating a Consumer Event Listener
Consumer Event Listener Examples
Client Connection Failover (Auto-Reconnect)
Parallel Broker Auto-Reconnect
Clustered-Broker Auto-Reconnect
Handling Exceptions When Failover Occurs
Handling Exceptions in a Transacted Session
Transacted Session: Failover Producer Example
Transacted Session: Failover Consumer Example
Handling Exceptions in a Non-Transacted Session
Schema Validation of XML Payload Messages
Logging Name Spaces, Levels, and Activities
Using the JRE Logging Configuration File
Using a Logging Configuration File for a Specific Application
Setting the Logging Configuration Programmatically
4. Using the Metrics Monitoring API
6. Embedding a Message Queue Broker in a Java Client
This section describes memory and performance issues that you can manage by increasing JVM heap space and by managing the size of your messages. It covers the following topics:
You can also improve performance by having the administrator set connection factory attributes to meter the message flow over the client-broker connection and to limit the message flow for a consumer. For a detailed explanation, please see Reliability And Flow Control in Oracle GlassFish Server Message Queue 4.5 Administration Guide.
A client application running in a JVM needs enough memory to accommodate messages that flow in from the network as well as messages the client creates. If your client gets OutOfMemoryError errors, chances are that not enough memory was provided to handle the size or the number of messages being consumed or produced.
Your client might need more than the default JVM heap space. On most systems, the default is 64 MB but you will need to check the default values for your system.
Consider the following guidelines:
Evaluate the normal and peak system memory footprints when sizing heap space.
You can start by doubling the heap size using a command like the following:
java -Xmx128m MyClass
The best size for the heap space depends on both the operating system and the JDK release. Check the JDK documentation for restrictions.
The size of the VM’s memory allocation pool must be less than or equal to the amount of virtual memory that is available on the system.
In general, for better manageability, you can break large messages into smaller parts, and use sequencing to ensure that the partial messages sent are concatenated properly. You can also use a Message Queue JMS feature to compress the body of a message. This section describes the programming interface that allows you to compress messages and to compare the size of compressed and uncompressed messages.
Message compression and decompression is handled entirely by the client runtime, without involving the broker. Therefore, applications can use this feature with a pervious version of the broker, but they must use version 3.6 or later of the Message Queue client runtime library.
You can use the Message.setBooleanProperty() method to specify that the body of a message be compressed. If the JMS_SUN_COMPRESS property is set to true, the client runtime, will compress the body of the message being sent. This happens after the producer’s send method is called and before the send method returns to the caller. The compressed message is automatically decompressed by the client runtime before the message is delivered to the message consumer.
For example, the following call specifies that a message be compressed:
MyMessage.setBooleanProperty(“JMS_SUN_COMPRESS”,true);
Compression only affects the message body; the message header and properties are not compressed.
Two read-only JMS message properties are set by the client runtime after a message is sent.
Applications can test the properties (JMS_SUN_UNCOMPRESSED_SIZE and JMS_SUN_COMPRESSED_SIZE) after a send returns to determine whether compression is advantageous. That is, applications wanting to use this feature, do not have to explicitly receive a compressed and uncompressed version of the message to determine whether compression is desired.
If the consumer of a compressed message wants to resend the message in an uncompressed form, it should call the Message.clearProperties() to clear the JMS_SUN_COMPRESS property. Otherwise, the message will be compressed before it is sent to its next destination.
Although message compression has been added to improve performance, such benefit is not guaranteed. Benefits vary with the size and format of messages, the number of consumers, network bandwidth, and CPU performance. For example, the cost of compression and decompression might be higher than the time saved in sending and receiving a compressed message. This is especially true when sending small messages in a high-speed network. On the other hand, applications that publish large messages to many consumers or who publish in a slow network environment, might improve system performance by compressing messages.
Depending on the message body type, compression may also provide minimal or no benefit. An application client can use the JMS_SUN_UNCOMPRESSED_SIZE and JMS_SUN_COMPRESSED_SIZE properties to determine the benefit of compression for different message types.
Message consumers deployed with client runtime libraries that precede version 3.6 cannot handle compressed messages. Clients wishing to send compressed messages must make sure that consumers are compatible. C clients cannot currently consume compressed messages.
Example 3-1 shows how you set and send a compressed message:
Example 3-1 Sending a Compressed Message
//topicSession and myTopic are assumed to have been created topicPublisher publisher = topicSession.createPublisher(myTopic); BytesMessage bytesMessage=topicSession.createBytesMessage(); //byteArray is assumed to have been created bytesMessage.writeBytes(byteArray); //instruct the client runtime to compress this message bytesMessage.setBooleanProperty("JMS_SUN_COMPRESS", true); //publish message to the myTopic destination publisher.publish(bytesMessage);
Example 3-2 shows how you examine compressed and uncompressed message body size. The bytesMessage was created as in Example 3-1:
Example 3-2 Comparing Compressed and Uncompressed Message Size
//get uncompressed body size int uncompressed=bytesMessage.getIntProperty(“JMS_SUN_UNCOMPRESSED_SIZE”); //get compressed body size int compressed=bytesMessage.getIntProperty(“JMS_SUN_COMPRESSED_SIZE”);
When a message is deemed undeliverable, it is automatically placed on a special queue called the dead message queue. A message placed on this queue retains all of its original headers (including its original destination) and information is added to the message’s properties to explain why it became a dead message. An administrator or a developer can access this queue, remove a message, and determine why it was placed on the queue.
For an introduction to dead messages and the dead message queue, see Using the Dead Message Queue in Oracle GlassFish Server Message Queue 4.5 Administration Guide
For a description of the destination properties and of the broker properties that control the system’s use of the dead message queue, see Chapter 18, Physical Destination Property Reference, in Oracle GlassFish Server Message Queue 4.5 Administration Guide
This section describes the message properties that you can set or examine programmatically to determine the following:
Whether a dead message can be sent to the dead message queue.
Whether the broker should log information when a message is destroyed or moved to the dead message queue.
Whether the body of the message should also be stored when the message is placed on the dead message queue.
Why the message was placed on the dead message queue and any ancillary information.
Message Queue 3.6 clients can set properties related to the dead message queue on messages and send those messages to clients compiled against earlier versions. However clients receiving such messages cannot examine these properties without recompiling against 3.6 libraries.
The dead message queue is automatically created by the broker and called mq.sys.dmq. You can use the message monitoring API, described in Chapter 4, Using the Metrics Monitoring API, to determine whether that queue is growing, to examine messages on that queue, and so on.
You can set the properties described in Table 3-2 for any message to control how the broker should handle that message if it deems it to be undeliverable. Note that these message properties are needed only to override destination, or broker-based behavior.
Table 3-2 Message Properties Relating to Dead Message Queue
|
The properties described in Table 3-3 are set by the broker for a message placed in the dead message queue. You can examine the properties for the message to retrieve information about why the message was placed on the queue and to gather other information about the message and about the context within which this action was taken.
Table 3-3 Dead Message Properties
|
When creating a topic or queue destination, the administrator can specify how the broker should behave when certain memory limits are reached. Specifically, when the number of messages reaching a physical destination exceeds the number specified with the maxNumMsgs property or when the total amount of memory allowed for messages exceeds the number specified with the maxTotalMsgBytes property, the broker takes one of the following actions, depending on the setting of the limitBehavior property:
If the default value REJECT_NEWEST is specified for the limitBehavior property, the broker throws out the newest messages received when memory limits are exceeded. If the message discarded is a persistent message, the producing client gets an exception which should be handled by resending the message later.
If any of the other values is selected for the limitBehavior property or if the message is not persistent, the application client is not notified if a message is discarded. Application clients should let the administrator know how they prefer this property to be set for best performance and reliability.