The preface to the persistence problem of AMQ
In the previous AMQ topic, we found that for topic this type of message, even if the DeliveryMode is set to persistent, as long as the producer starts before the consumer. Messages that are published by the message producer are still lost. This is in accordance with the JMS specification.
Of course, as such an active open source message middleware, after implementing the JMS Basic specification, it is necessary to extend the way to implement topic persistent subscription.
The so-called DeliveryMode persistence and subscription persistence is still a two different concept. In this blog we will use examples to explore.
DeliveryMode Persistence
In the previous article, we set the producer.setDeliveryMode(DeliveryMode.PERSISTENT);
message passing attribute to persistent, when the message type was attempted, topic
regardless of the value setting, as soon as it was started Producer
, it was Consumer
not possible to get the original published topic after starting.
So what DeliveryMode
exactly is this for?
- Whether persistence in DeliveryMode refers to whether messages that were not consumed in the original queue or subject remain when the ACTIVEMQ is restarted
I have done the following tests myself through the code, and the test steps and results are as follows:
- Create the producer and set the producer DeliveryMode to persistent and run producer
- Restart ACTIVEMQ before the message is consumed by consumer
- Run consumer to discover messages sent producer before ACTIVEMQ restart
- Modify the producer, set the producer DeliveryMode to non-persistent, run the producer
- Restart ACTIVEMQ before the message is consumed by consumer
- Run consumer, without receiving any messages, the original producer generated message is lost
The persistent and non-persistent final queue consoles are as follows:
至此,不难发现,deliveryMode的是否持久化是针对activeMQ服务器是否重启而言的。对于不支持持久化的设置,当mq重启之后,没有被消费的消息就会丢失。而支持持久化的设置,只要消息没有被消费,重启mq,仍然能被新加入的consumer消费。
Subscription persistence
The specification for JMS is that there is no requirement to implement subscription persistence. Fortunately, ACTIVEMQ has achieved this feature. The personal view that the so-called subscription persistence is a pseudo-persistence relative to the persistence of messages. Let's take a look at a sample code without much explanation:
Producers
public class Simpleproducer {public static void main (string[] args) {//STEP1: Get Connection Factory ConnectionFactory ConnectionFactory = new Activemqconnectionfactory (Activemqconnection.default_user, Activemqconnection.defa Ult_password, Activemqconnection.default_broker_url); Connection Connection = null; Session session = NULL; MessageProducer topicproducer = null; Destination topicdestination = null; try {//STEP2: Get the connection from the connection factory and start the connection connection = Connectionfactory.createconnection (); Connection.start (); STEP3: Get session = Connection.createsession (false, Session.auto_acknowledge); STEP4: Create Theme topicdestination = Session.createtopic ("Kide-topic-demo"); STEP5: Create message producer Topicproducer = Session.createproducer (topicdestination); Topicproducer.setdeliverymode (Deliverymode.perSistent); Set to persistent//STEP6: Send message for (int i=0; i<20; i++) {TextMe Ssage message = session.createtextmessage ("Producer message:" + i); Topicproducer.send (message); }//STEP7: If the transaction is turned on, the session commit action//Session.commit () is required at this time; } catch (Exception e) {e.printstacktrace (); } finally {if (connection! = null) {try {connection.close (); } catch (JMSException e) {}}}}}
Consumers
public class Simpleconsumer {public static void main (string[] args) {//STEP1: Creating a connection Factory ConnectionFactory ConnectionFactory = new Activemqconnectionfactory (Activemqconnection.default_user, Activemqconnection.defa Ult_password, Activemqconnection.default_broker_url); Connection Connection = null; Session session = NULL; Messageconsumer topicconsumer = null; try {//STEP2: Get the connection from the connection factory and start the connection connection = Connectionfactory.createconnection (); Connection.setclientid ("1"); If you want to persist a subscription, you must set ClientID Connection.start () on the connection; STEP3: Get session = Connection.createsession (false, Session.auto_acknowledge); STEP4: Create persistent subscriber TopicSubscriber TopicSubscriber = Session.createdurablesubscriber (Session.createtopic ("KiDe- Topic-demo ")," 1 "); STEP5: Set message Receive listener Topicsubscriber.setmessagelisteneR (New MessageListener () {@Override public void OnMessage (Message Parammessa GE) {TextMessage message = (textmessage) parammessage; try {System.out.println ("Consumer receives subject message:" + message.gettext ()); } catch (JMSException e) {e.printstacktrace (); } } }); TimeUnit.SECONDS.sleep (200); Sleeps 200 seconds so that the client can receive the corresponding message} catch (Exception e) {e.printstacktrace (); } finally {if (connection! = null) {try {connection.close (); } catch (JMSException e) {}}}}}
Finally my verification steps and results are as follows:
- Run producer to send a topic message to ACTIVEMQ
- Run consumer and find no message received
- Run producer, at which point the running consumer receives the topic message
- Stop running consumer and re-run producer
- Rerun consumer, at which point consumer receives the message just producer generated
- When creating a consumer session, simultaneous creation of two sessions of the same ClientID will report the same channel is already occupied error
Analyzing the above steps, I end up with the following summary of this pseudo-persistent subscription :
To implement a pseudo-persistent subscription, you must first publish a persistent subscription message to ACTIVEMQ and identify the different subscription channels through ClientID.
If producer sends a topic message to MQ before publishing persisted subscription messages, consumer still can't receive
ACTIVEMQ determines whether the same persistent subscriber is based on two criteria: connection.setClientID("3")
ClientID in
and session.createDurableSubscriber(session.createTopic("KiDe-topic-Demo"), "12")
the name in the
Summarize
- deliverymode Persistence and subscription persistence is two different concepts that do not interfere with each other and combine to achieve business requirements
- need to figure out the actual meaning of the parameters first step, self-realistic example, See if the running results are consistent with your expectations. The second step is when the situation allows, read more about the source code, master the good coding and design