I have a producer send msg to a ActiveMQ broker, and a consumer subscribe from the same topic. I know that the broker can persist the msg, so as soon as the msg reaches the broker, it can be guaranteed available for the consumer. (right?)
But what happen if the network between producer and ActiveMQ broker is broken, in this case is there a way to guarantee the at-least-once sent? like, the producer itself can persist msg before sending to the ActiveMQ broker?
In order for the guarantee to be established the message must reach the broker, if the network is down then the burden is on you to capture the send error and retry the send at a later time. The ActiveMQ client offers no persistent storage for what it sends, you can use the failover transport and the client will retry the send on reconnect but it the application is shutdown and you haven't provided some means of recovery on restart then there isn't anything more the client can do.
Related
I read following quote from ActiveMQ documentation here:
The downside to using synchronous message delivery is that the
producer is more likely to block if there is a slow consumer that he
is dispatching messages to.
But I don't understand how the producers, in general, can be blocked because of slow consumer, because my understanding is that a JMS client (producer) will send a message to a queue of a ActiveMQ instance (broker) and that's it, now producer is free or in other words producer thread which sent the message is free to complete/die. Then there will be some other JMS clients (consumers) listening for that queue, now as soon as message arrives to the broker, broker will send it to the listening consumers.
Now, in all this where producer is dependent upon consumer?
When a producer send a persistent message to the broker the broker must write that message to disk before sending back an acknowledge to the producer to let it know what it's message is safely stored away for later dispatch to a consumer. In the case of a slow consumer the producer might eventually run into a case where the broker has reached a resource limit and cannot store that message either on the Queue in memory or on disk, it all depends on the broker's configuration.
The the producer isn't so much tied to the consumer as it is to the resources on the broker needed to hold the message until it has been consumed.
Is there a way to set timeout for sending a message to broker.
I want to send large messages to ActiveMQ broker but I do not want it to take forever, so I was planning to set a timeout while sending message.
you can set connection.sendTimeout=some ms in URI while connecting to broker
Official document for sendTimeout says
Time to wait on Message Sends for a Response, default value of zero
indicates to wait forever. Waiting forever allows the broker to have
flow control over messages coming from this client if it is a fast
producer or there is no consumer such that the broker would run out
of memory if it did not slow down the producer. Does not affect Stomp
clients as the sends are ack'd by the broker. (Since ActiveMQ-CPP
2.2.1)
here is the documentation https://activemq.apache.org/components/cms/configuring
hope this helps!
Good luck!
Is it possible to use CLIENT_ACKNOWLEDGE in producer side in JMS? Then what does it mean? I mean acknowledging is something in consumer side.
No, message acknowledgement is purely a consumer side concept. When creating a JMS Session you have the choice among several acknowledgment modes. The idea behind message acknowledgement has to do with the concept of guaranteed delivery in message oriented middleware (MOM). In short, when you send a message via a MOM implementation, that message will be persisted (by the producer) until it is sent to a consumer AND the consumer acknowledges its delivery (or until the message expires). In the event that an acknowledgement is not received by the consumer within some reasonable amount of time the message is re-sent by the producer. Each mode impacts message delivery differently.
In AUTO_ACKNOWLEDGE mode, any messages received by consumers through the session will be acknowledged automatically by the consumers underlying JMS runtime upon reception.
In CLIENT_ACKNOWLEDGE mode, each message received by consumers through the session must be explicitly acknowledged. This means that the responsibility of acknowledging a message falls on the application instead of the JMS runtime. Typically the consumer needs to invoke the acknowledge() method on the session after processing the message in the onMessage() method.
There is also a DUPS_OK_ACKNOWLEDGE setting that is similar to AUTO_ACKNOWLEDGE but instead acknowledgements are sent by the JMS implementation lazily, potentially causing duplicate reception of messages.
Typically you would use CLIENT_ACKNOWLEDGE mode when you need to have explicit control over the acknowledgement of messages.
I am using ActiveMQ as a JMS implementation server in my application. Scenario is like, there is a topic over which I have many durable subscribers which consumes the published message and a message listener which save the data from message object to central DB server. There is a producer thread which keeps on publishing persistent message over the same topic. I am using KahaDB for persistent Message Store. As soon as a message is published, kahaDB creates a data log file in message store to persist message until all durable subscriber consume it. I want to know if at any point, I shutdown the JMS server and delete all the data log files, what would be the impact. Will it be just that few durable subscriers will not receive a message which was there in data log files for them to be consumed or is there a possibility that few message didn't got saved in central database which is done by message listener over this topic.
Any hint or help is greatly appreciated......
Thanks in advance.
If you stop and start your broker, regardless of whether you delete your data files or not, topic consumer that have not already received a published message will no longer receive it. The reason behind this is that messages sent to a topic will not be written out to the persistent message store.
Durability and persistence are not the same things. A durable subscription tells the broker to preserve the subscription state in case the subscriber disconnects - any messages sent while the consumer is disconnected will be kept around. A non-durable subscription on the other hand is finite; if a subscriber disconnects, it missed any messages sent in the interim. All messages are stored in memory, and will not survive a broker restart.
Message persistence on the other hand stores messages for eventual delivery. This guards against catastrophic failure, or for later delivery to consumers who might not yet be active.
If you want to broadcast messages using pub-sub, and have the subscriptions appear durable and survive broker restarts you should use virtual destinations instead of durable subscriptions.
No messages, persistent or non-persistent, will survive switching the broker off and deleting the data directory.
I'm dealing with a standalone MQ JMS application, our app need to "aware" that client already consumed the message producer put on the queue. Because client app is not responsible by us. So we cannot let them to write something like "msg.acknowledge();" thing on their side (msg.acknowledge() is not the right approach on my condition.). I search the history answer in the stackoverflow. Find following is quite the same what I want:
https://stackoverflow.com/questions/6521117/how-to-guarantee-delivery-of-the-message-in-jms
Do the JMS spec or the various implementations support delivery confirmation of messages?
My question is, is there any other way to archive this in the MQ API or JMS API? I need to do the coding only on the msg produce side, it is can be queue or topic.
Another question is in the JMS the acknowledge mode CLIENT_ACKNOWLEDGE, is that produce irrelevant? I always believe that this mode can block the application when call send() method until the client consume the message and call the msg.acknowledge(), but seems not like that. The produce just exit the app after message be delivered, and the message just store in the queue until client call the acknowledge(). Is that possible let the producer app hang there wait until the message be acknowledged by the client?
If my concept is not right, just correct me, thanks.
The main intention of message queuing is to decouple producer and consumer. Producer does not need to wait for the message to be consumed by the consumer, it can continue it's job. Ideally if producer needs to know if the message has been processed by consumer or not, it should wait for consumer to send a response message on another queue.
Message acknowledgement has nothing to do with producer. Message acknowledgement is the way a consumer tells the messaging provider to remove the message from a queue after the message has been delivered to an application.
There is auto acknowledge where the JMS providers (like MQ JMS), after delivering message to an application, tell the messaging provider to remove the message from queue. Then there is client acknowledge where, after receiving a message, the application explicitly tells the messaging provider to remove message from a queue.
Is there is a reason why the producer has to wait for consumer to receive the message? One way, though not elegant, could be: Once the message is sent, use the message id of the sent message and try to browse for that message. If message is not found, you can assume it has been consumed