异步发送丢失场景:生产者设置了useAsyncSend=true,使用producer.send(message);持续发送消息。由于消息不阻塞,生产者会认为所有send的消息都被成功发送到MQ了。如果此时MQ突然宕机,生产者端内存中尚未发送至MQ的消息就会丢失。

所以,正确的异步发送方法是需要接收回调函数的。

同步和异步的区别就在这里,同步发送send不阻塞就一定发送成功,异步发送需要接收回调函数并由客户端再判断一次是否发送成功。

package com.wsy.activemq;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.ActiveMQMessageProducer;
import org.apache.activemq.AsyncCallback;

import javax.jms.*;
import java.util.UUID;

public class JmsProducer_Async {
public static final String ACTIVEMQ_URL = "tcp://192.168.0.123:61616";
public static final String QUEUE_NAME = "queue_asyncSend";

public static void main(String[] args) throws JMSException {
// 创建连接工厂,按照给定的url地址采用默认的用户名和密码
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
// 设置消息发送模式是AsyncSend模式
activeMQConnectionFactory.setUseAsyncSend(true);
// 通过连接工厂,获取Connection并启动
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
// 创建Session
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 创建目的地(目的地有两个子接口,分别是Queue和Topic)
Queue queue = session.createQueue(QUEUE_NAME);
// 创建消息生产者,生产的消息放到queue中
ActiveMQMessageProducer activeMQMessageProducer = (ActiveMQMessageProducer) session.createProducer(queue);
for (int i = 0; i < 3; i++) {
TextMessage textMessage = session.createTextMessage("message-" + i);
textMessage.setJMSMessageID(UUID.randomUUID().toString());
String messageID = textMessage.getJMSMessageID();
// 设置回调函数,通过回调函数判断是否发送成功,成功走onSuccess()方法,失败走onException()方法
activeMQMessageProducer.send(textMessage, new AsyncCallback() {
@Override
public void onSuccess() {
System.out.println(messageID + " success!");
}

@Override
public void onException(JMSException e) {
System.out.println(messageID + " fail!");
}
});
}
// 按照资源打开的相反顺序关闭资源
activeMQMessageProducer.close();
session.close();
connection.close();
}
}