准备代码 生产Channel的工具类
public static Channel getChannel() {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setUsername("guest");
factory.setPassword("guest");
try {
connection = factory.newConnection();
channel = connection.createChannel();
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
return channel;
}
(一)、单个消息确认
重点代码
//消息确认
boolean flag = channel.waitForConfirms();
Channel channel = RabbitUtils.getChannel();
channel.queueDeclare(PUBLISH_QUEUE, true, false, false, null);
//开启发布确认
channel.confirmSelect();
long begin = System.currentTimeMillis();
for (int i = 0; i < MESSAGE_NUM; i++) {
String message = i+"";
channel.basicPublish("", PUBLISH_QUEUE, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes("UTF-8"));
//单个消息马上进行确认
boolean flag = channel.waitForConfirms();
if (flag) {
System.out.println("消息被确认 = " + message);
}
}
long end = System.currentTimeMillis();
System.out.println("end-begin = " + (end - begin));
(二)、批量确认
重点代码
boolean flag = channel.waitForConfirms();
public static void publishMessageBatch() throws Exception {
Channel channel = RabbitUtils.getChannel();
channel.queueDeclare(PUBLISH_QUEUE, true, false, false, null);
//开启发布确认
channel.confirmSelect();
long begin = System.currentTimeMillis();
for (int i = 0; i < MESSAGE_NUM; i++) {
String message = i+"";
channel.basicPublish("", PUBLISH_QUEUE, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes("UTF-8"));
if (i % 100 == 0) {
boolean flag = channel.waitForConfirms();
System.out.println("消息被确认 = " + message);
}
}
long end = System.currentTimeMillis();
System.out.println("批量确认时间 :end-begin = " + (end - begin));
}
(三)、异步确认
重点代码:
//监听确认回调和未确认回调
channel.addConfirmListener(confirmCallback, nackCallback);
完整代码:
public static void publishMessageAsync() throws Exception {
Channel channel = RabbitUtils.getChannel();
channel.queueDeclare(PUBLISH_QUEUE, true, false, false, null);
//开启发布确认
channel.confirmSelect();
//消息确认成功回调
ConfirmCallback confirmCallback = (deliveryTag, multiple) ->{
System.out.println("已确认的消息" + deliveryTag);
};
//消息确认失败回调
//deliveryTag : 消息的标记
//multiple : 是否批量确认
ConfirmCallback nackCallback = (deliveryTag, multiple)->{
System.out.println("未确认的消息" + deliveryTag);
};
//开启消息监听,监听哪些消息成功,哪些消息失败
channel.addConfirmListener(confirmCallback, nackCallback);
long begin = System.currentTimeMillis();
for (int i = 0; i < MESSAGE_NUM; i++) {
String message = i+"";
channel.basicPublish("", PUBLISH_QUEUE, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes("UTF-8"));
}
long end = System.currentTimeMillis();
System.out.println("异步确认时间 :end-begin = " + (end - begin));
}
异步确认优化:
记录所有消息的标记和内容,然后判断哪些消息被接收到哪些没有
重点代码
1、创建一个ConcurrentSkipListMap存放消息的序号和消息
/*
* 线程安全有序的一个哈希表,适用于高并发情况下
* 优点1:能很好的将序号(key)和消息(value)关联起来
* 优点2:轻松批量删除条目,只要给到序号
* 优点3:适用于高并发(多线程)
* */
ConcurrentSkipListMap<Long, String> outstandingConfirms= new ConcurrentSkipListMap<>();
public static void publishMessageAsync() throws Exception {
Channel channel = RabbitUtils.getChannel();
channel.queueDeclare(PUBLISH_QUEUE, true, false, false, null);
//开启发布确认
channel.confirmSelect();
/*
* 线程安全有序的一个哈希表,适用于高并发情况下
* 优点1:能很好的将序号(key)和消息(value)关联起来
* 优点2:轻松批量删除条目,只要给到序号
* 优点3:适用于高并发(多线程)
* */
ConcurrentSkipListMap<Long, String> outstandingConfirms= new ConcurrentSkipListMap<>();
//消息确认成功回调
ConfirmCallback confirmCallback = (deliveryTag, multiple) ->{
if (multiple) {
ConcurrentNavigableMap<Long, String> confirmed = outstandingConfirms.headMap(deliveryTag);
confirmed.clear();
} else {
outstandingConfirms.remove(deliveryTag);
}
System.out.println("已确认的消息" + deliveryTag);
};
//消息确认失败回调
//deliveryTag : 消息的标记
//multiple : 是否批量确认
ConfirmCallback nackCallback = (deliveryTag, multiple)->{
System.out.println("未确认的消息" + deliveryTag);
System.out.println("outstandingConfirms = " + outstandingConfirms);
};
//开启消息监听,监听哪些消息成功,哪些消息失败
channel.addConfirmListener(confirmCallback, nackCallback);
long begin = System.currentTimeMillis();
for (int i = 0; i < MESSAGE_NUM; i++) {
String message = i+"";
channel.basicPublish("", PUBLISH_QUEUE, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes("UTF-8"));
//outstandingConfirms中存放序号和消息
outstandingConfirms.put(channel.getNextPublishSeqNo(), message);
}
long end = System.currentTimeMillis();
System.out.println("异步确认时间 :end-begin = " + (end - begin));
}