1、消息的可靠性投递方案
- 消息落库,对消息状态进行标识(存储到消息数据库上。对状态进行修改。适合并发量不高的情况下)
- 消息延迟投递,做二次确认,回调检查(推荐使用。可以减少多次DB的存储)
消费幂等性:
利用Redis的原子性去实现
confirm确认消息
生产者(指定消息投递模式,并设置消息应答监听)
public class ProductConfirem {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = ConnectionUtils.getConnection();
Channel channel = connection.createChannel();
//指定我们的消息投递模式:消息确认模式********************
channel.confirmSelect();
String exchange="confirem_muke";
String rokey="confirem.save";
channel.basicPublish(exchange,rokey,null,"这是个消息".getBytes());
//添加一个消息确认监听********************
channel.addConfirmListener(new ConfirmListener() {
/**
*
* @param l 第一个参数为这个消息的唯一标签
* @param b 是否批量的
* @throws IOException
*/
@Override
public void handleAck(long l, boolean b) throws IOException {
System.out.println("应答成功!"+l+"--->"+b);
}
@Override
public void handleNack(long l, boolean b) throws IOException {
System.out.println("应答失败!");
}
});
}
}
消费者(只需要消费消息就可以)
public class ConsumerConfirem {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = ConnectionUtils.getConnection();
Channel channel = connection.createChannel();
String queuename="confirm_queue";
String exchange="confirem_muke";
//声明队列,声明交换机,并将队列绑定到交换机上
channel.queueDeclare(queuename,true,false,false,null);
channel.exchangeDeclare(exchange,"topic",true);
channel.queueBind(queuename,exchange,"confirem.#");
DefaultConsumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(new String(body,"UTF-8"));
}
};
channel.basicConsume(queuename,true,consumer);
}
}
Return返回消息机制(多适用于没有找到路由key或者exchange)
如果设置return返回消息机制,就必须把Mandatory设置成true,监听器就会接收到路由不可达的消息。然后进行处理。如果为false了。那么broker端会自动删除消息。