MQ简介
-
MQ全称为Message Queue,消息队列(MQ)是一种应用程序对应用程序的通信方法。应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们。
-
消息传递指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,直接调用通常是用于诸如远程过程调用的技术。排队指的是应用程序通过队列来通信。队列的使用除去了接收和发送应用程序同时执行的要求。
-
同步调用
- A服务调用B服务,需要等待B服务执行完毕的返回值,A服务才可以继续往下执行
- 同步调用可以通过REST和RCP完成
- REST: ribbon、Feign
- RCP:Dubbo
-
异步调用
- A服务调用B服务,而无需等待B服务的执行结果,也就是说在B服务执行的同时A服务可以继续往下执行
- 通过消息队列实现异步调用
4.1 RabbitMQ介绍
- RabbitMQ是一个在AMQP基础上完成的,可复用的企业消息系统。他遵循Mozilla Public License开源协议。
- AMQP,即Advanced Message Queuing Protocol, 一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同的开发语言等条件的限制。Erlang中的实现有 RabbitMQ等。
- 主要特性:
- 保证可靠性:使用一些机制来保证可靠性,如持久化、传输确认、发布确认
- 灵活的路由功能
- 可伸缩性:支持消息集群,多台RabbitMQ服务器可以组成一个集群
- 高可用性:RabbitMQ集群中的某个节点出现问题时队列任然可用
- 支持多种协议
- 支持多语言客户端
- 提供良好的管理界面
- 提供跟踪机制:如果消息出现异常,可以通过跟踪机制分析异常原因
- 提供插件机制:可通过插件进行多方面扩展
RabbitMQ工作模式
-
简单模式:
做某事 的最简单的事情
一个队列只有一个消费者,生产者将消息发送到队列,消费者从队列取出数据 -
工作模式:
在工人之间分配任务(竞争的消费者模式)
多个消费者监听同一个队列,多个消费者监听同一个队列,但多个消费者中只有一个消费者会成功的消费消息 -
发布/订阅模式:
一次向许多消费者发送消息
一个交换机绑定多个消息队列,每个消息队列有一个消费者监听,消息生产者发送的消息可以被每一个消费者接收 -
路由模式:
有选择地接收消息
一个交换机绑定多个消息队列,每个消息队列都由自己唯一的key,每个消息队列有一个消费者监听@Service public class TestService { @Resource private AmqpTemplate amqpTemplate; public void sendMsg(String msg){ //1. 发送消息到队列 amqpTemplate.convertAndSend("queue1",msg); //2. 发送消息到交换机(订阅交换机) amqpTemplate.convertAndSend("ex1","",msg); //3. 发送消息到交换机(路由交换机) amqpTemplate.convertAndSend("ex2","a",msg); } }
@Service //@RabbitListener(queues = {"queue1","queue2"}) @RabbitListener(queues = "queue1") public class ReceiveMsgService { @RabbitHandler public void receiveMsg(String msg){ System.out.println("接收MSG:"+msg); } }
使用RabbitMQ传递对象
使用序列化对象
使用序列化字节数组
使用JSON字符串传递
消息的可靠性
- RabbitMQ事务
当在消息发送过程中添加了事务,处理效率降低几十倍甚至上百倍
channel.txSelect(); //开启事务
try{
channel.basicPublish("ex4", "k1", null, msg.getBytes());
System.out.println("发送:" + msg);
channel.txCommit(); //提交事务
}catch (Exception e){
channel.txRollback(); //事务回滚
}
- RabbitMQ消息确认和return机制
消息确认机制:确认消息提供者是否成功发送消息到交换机
return机制:确认消息是否成功的从交换机分发到队列
@Component
public class MsgConfirmAndReturn implements RabbitTemplate.ConfirmCallback,RabbitTemplate.ReturnCallback {
Logger logger = LoggerFactory.getLogger(MsgConfirmAndReturn.class);
@Resource
private RabbitTemplate rabbitTemplate;
@PostConstruct
public void init(){
rabbitTemplate.setConfirmCallback(this);
rabbitTemplate.setReturnCallback(this);
}
@Override
public void confirm(CorrelationData correlationData, boolean b, String s) {
//此方法用于监听消息确认结果(消息是否发送到交换机)
if(b){
logger.info("-------消息成功发送到交换机");
}else{
logger.warn("-------消息发送到交换机失败");
}
}
@Override
public void returnedMessage(Message message, int i, String s, String s1, String s2) {
//此方法用于return监听(当交换机分发消息到队列失败时执行)
logger.warn("~~~~~~~交换机分发消息到队列失败");
}
}
延迟机制
5.1 延迟队列
- 延迟队列——消息进入到队列之后,延迟指定的时间才能被消费者消费
- AMQP协议和RabbitMQ队列本身是不支持延迟队列功能的,但是可以通过TTL(Time To Live)特性模拟延迟队列的功能
- TTL就是消息的存活时间。RabbitMQ可以分别对队列和消息设置存活时间
- 在创建队列的时候可以设置队列的存活时间,当消息进入到队列并且在存活时间内没有消费者消费,则此消息就会从当前队列被移除;
- 创建消息队列没有设置TTL,但是消息设置了TTL,那么当消息的存活时间结束,也会被移除;
- 当TTL结束之后,我们可以指定将当前队列的消息转存到其他指定的队列
RabbitMQ官方API:rabbitmq.