Menu Search

5.4. Session

A Session object is a single-threaded context for producing and consuming messages.

Session objects are created from the Connection. Whilst Session objects are relatively lightweight, patterns utilising a single Session per message are not recommended.

The number of sessions open per connection at any one time is limited. This value is negotiated when the connection is made. It defaults to 256.

Qpid JMS Sessions have the ability to prefetch messages to improve consumer performance. This feature is described next.

5.4.1. Prefetch

Prefetch specifies how many messages the client will optimistically cache for delivery to a consumer. This is a useful parameter to tune that can improve the throughput of an application. The prefetch buffer is scoped per Session.

The size of the prefetch buffer can be tuned per Connection using the connection url option maxprefetch (or JVM wide using the system property max_prefetch). By default, prefetch defaults to 500.

There are situations when you may wish to consider reducing the size of prefetch:

  1. When using a Competing Consumers pattern, prefetch can give the appearance of unequal division of work. This will be apparent on startup when the queue has messages. The first consumer started will cache prefetch size number of messages, possibly leaving the other consumers with no initial work.

  2. When using special queue types (such as LVQs, Sorted Queue and Priority Queues). For these queue types the special delivery rules apply whilst the message resides on the Broker. As soon as the message is sent to the client it delivery order is then fixed. For example, if using a priority queue, and a prefetch of 100, and 100 messages arrive with priority 2, the broker will send these to the client. If then a new message arrives with priority 1, the broker cannot leap frog messages of the lower priority. The priority 1 message will be delivered at the front of the next batch.

  3. When message size is large and you do not wish the memory footprint of the application to grow (or suffer an OutOfMemoryError).

Finally, if using multiple MessageConsumers on a single Session, keep in mind that unless you keep polling all consumers, it is possible for some traffic patterns to result in consumer starvation and an application level deadlock. For example, if prefetch is 100, and 100 hundred messages arrive suitable for consumer A, those messages will be prefetched by the session, entirely filling the prefetch buffer. Now if the application performs a blocking MessageConsumer#receive() for Consumer B on the same Session, the application will hang indefinitely as even if messages suitable for B arrive at the Broker. Those messages can never be sent to the Session as no space is available in prefetch.

Note

Please note, when the acknowledgement mode Session#SESSION_TRANSACTED or Session#CLIENT_ACKNOWLEDGE is set on a consuming session, the prefetched messages are released from the prefetch buffer on transaction commit/rollback (in case of acknowledgement mode Session#SESSION_TRANSACTED ) or acknowledgement of the messages receipt (in case of acknowledgement mode Session#CLIENT_ACKNOWLEDGE ). If the consuming application does not commit/rollback the receiving transaction (for example, due to mistakes in application exception handling logic), the prefetched messages continue to remain in the prefetch buffer preventing the delivery of the following messages. As result, the application might stop the receiving of the messages until the transaction is committed/rolled back (for Session#SESSION_TRANSACTED ) or received messages are acknowledged (for Session#CLIENT_ACKNOWLEDGE).

Settings maxprefetch to 0 ( either globally via JVM system property max_prefetch or on a connection level as a connection option maxprefetch ) switches off the pre-fetching functionality. With maxprefetch=0 messages are fetched one by one without caching on the client.

Note

Setting maxprefetch to 0 is recommended in Spring-JMS based applications whenever DefaultMassgeListenerContainer is configured with a CachingConnectionFactory that has cacheLevel set to either CACHE_CONSUMER or CACHE_SESSION. In these configurations the Qpid JMS Session objects remain open in Spring's dynamically scaled pools. If maxprefetch is not 0, any prefetched messages held by the Session and any new ones subsequently sent to it (in the background until prefetch is reached) will be effectively by 'stuck' (unavailable to the application) until Spring decides to utilise the cached Session again. This can give the impression that message delivery has stopped even though messages remain of the queue. Setting maxprefetch to 0 prevents this problem from occurring.

If using maxprefetch > 0 SingleConnectionFactory must be used. SingleConnectionFactory does not have the same session/consumer caching behaviour so does not exhibit the same problem.

5.4.2. TemporaryQueues

Temporary queues are exposed to Management in the same way as normal queues. Temporary queue names take the form string TempQueue followed by a random UUID.

5.4.3. CreateQueue

In the Client, Session#createQueue() accepts either a queue name, or a Binding URL. If only name is specified the destination will be resolved into binding URL: direct://amq.direct//<queue name>?routingkey='<queue name>'&durable='true'.

Calling Session#createQueue() has no effect on the Broker.

Reiterating the advice from the JMS javadoc, it is suggested that this method is not generally used. Instead, application should lookup Destinations declared within JNDI.

5.4.4. CreateTopic

In the Client, Session#createTopic() accepts either a topic name, or a Binding URL. If only name is specified the destination will be resolved into binding URL: topic://amq.topic//<topic name>?routingkey='<topic name>'.

Calling Session#createTopic() has no effect on the Broker.

Reiterating the advice from the JMS javadoc, it is suggested that this method is not generally used. Instead, application should lookup Destinations declared within JNDI.