RabbitMQ接收端
1,application.yml的配置
#MQ消息队列
rabbitmq:
# 消息确认(ACK)
# publisher-confirm-type: correlated #确认消息已发送到交换机(Exchange),会返回一个ack确认码
# publisher-returns: true #确认消息已发送到队列(Queue)
listener: #加了2下面2个属性,消费消息的时候,就必须发送ack确认,不然消息永远还在队列中
direct:
acknowledge-mode: manual
retry: # 是否启用发布重试
enabled: true
simple:
acknowledge-mode: manual
concurrency: 5
max-concurrency: 10
retry:
enabled: true
2,实现类
@Slf4j
@Component()
public class BctDataReceiver {
// 存放接收处理失败的消息次数
private static ConcurrentMap<String, Integer> concurrentMap = new ConcurrentHashMap<>();
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue(value = "SWAP_REGULATION_QUEUE", durable = "true"),
exchange = @Exchange(value = "SWAP_REGULATION"),
key = "swap.regulation")
})
public void handleSwap(Message message, Channel channel) throws IOException, InterruptedException {
// 接受JSON形式的mq
String json = JsonUtils.mapper.readValue(message.getBody(), String.class);
User user= JsonUtils.mapper.readValue(json, User.class);
log.info("bctDataDTO:{}", user.toString());
//mq重复失败问题处理
if (concurrentMap.containsKey(user.getName())) {
Integer value = concurrentMap.get(user.getName());
if (value <= 5) {
//log.error("消息已重复处理失败,拒绝再次接收...");
//channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
concurrentMap.put(user.getName(), ++value);
log.error("消息已重复处理失败{}次,睡眠60s再次返回队列...", value);
TimeUnit.SECONDS.sleep(60);
log.info("60s睡眠结束");
// 重新放入队列
channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
return;
} else {
concurrentMap.remove(user.getName());
}
}
try{
// mq接收数据的处理逻辑
.............
}catch (Exception e) {
e.printStackTrace();
log.error(e.getMessage());
// 拒绝确认接收
concurrentMap.putIfAbsent(user.getName(), 1);
channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
log.error("消息失败即将再次返回队列处理...");
}
}
}