一、RabbitConfig配置
//定义多线程消费消息监听器factory
@Bean("mutiListenerFactory")
SimpleRabbitListenerContainerFactory mutiListenerFactory() {
SimpleRabbitListenerContainerFactory containerFactory = new SimpleRabbitListenerContainerFactory();
factoryConfigurer.configure(containerFactory, connectionFactory);
containerFactory.setConcurrentConsumers(10); //最小开启10个线程消费消息
containerFactory.setMessageConverter(new Jackson2JsonMessageConverter());
containerFactory.setPrefetchCount(10);
containerFactory.setMaxConcurrentConsumers(20);
containerFactory.setTxSize(10);
return containerFactory;
}
//1 死信队列
@Bean
public Queue deadQueue() {
HashMap<String, Object> args = new HashMap<>();
args.put("x-dead-letter-routing-key", environment.getProperty("rabbitMq.deadletter.routingkey")); //ttl过了后,发往
args.put("x-dead-letter-exchange", environment.getProperty("rabbitMq.deadletter.exchange"));
//args.put("x-message-ttl", 5000); //针对整个队列
//args.put("x-max-length",10); //队列长度
//args.put("x-overflow","reject-publish" ); //溢出直接拒绝
return new Queue(environment.getProperty("rabbitMq.deadletter.queue"), true, false, false, args);
}
//2 死信交换机
@Bean
public TopicExchange realDeadExchange() {
return new TopicExchange(environment.getProperty("rabbitMq.realQueue.exchange"), true, false);
}
//3死信rountingkey绑定
@Bean
public Binding deadBinding() {
return BindingBuilder.bind(deadQueue()).to(realDeadExchange()).with(environment.getProperty("rabbitMq.realQueue.routingkey"));
}
//3.接收死信的队列
@Bean
public Queue recvieDeadMsgQueue() {
return new Queue("dead.msg.queue",true,false,false);
}
//4.接收死信的交换机 与 死队列绑定交换器一致
@Bean
public TopicExchange recvieDeadMsgExchange() {
return new TopicExchange(environment.getProperty("rabbitMq.deadletter.exchange"), true, false);
}
//5.接收死信消息
@Bean
public Binding recvieDeadMsgBinding() {
return BindingBuilder.bind(recvieDeadMsgQueue()).to(recvieDeadMsgExchange()).with(environment.getProperty("rabbitMq.deadletter.routingkey"));
}
二、生产端
//确认机制
private final ConfirmCallback confirmCallback = new ConfirmCallback() {
@Override
public void confirm(CorrelationData correlationData, boolean ack, String s) {
log.info("correlationData: {}",correlationData);
log.info("ack: {} ",ack);
if(!ack){
//做一些补偿机制等
correlationData.getId(); //获取中奖信息ID 然后再去数据查询来,做其它操作
log.info("异常处理....");
}
}
};
//回调机制
private final ReturnCallback returnCallback = new ReturnCallback() {
@Override
public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
log.info("return exchange: " + exchange + ", routingKey: "
+ routingKey + ", replyCode: " + replyCode + ", replyText: " + replyText);
//操作......
}
};
//发送消息
Message message = MessageBuilder.withBody(objectMapper.writeValueAsBytes(gameLotteryInfoEnity)).
setDeliveryMode(MessageDeliveryMode.PERSISTENT).setContentEncoding("UTF-8").setContentType("application/json")
.setExpiration("15000").build(); //setExpiration针对本消息
rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
rabbitTemplate.setConfirmCallback(confirmCallback);
rabbitTemplate.setReturnCallback(returnCallback);
CorrelationData correlationData = new CorrelationData(gameGiftInfoEnity.getId()+"");
//exchange, routingKey, object, correlationData
rabbitTemplate.convertAndSend(environment.getProperty("rabbitMq.realQueue.exchange"), environment.getProperty("rabbitMq.realQueue.routingkey"), message, correlationData);
三、消费端
@RabbitListener(queues = "dead.msg.queue",containerFactory = "mutiListenerFactory")
public void receiverDirectQueue(@Payload Message message, Channel channel, @Headers Map<String,Object> headers) throws IOException {
log.info("msg1 : {}", message);
try {
channel.basicAck((Long)headers.get(AmqpHeaders.DELIVERY_TAG), true); //确认消息
gameLotteryInfoMapper.insert(objectMapper.readValue(message.getBody(), GameLotteryInfoEnity.class));
} catch (IOException e) {
log.info("处理中奖消息发生异常,重新把消息放入队列");
channel.basicNack((Long)headers.get(AmqpHeaders.DELIVERY_TAG), true, true);
}
}