(内容来源于蚂蚁课堂)
1.消费者如何确保消息一定被消费成功?
通过手动应答(默认自动应答)
2.RabbitMQ服务器宕机了,消息会丢失吗?
默认会丢失,需要设置持久化 durable=true;
3.如何确保生产者一定会投递到MQ服务上?
生产者发送消息出去之后,不知道到底有没有发送到RabbitMQ服务器, 默认是不知道的。而且有的时候我们在发送消息之后,后 面的逻辑出问题了,我们不想要发送之前的消息了,需要撤回该怎么做。
解决方案:
①AMQP 事务机制
②Confirm 模式
事务模式:
txSelect 将当前channel设置为transaction模式
txCommit 提交当前事务
txRollback 事务回滚
生产者代码:在信息发布代码后,加一行异常代码。
运行,消息会投递失败
package com.google.util.amqp;
import com.google.util.MQConnectionUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* @author wk
* @Description:amqp事务机制 生产者
* @date 2019/12/12 14:12
**/
public class Producer {
//队列名称
private static final String QUEUE_NAME = "AMQP_QUEUE";
public static void main(String[] args) throws IOException, TimeoutException {
System.out.println("AMQP事务机制-生产者启动!");
//创建连接
Connection connection = MQConnectionUtils.newConnection();
//创建通道
Channel channel = connection.createChannel();
//声明队列
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
channel.txSelect();//开启事务
try {
//发布消息
String msg = "AMQP事务机制发布的消息哦!开启事务";
channel.basicPublish("", QUEUE_NAME, null, msg.getBytes());
//不加事务的情况,消息会发布成功,消费者可以接收到
@SuppressWarnings("unused") int i = 1 / 0;
channel.txCommit();//提交事务
} catch (Exception e) {
e.printStackTrace();
channel.txRollback();//回滚事务
} finally {
channel.close();
connection.close();
}
}
}
消费者代码:
package com.google.util.amqp;
import com.google.util.MQConnectionUtils;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* @author wk
* @Description:amqp事务机制 消费者
* @date 2019/12/12 14:13
**/
public class Consumer {
//队列名称
private static final String QUEUE_NAME = "AMQP_QUEUE";
public static void main(String[] args) throws IOException, TimeoutException {
System.out.println("AMQP-消费者启动!");
//创建通道
Channel channel = MQConnectionUtils.getChannel();
//声明消息队列
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
//监听获取消息
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
throws IOException {
String msg = new String(body, "UTF-8");
System.out.println("AMQP事务机制-消费者获取信息:" + msg);
//手动应答模式,
channel.basicAck(envelope.getDeliveryTag(), false);
}
};
//设置应答模式 如果为true情况下,表示为自动应答模式 false表示为手动应答 监听队列
//channel.basicConsume(queue, true, defaultConsumer);
// [ˈbeɪsɪk] 悲sei克
//默认false
channel.basicConsume(QUEUE_NAME, defaultConsumer);
}
}