rabbitmq是MQ中的一种,比较适用于一般的中小型公司。并发量可以达到1.2w+。
基础知识:
RabbitMQ的发送、接收端口一般为5672,管理接口15672。
RabbitMQ用TCP建立通信,但是TCP连接是十分消耗资源的,所以RabbitMQ引入了信道Channel的概念。信道Channel其实是TCP的虚连接,建在TCP之上,相对TCP来讲效率很高,用到了多路复用技术。
另外还引入了交换机,可以根据特定的场景选择特定的策略方式,主要由
Direct exchange:直连交换机,转发消息到routigKey指定的队列
Fanout exchange:扇形交换机,转发消息到所有绑定队列(速度最快)
Topic exchange:主题交换机,按规则转发消息(最灵活)
Headers exchange:首部交换机 (几乎用不到)
协议
RabbitMQ是实现AMQP(高级消息队列协议)的消息中间件的一种。AMQP是一种应用层的协议,类似于浏览器的http协议。扩展:其他常见的协议还有邮件SMTP,redis的RESP、FTP协议(传输大文件时可以考虑,传输效率高)。
原始的代码连接
---------------- 生产者端代码------ ----- ------- ------
1、创建连接 2、建立信道 3、创建交换器 4、发送带有路由键的消息
ConnectionFactory factory = new ConnectionFactory();
Factory.setHost(“127.0.0.1”);//默认端口5672
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();//建立信道
//1-信道中设置交换器(在生产者环节处理)
Channel.exchangeDeclare(“exchangeName”,BuitinExchangeType.DIRECT);/设置交换器类型为直连类型
//消息体
String msg = “hello.this is message”;
//2-发布消息
channel.basicPublish(“exchangeName”,”routeKey”,null,msg.getBytes());
Channel.close();
connection.close();
---------------- 消费端代码------ ----- ------- ------
1、建立连接 2、创建信道 3、创建交换器 4、创建队列 5、队列/交换器绑定 6、根据路由键消费消息 7、设置确认
ConnectionFactory factory = new ConnectionFactory();
Factory.setHost(“127.0.0.1”);//默认端口5672
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();//2创建信道
//3-声明交换器
Channel.exchangeDeclare(“exchangeName”,BuitinExchangeType.DIRECT);/设置交换器类型为直连
//4-声明队列(在消费者端做)
channel.queueDeclare(“queueName”,false,false,false)
//5-绑定交换与队列的绑定键 red为绑定键
channel.queueBind(“queueName”,”exchangeName”,”red”);
//6-声明一个消费者
final Consumer consumer = new DefaultConsumer(channel){
……
}
//7-设置自动确认参数 ,第二个参数autoAck如果是true就是自动确认
channel.basicConsume(queueName,true,consumer);
RabbitMQ消息可靠性保证
上图为MQ消息的整个流程,基于整个流程,主要由以下需要保证:
1、生产者确保消息到MQ,也就是上图的第一步。
2、确保消息经交换器路由到准确的队列,也就是上图的第二步。
3、确保消息在队列中正确存储,上图第三步。
4、确保消息从队列中正确投递到消费者,上图第四步。
一、确保消息到MQ
有两种方法:
事务模式:事务模式一般不推荐,因为意味着同步,同步又跟MQ三大优点中的异步违背,会导致性能降低。
确认模式:
主要分两步:
- 打开连接工厂的确认开关。一般在项目中使用配置的方式进行连接,如下。
-
RabbitTemplate发送后调用回调函数confirmCallback();
项目中一般使用org.springframework.amqp.rabbit.core.RabbitTemplate 进行发送消息,所以在template中设置回调确认方法。
二、路由保障
-
路由失败通知
org.springframework.amqp.rabbit.core.RabbitTemplate 中打开路由失败通知开关。
//开启路由失败通知
template.setMandatory(true);
//路由失败通知
template.setReturnCallback(returnCallback());
2、备用交换器
// 声明备用交换器
Map<String,Object> argsMap = new HashMap<String,Object>();
argsMap.put("alternate-exchange","Ae_exchange");
//备用交换器
channel.exchangeDeclare("Ae_exchange",BuiltinExchangeType.FANOUT);
三、消息正确存储
1、队列持久化。如下图,创建的时候默认是持久化的,所以rabbitmq重启后,队列还在
2、交换器持久化,跟队列一样,默认创建的时候是打开的。
3、消息持久化,消息默认也是持久化的。
四、消费确认(重点)
手动确认
消费者消息消费,使用一个继承了ChannelAwareMessageListner的监听类Receiver。
Receiver不像注解@ListenerRabbit的消费者那样发送给消费者就直接从队列中删除,而是有消费者确认后再从队列中删除,一旦发生异常,消费者可以将消息重新放入队列中重新发送给消费者消费。
消息的拒绝策略除了有nack外,还可以有reject方式,如下:
Receiver类要放到一个特定的rabbitmq的容器中,才会生效。