JMS Message Handling Scenarios
I am coming through the Solace docs trying to figure out the differences between various JMS pub/sub configurations and how the message and acks would be handled.
Here are my scenarios. What I am trying to identify is when an ack is sent, when a message is spooled to disk vs retained in memory, and when/how a message may be lost/discarded.
S1: JMS pub topic w/ direct mode -> Durable queue w/ matching topic sub -> JMS cons
S2: JMS pub topic w/ non-persisted mode -> Durable queue w/ matching topic sub -> JMS cons
S3: JMS pub topic w/ persisted mode -> Durable queue w/ matching topic sub -> JMS cons
Thanks
Best Answer
-
Hi @arm, yes, you caught me out here. I was hoping to gloss over this
In Solace, we have DIRECT and GUARANTEED.
In JMS, there is PERSISTENT and NON-PERSISTENT.
We can map PERSISTENT to GUARANTEED no problem. An unfortunate side effect of the JMS spec is an implicit synchronous acknowledgement of the published message. This clobbers publisher performance quite badly, especially if the network round trip time is high, so if you send PERSISTENT in JMS you will suffer this problem.
There isn't such an easy mapping of NON-PERSISTENT to DIRECT. As you say, we have a Solace specific connection factory setting that allows you to specify what happens to NON-PERSISTENT messages: should we use DIRECT or GUARANTEED. And, as you say, if we enable GUARANTEED we don't have to use synchronous acknowledgement, which results in much higher performance as we can use Solace's windowed acknowledgement mechanism for guaranteed messages. We call this "streaming JMS." It's a Solace secret sauce.
It's important to remember that we are mapping to Solace delivery modes. So if direct is set to false, the acknowledgement works just as it does for any other GUARANTEED interaction: the acknowledgement is only ever returned once the message has been successfully persisted. The broker has taken responsibility for the message.
Similarly, if the producer crashes after sending a GUARANTEED message but before an acknowledgement has been received, the producer is in an unknown state. It doesn't know whether the messsages have been received by the broker. Fortunately, there's an approach that can help: the Last Value Queue (LVQ). An LVQ is simply a queue that has its spool size set to 0. It will store one message - the last message published. So your publisher, when it reconnects, can interrogate (browse) the LVQ to work out what the last successful message it sent was.
0
Answers
-
Hi @arm, this is always a bit of a tricky topic. In Solace we do something called message "promotion" and "demotion" which is how messages cross levels of persistence. Solace does not have any kind of "semi persistence" where messages are "queued" but only in memory - in the Solace world, messages are either persisted or they are not.
Taking your scenarios:
S1: JMS pub topic w/ direct mode: no ack to publisher so message may be lost, for instance if the destination queue is full.
-> Durable queue w matching topic sub: message promoted to "non-persistent", message saved to queue and to disk. At this point the message is now fully persisted and will not be lost
-> JMS Cons: must ack the message before it is remoevd from the queue.S2: Essentially identical. There is no ack to the publisher, so the message can be lost at this stage, otherwise the message is fully persisted to disk when it lands on the queue.
S3: No message loss, acked at every stage.
0 -
Thanks @TomF
Follow on question for S2, you state that "There is no ack to the publisher" but according to Solace site on guaranteed transport, there is an ack sent back when a publisher publishes as non-persistent and the connection factory setting for "Direct Transport for Non-persistent Messages" is set to false (https://docs.solace.com/Solace-JMS-API/Message-Transport-Modes.htm?Highlight=guaranteed transport).
My understanding is there are two transport modes for JMS published non-persistent messages; direct transport and guaranteed transport. When "Direct Transport for Non-persistent Messages" is set to true the direct transport mode is used but when false the guaranteed transport mode is use, which includes an ack back to the producer.
The only difference I can ascertain between JMS persisted publishing and JMS non-persisted publishing (with Direct Transport for Non-persistent Messages set to false) is that the when publishing in persisted mode it uses a synchronous call where an ack has to be returned from the broker before the next message can be sent where non-persistent publishers have a publish window size (up to 255) which allows for asynchronous sending (my assumption) up to 255 messages can be in pending ack state.
I did some testing using sdkperf against a VMR and verified there is performance difference between the three configurations as expected; persisted ~ 100mps, non-persisted w/ Direct Transport for Non-persistent Messages set to false ~ 1000 mps, non-persisted w/ Direct Transport for Non-persistent Messages set to true ~ 2000+ mps
Can you please verify this and help me understand if there is any difference between S2 and S2 regarding message loss? If a producer or the broker disconnects/crashes while the producer is sending using on-persisted w/ Direct Transport for Non-persistent Messages set to false, will the messages in flight pending acks be lost? Also, with on-persisted w/ Direct Transport for Non-persistent Messages set to false does the ack get returned before or after the non-persisted message is spooled to disk?
Thanks in advance
0 -
Hi @arm, yes, you caught me out here. I was hoping to gloss over this
In Solace, we have DIRECT and GUARANTEED.
In JMS, there is PERSISTENT and NON-PERSISTENT.
We can map PERSISTENT to GUARANTEED no problem. An unfortunate side effect of the JMS spec is an implicit synchronous acknowledgement of the published message. This clobbers publisher performance quite badly, especially if the network round trip time is high, so if you send PERSISTENT in JMS you will suffer this problem.
There isn't such an easy mapping of NON-PERSISTENT to DIRECT. As you say, we have a Solace specific connection factory setting that allows you to specify what happens to NON-PERSISTENT messages: should we use DIRECT or GUARANTEED. And, as you say, if we enable GUARANTEED we don't have to use synchronous acknowledgement, which results in much higher performance as we can use Solace's windowed acknowledgement mechanism for guaranteed messages. We call this "streaming JMS." It's a Solace secret sauce.
It's important to remember that we are mapping to Solace delivery modes. So if direct is set to false, the acknowledgement works just as it does for any other GUARANTEED interaction: the acknowledgement is only ever returned once the message has been successfully persisted. The broker has taken responsibility for the message.
Similarly, if the producer crashes after sending a GUARANTEED message but before an acknowledgement has been received, the producer is in an unknown state. It doesn't know whether the messsages have been received by the broker. Fortunately, there's an approach that can help: the Last Value Queue (LVQ). An LVQ is simply a queue that has its spool size set to 0. It will store one message - the last message published. So your publisher, when it reconnects, can interrogate (browse) the LVQ to work out what the last successful message it sent was.
0