消费者接收消息时突然挂掉,为了保证数据不丢失。引入消息应答机制
1.消费者接收消息时手动应答,不进行批处理,批处理时,处理多个消息,而消息是否被处理完成并不知晓,所以关闭批处理。
2.消息自动重新入队:消息未发送ack确认,RabbitMQ了解消息未处理,对消息进行重新排队处理,某个挂掉的消费者处理得任务重新交给其他工作完成的消费者处理。
生产者
package com.zhaoye.three;
import com.rabbitmq.client.Channel;
import com.zhaoye.utils.RabbitMqUtils;
import java.util.Scanner;
/**
* @author feng
* @Date 2021/11/3 15:37
* 消息应答机制:消息不丢失,消息丢失时放入队列重新进行消费
*/
public class Task2 {
public static final String TASK_QUEUE_NAME = "ack_queue";
public static void main(String[] args) throws Exception {
Channel channel = RabbitMqUtils.getChannel();
channel.queueDeclare(TASK_QUEUE_NAME, false, false, false, null);
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
String message = scanner.next();
channel.basicPublish("", TASK_QUEUE_NAME, null, message.getBytes("UTF-8"));
System.out.println("消息发送完成" + message);
}
}
}
消费者c1
package com.zhaoye.three;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;
import com.rabbitmq.client.Delivery;
import com.zhaoye.utils.RabbitMqUtils;
import com.zhaoye.utils.SleepUtils;
/**
* @author feng
* @Date 2021/11/3 15:48
*/
public class work03 {
public static final String TASK_QUEUE_NAME = "ack_queue";
public static void main(String[] args) throws Exception {
Channel channel = RabbitMqUtils.getChannel();
System.out.println("c1接收消息时间较短");
DeliverCallback deliverCallback = (consumerTag,message)->{
//沉睡1s
SleepUtils.sleep(1);
System.out.println("接收到的消息" + new String(message.getBody(),"UTF-8"));
//接收到消息后,手动应答确认
/** 1.@tag 消息的标记
* 2.不进行批量应答
*/
channel.basicAck(message.getEnvelope().getDeliveryTag(),false);
};
CancelCallback cancelCallback = (consumerTag)->{
System.out.println("消费者取消消息接口逻辑");
};
//关闭自动应答
boolean actoAck = false;
channel.basicConsume(TASK_QUEUE_NAME,actoAck,deliverCallback,cancelCallback);
}
}
消费者c2
package com.zhaoye.three;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;
import com.zhaoye.utils.RabbitMqUtils;
import com.zhaoye.utils.SleepUtils;
/**
* @author feng
* @Date 2021/11/3 15:48
*/
public class work04 {
public static final String TASK_QUEUE_NAME = "ack_queue";
public static void main(String[] args) throws Exception {
Channel channel = RabbitMqUtils.getChannel();
System.out.println("c2接收消息时间较长");
DeliverCallback deliverCallback = (consumerTag,message)->{
//沉睡30s
SleepUtils.sleep(30);
System.out.println("接收到的消息" + new String(message.getBody(),"UTF-8"));
//接收到消息后,手动应答确认
/** 1.@tag 消息的标记
* 2.不进行批量应答
*/
channel.basicAck(message.getEnvelope().getDeliveryTag(),false);
};
CancelCallback cancelCallback = (consumerTag)->{
System.out.println("消费者取消消息接口逻辑");
};
//关闭自动应答
boolean actoAck = false;
channel.basicConsume(TASK_QUEUE_NAME,actoAck,deliverCallback,cancelCallback);
}
}
c2在处理dd时突然挂掉,挂掉之后,消息重新回到队列,c1处理消息
c1接收消息时间较短
接收到的消息aa
接收到的消息cc
接收到的消息dd
c2
c2接收消息时间较长
接收到的消息bb