RabbitMQ消息发布确任的三种方式
RabbitMQ消息发布确任的三种方式
单个确认
顾名思义就是消息生产方每发送一条消息,服务器都需要返回一条确认消息。
优点:每条消息都会进行确认,消息发送失败可以快速定位失败消息。
缺点:效率低
/**
* 单个确认.
*
* @throws Exception Exception
*/
public static void publishMessageIndividually() throws Exception {
Channel channel = RabbitMqUtils.getChannel();
String queueName = UUID.randomUUID().toString();
channel.queueDeclare(queueName, true, false, false, null);
channel.confirmSelect();
long begin = System.currentTimeMillis();
for (int i = 0; i < MESSAGE_COUNT; i++) {
String message = i + "Wk";
channel.basicPublish("", queueName, null, message.getBytes(StandardCharsets.UTF_8));
boolean flag = channel.waitForConfirms();
if (flag) {
System.out.println("消息发送成功");
}
}
long end = System.currentTimeMillis();
System.out.println("发布1000个单独确认消息耗时:" + (end - begin));
}
}
批量确认
可以设定生产方每发送n条消息,服务器返回一条确认信息。
优点:效率高
缺点:一旦出现消息发送失败,不容易确定是哪一条失败。
/**
* 批量发布确认.
*
* @throws Exception Exception
*/
public static void publishMessageBatch() throws Exception {
Channel channel = RabbitMqUtils.getChannel();
String queueName = UUID.randomUUID().toString();
channel.queueDeclare(queueName, true, false, false, null);
channel.confirmSelect();
long begin = System.currentTimeMillis();
//批量确认消息的长度.
int batchSize = 100;
for (int i = 0; i < MESSAGE_COUNT; i++) {
String message = i + "Wk";
channel.basicPublish("", queueName, null, message.getBytes(StandardCharsets.UTF_8));
if (i % batchSize == 0) {
channel.waitForConfirms();
}
}
long end = System.currentTimeMillis();
System.out.println("发布1000个批量确认消息耗时:" + (end - begin));
}
异步批量确认
即发送方不必等待上一条确认消息返回才开始发送下一条,确认消息和发送消息是异步行为。也是每条消息都进行确认。
优点:可以达到最佳的性能和资源使用,在出现问题的情况下可以很好地控制。
缺点:实现稍微难一点。
/**
* 异步确认.
*
* @throws Exception Exception
*/
public static void publishMessageAsync() throws Exception {
Channel channel = RabbitMqUtils.getChannel();
String queueName = UUID.randomUUID().toString();
channel.queueDeclare(queueName, true, false, false, null);
channel.confirmSelect();
/**
* 线程安全有序的一个map,适用于高并发的情况.
*/
ConcurrentSkipListMap<Long, String> concurrentSkipListMap =
new ConcurrentSkipListMap<>();
//消息确认成功回调
ConfirmCallback ackCallBack = (deliveryTag, multiple) -> {
if (multiple) {
ConcurrentSkipListMap<Long, String> confirmMap =
(ConcurrentSkipListMap<Long, String>) concurrentSkipListMap.headMap(deliveryTag);
confirmMap.clear();
}else {
concurrentSkipListMap.remove(deliveryTag);
}
System.out.println("确认的消息:" + deliveryTag);
};
//消息确认失败回调
ConfirmCallback nackCallBack = (deliveryTag, multiple) -> {
String message = concurrentSkipListMap.get(deliveryTag);
System.out.println("未确认的消息:" + deliveryTag);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
};
//消息的监听器,监听异步回调的信息.
channel.addConfirmListener(ackCallBack, nackCallBack);
long begin = System.currentTimeMillis();
//批量发消息.
for (int i = 0; i < MESSAGE_COUNT; i++) {
String message = i + "Wk";
channel.basicPublish("", queueName, null, message.getBytes(StandardCharsets.UTF_8));
System.out.println(i);
concurrentSkipListMap.put(channel.getNextPublishSeqNo(), message);
}
long end = System.currentTimeMillis();
System.out.println("发布1000个异步确认消息耗时:" + (end - begin));
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了