diff --git a/docs/user-manual/en/last-value-queues.md b/docs/user-manual/en/last-value-queues.md index cf89369033..0b1627d04b 100644 --- a/docs/user-manual/en/last-value-queues.md +++ b/docs/user-manual/en/last-value-queues.md @@ -1,19 +1,20 @@ # Last-Value Queues -Last-Value queues are special queues which discard any messages when a -newer message with the same value for a well-defined Last-Value property -is put in the queue. In other words, a Last-Value queue only retains the -last value. +Last-Value queues are special queues which discard any messages when a newer +message with the same value for a well-defined Last-Value property is put in +the queue. In other words, a Last-Value queue only retains the last value. -A typical example for Last-Value queue is for stock prices, where you -are only interested by the latest value for a particular stock. +A typical example for Last-Value queue is for stock prices, where you are only +interested by the latest value for a particular stock. -Messages sent to an Last-Value queue without the specified property will be delivered as normal and will never be "replaced". +Messages sent to an Last-Value queue without the specified property will be +delivered as normal and will never be "replaced". ## Configuration #### Last Value Key Configuration -Last-Value queues can be statically configured in broker.xml via the `last-value-key` +Last-Value queues can be statically configured in broker.xml via the +`last-value-key` ```xml
@@ -34,8 +35,8 @@ Queue queue = session.createQueue("my.destination.name?last-value-key=reuters_co Topic topic = session.createTopic("my.destination.name?last-value-key=reuters_code"); ``` -Address wildcards can be used to configure Last-Value queues -for a set of addresses (see [here](wildcard-syntax.md)). +Address wildcards can be used to configure Last-Value queues for a set of +addresses (see [here](wildcard-syntax.md)). ```xml @@ -43,13 +44,12 @@ for a set of addresses (see [here](wildcard-syntax.md)). ``` -By default, `default-last-value-key` is null. - +By default, `default-last-value-key` is `null`. #### Legacy Last Value Configuration -Last-Value queues can also just be configured via the `last-value` boolean property, doing so it will default the last-value-key to `"_AMQ_LVQ_NAME"`. - +Last-Value queues can also just be configured via the `last-value` boolean +property, doing so it will default the last-value-key to `_AMQ_LVQ_NAME`. ```xml
@@ -84,15 +84,14 @@ By default, `default-last-value-queue` is false. Note that `address-setting` `last-value-queue` config is deprecated, please use `default-last-value-queue` instead. - - ## Last-Value Property The property name used to identify the last value is configurable at the queue level mentioned above. -If using the legacy setting to configure an LVQ then the default property `"_AMQ_LVQ_NAME"` is used -(or the constant `Message.HDR_LAST_VALUE_NAME` from the Core API). +If using the legacy setting to configure an LVQ then the default property +`"_AMQ_LVQ_NAME"` is used (or the constant `Message.HDR_LAST_VALUE_NAME` from +the Core API). For example, using the sample configuration @@ -127,16 +126,23 @@ TextMessage messageReceived = (TextMessage)messageConsumer.receive(5000); System.out.format("Received message: %s\n", messageReceived.getText()); ``` - ## Forcing all consumers to be non-destructive -When a consumer attaches to a queue, the normal behaviour is that messages are sent to that consumer are acquired exclusively by that consumer, and when the consumer acknowledges them, the messages are removed from the queue. -Another common pattern is to have queue "browsers" which send all messages to the browser, but do not prevent other consumers from receiving the messages, and do not remove them from the queue when the browser is done with them. Such a browser is an instance of a "non-destructive" consumer. +When a consumer attaches to a queue, the normal behaviour is that messages are +sent to that consumer are acquired exclusively by that consumer, and when the +consumer acknowledges them, the messages are removed from the queue. -If every consumer on a queue is non destructive then we can obtain some interesting behaviours. In the case of a LVQ then the queue will always contain the most up to date value for every key. +Another common pattern is to have queue "browsers" which send all messages to +the browser, but do not prevent other consumers from receiving the messages, +and do not remove them from the queue when the browser is done with them. Such +a browser is an instance of a "non-destructive" consumer. -A queue can be created to enforce all consumers are non-destructive for last value queue. This can be achieved using the following queue configuration: +If every consumer on a queue is non destructive then we can obtain some +interesting behaviours. In the case of a LVQ then the queue will always contain +the most up to date value for every key. +A queue can be created to enforce all consumers are non-destructive for last +value queue. This can be achieved using the following queue configuration: ```xml
@@ -164,15 +170,42 @@ Also the default for all queues under and address can be defaulted using the ``` -By default, `default-non-destructive` is false. +By default, `default-non-destructive` is `false`. +#### Bounding size using `expiry-delay` -#### Bounding size using expiry-delay -For queues other than LVQs, having only non-destructive consumers could mean that messages would never get deleted, leaving the queue to grow unconstrainedly. To prevent this you can use the ability to set a default `expiry-delay`. +For queues other than LVQs, having only non-destructive consumers could mean +that messages would never get deleted, leaving the queue to grow unconstrained. +To prevent this you can use the ability to set a default `expiry-delay`. -See [expiry-delay](message-expiry.md#configuring-expiry-delay) for more details on this. - +See [expiry-delay](message-expiry.md#configuring-expiry-delay) for more details +on this. +## Clustering + +The fundamental ideas behind last-value queues and clustering are at odds with +each other. + +Clustering was designed as a way to increase message throughput through +horizontal scaling. The messages in a clustered queue can be spread across +_all_ nodes in the cluster. This allows clients to be distributed across the +cluster to leverage the computing resources all the nodes rather than being +bottlenecked on a single node. + +However, if you wanted to use a last-value queue in a cluster then in order +to enforce last-value semantics all messages would be required to go to a +queue on a _single_ node. This would effectively _nullify_ the benefits of +clustering. Also, the arrival of messages on and and redistribution of +those messages from nodes other than the node where the last-value semantics +would be enforced would almost certainly impact which message is considered +"last." + +For these reasons last-value queues are not supported in a traditional cluster. +However, it would be possible to use a [broker balancer](broker-balancers.md) +in front of a cluster (or even a set of non-clustered brokers) to ensure all +clients which need to use the same last-value queue are directed to the same +node. See the [broker balancer chapter](broker-balancers.md) for more details +on configuration, etc. ## Example