Hi Fred,

If you are using message expiration, you ultimately need to have a handle
on the degree of time synchronization between your hosts.

The JMS API says for Message#getJMSExpiration() that "Clients should not
receive messages that have expired; however, the JMS API does not guarantee
that this will not happen". The escape clause there is effectively to cover
the race that occurs when you decide 'this hasn't expired', only for the
expiration point to have passed by the time the delivery is completed and
an application checks the value. The earlier bit is saying if JMSExpiration
> currentTime, client applications shouldnt see the message.

If a JMS client receives a message from a broker and possibly examines its
JMSExpiration value, it may determine that according to its local time the
message expiry time has already been passed, at which point it becomes an
interesting question as to whether the message should be given to a
consuming application or not. Some implementations will do so simply
because they dont check this, and others wont because they are trying to
enforce what the spec says above and according to the information at hand
the message really has actually expired. Different people might prefer one
or the other behaviour.

The same issue could reasonably exist between a producer and a broker it
sends to on another host, which might never give a message out to a
consumer because it had 'already expired when it arrived' for similar
reason.

Going back to the start this is basically to say, if you are using TTL
based expiration you need to ensure an appropriate level of clock
synchronization for your particular needs.

I'll leave the specifics of the questions to someone familiar with the code.

Robbie

On 21 October 2014 16:14, Fred Moore <[email protected]> wrote:

> Hi folks,
>
> I found a situation where the handling of timestamps/expirations by
> ActiveMQ 5.10 appears not to be correct, and unfortunately -- being this a
> consumer side issue -- it does not appear to be solvable via classic
> TimeStampingBrokerPlugin tweaks.
>
> Scenario:
>
> S1\ Broker B1 runs on HOST1
> S2\ Producer P1 is a java JMS application running on HOST1
> S3\ HOST1 is on UTC timezone
> S4\ B1 has BrokerTimestampingPlugin with futureOnly=true configured
>     (even if I think it does not play any role in this specific case)
> S4\ Consumer C1 is a java JMS API application running on HOST2
> S5\ Consumer C2 is a java STOMP API application running on HOST2
> S6\ HOST2 is on UTC timezone and its clock is 3 mins ahead of HOST1 clock
>
>
> Test case:
>
> T1\ P1 sends  message M1 with TTL=1 minute
> T2\ C1 on HOST2 immediately tries to receive a message but it does not find
> it because
>     according to HOST2 clock that message has already expired (see [*]
> trace)
> T3\ C2 on HOST2 tries to receive a message and it succeeds
>
> Questions/congeptures:
>
> Q1\ The behaviour looks client API/technology dependent, is this expected?
>    [I think it's not]
> Q2\ It looks like the JMS layer in C1 is re-checking expiration on
> candidate messages
>    "served" to it by the broker, causing the reported issue: is there a way
> to inhibit
>    this extra logic in JMS?
> Q3\ Is my assumption about BrokerTimestampingPlugin being useless here
> correct?
>     [It can only influence the produced messages and not the consumed ones]
>
> If there is no general solution to this it means that messages are wrongly
> ignored by ActiveMQ JMS consumers every time these [not so uncommon]
> conditions are verified:
>
> F1\ the consumer clock runs ahead of the broker clock by X seconds
> F2\ the TTL of messages is less than X seconds
> F3\ the consumer is a java JMS application
>
> Please help!
> Cheers,
> F.
>
>
> -----
> [*] Trace showing C1 misperception of M1 expiration
>
> 2014-10-21 15:53:11,987 [TestListener] DEBUG ActiveMQMessageConsumer
> .dequeue - ID:gd-57426-1413899591527-1:1:1:1 received expired message:
> MessageDispatch {commandId = 0, responseRequired = false, consumerId =
> ID:gd-57426-1413899591527-1:1:1:1, destination = queue://TEST, message =
> ActiveMQTextMessage {commandId = 9, responseRequired = false, messageId =
> ID:narsil104.narsil104-29953-1413889401564-3:3:1:1:5, originalDestination =
> null, originalTransactionId = null, producerId =
> ID:narsil104.narsil104-29953-1413889401564-3:3:1:1, destination =
> queue://TEST, transactionId = null, expiration = 1413898985466, timestamp =
> 1413898385466, arrival = 0, brokerInTime = 1413898385466, brokerOutTime =
> 1413898389795, correlationId = , replyTo = null, persistent = false, type =
> , priority = 0, groupID = null, groupSequence = 0, targetConsumerId = null,
> compressed = false, userID = null, content =
> org.apache.activemq.util.ByteSequence@642a590d, marshalledProperties =
> null, dataStructure = null, redeliveryCounter = 0, size = 0, properties =
> null, readOnlyProperties = true, readOnlyBody = true, droppable = false,
> jmsXGroupFirstForConsumer = false, text = Exp 5 min}, redeliveryCounter = 0
>

Reply via email to