activemq -- asynchronous delivery

Posted by nnichols on Mon, 20 Dec 2021 01:52:27 +0100

Asynchronous delivery

activemq supports synchronous and asynchronous sending modes to send messages to the broker. The choice of mode has a great impact on the sending delay. The output rate that producer can achieve (output rate = total amount of transmitted data / time) is mainly affected by the transmission delay. Using asynchronous transmission can significantly improve the transmission performance.

activemq uses asynchronous sending mode by default:

Unless the method of synchronous sending is explicitly specified or persistent messages are sent without using transactions, these two cases are synchronous sending to.

If transactions are not used and persistent messages are sent, each message is sent synchronously and the producer will be blocked until the broker returns an acknowledgement, indicating that the message has been safely persisted to the disk. The acknowledgement mechanism provides the guarantee of message security, but blocking the client also brings great delay.

Therefore, it is allowed to lose a small amount of data in case of failure, and asynchronous sending can be used to improve productivity.

Asynchronous sending can maximize the sending efficiency of producer. Generally, asynchronous sending is used when the number of messages sent is relatively dense, which can improve the performance of producer, but there will be additional problems:

It needs to consume more client memory, which will also increase the performance consumption of the broker, and can not effectively ensure the successful sending of messages.

Therefore, when userAsyncSend=true, the client needs to tolerate the possibility of message loss.

Configuration mode: there are 3 types

tcp://106.13.187.36:61616?jms.useAsyncSend=true
activeMQConnectionFactory.setUseAsyncSend(true);
((ActiveMQConnection) connection).setUseAsyncSend(true);

How can asynchronous sending ensure success

Scenario of asynchronous message loss:

Producer sets useAsyncSend=true and uses producer Send (MSG) keeps sending messages.

Since the message is not blocked, the producer will think that all sent messages are successfully sent to mq. However, if mq goes down suddenly, messages that are not sent in the memory of the producer will be lost.

Therefore, correct asynchronous sending requires receiving callback.

Difference between synchronous transmission and asynchronous transmission:

After the synchronous transmission is completed, if the send is not blocked, it means that the transmission is successful

After asynchronous sending, the client needs to receive the receipt and judge whether the sending is successful again

The callback is implemented through ActiveMQMessageProducer. The previous code uses the message sent by MessageProducer

public class JmsProducerAsyncSend {

    public static final String ACTIVEMQ_URL = "tcp://localhost61616";

    public static final String USERNAME = "admin";

    public static final String PASSWORD = "hll123";

    public static final String QUEUE_NAME = "queue01";

    public static void main(String[] args) throws Exception {
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(USERNAME, PASSWORD, ACTIVEMQ_URL);
        // Set asynchronous sending
        activeMQConnectionFactory.setUseAsyncSend(true);

        Connection connection = activeMQConnectionFactory.createConnection();
        connection.start();

        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

        Queue queue = session.createQueue(QUEUE_NAME);

        // Implementing callbacks using ActiveMQMessageProducer
        ActiveMQMessageProducer activeMQMessageProducer = (ActiveMQMessageProducer)session.createProducer(queue);
        TextMessage textMessage = null;

        for (int i = 1; i <= 3; i++) {
            textMessage = session.createTextMessage("message=" + i);
            // Set message id
            textMessage.setJMSMessageID(IdUtil.fastSimpleUUID() + "-callback");
            String msgId = textMessage.getJMSMessageID();

            // Implement asynchronous callback to confirm that the message is sent successfully
            activeMQMessageProducer.send(textMessage, new AsyncCallback() {
                @Override
                public void onSuccess() {
                    System.out.println(msgId + " success");
                }

                @Override
                public void onException(JMSException e) {
                    System.out.println(msgId + " error");
                }
            });
        }

        activeMQMessageProducer.close();
        session.close();
        connection.close();

        System.out.println(" **** Message sent to MQ complete **** ");
    }
}

Topics: ActiveMQ