一、MQ的应用场景
1、实现项目中的解耦,应用内部的消息同步变异步通信
2、不同系统之前实现异步通信
3、利用RabbitMQ实现最终一致性的事务
二、基本介绍
1、RabbitMQ的特性
- 可靠性
- 灵活的路由
- 消息集群
- 高可用
- 多种协议
- 多语言客户端
- 管理界面
- 插件机制
2、AMQP协议
AMQP,即Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件同产品、不同的开发语言等条件的限制。
3、工作模型
生产者发出消息给交换机,然后消费者从队列中取消息,其中交换机起到了关键作用,会根据消息绑定关系进行分发。
三、交换机介绍
1、Direct Exchange 直连交换机
在直连交换机模式中,生产者发送绑定消息给交换机,消费取消息时也需要绑定好对应关系取来消费,绑定关键字需要完全一致。
伪代码演示
生产者:
1. 配置连接工厂
2. 建立TCP连接
3. 在TCP连接的基础上创建通道
// 4.声明一个direct交换机
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
String message = "test:time=" + System.currentTimeMillis();
// 5.发送消息,并配置消息的路由键
channel.basicPublish(EXCHANGE_NAME, routingKey, null, message.getBytes("UTF-8"));
消费者:
1. 配置连接工厂
2. 建立TCP连接
3. 在TCP连接的基础上创建通道
// 4.声明一个direct交换机
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
// 5.声明一个临时队列
String queueName = channel.queueDeclare().getQueue();
// 6.绑定路由,同一个队列可以绑定多个值
for (String colour : colours) {
channel.queueBind(queueName, EXCHANGE_NAME, colour);
}
7. 接收消息并处理
2、Topic Exchange 主题交换机
在主题交换机模式中,生产者发送绑定消息给交换机,消费取消息时也需要绑定好对应关系取来消费,绑定关键字可以根据规则进行匹配,’ * ’ 可以表示一个词’#’ 表示0个或多个词。
例如:
routing key=sh.abc 那么队列1就会收到消息
routing key=ab.jak 那么队列2和队列3就会收到消息
routing key=ab.sss.food那么队列2和队列4就会收到消息
伪代码演示
生产者:
//将队列Constants.TOPIC_QUEUE与exchange绑定,binding_key为topic.queue.key,就是完全匹配
BindingBuilder.bind(topicQueue).to(exchange).with(Constants.ROUTING_KEY);
//将队列Constants.TOPIC_QUEUE_TWO与exchange绑定,binding_key为topic.*.#,模糊匹配
BindingBuilder.bind(topicQueue2).to(exchange).with(Constants.ROUTING_KEY_TWO);
消费者:
/**
*使用模糊匹配模式
*/
@Component
@RabbitListener(queues = Constants.TOPIC_QUEUE_TWO)
public class TopicConsumer {
@RabbitHandler
public void process(String test) {
System.out.println(test);
}
}
/**
*使用完全匹配模式
*/
@Component
@RabbitListener(queues = Constants.TOPIC_QUEUE)
public class TopicConsumer {
@RabbitHandler
public void process(String test) {
System.out.println(test);
}
}
3、Fanout Exchange 广播交换机
以广播的模式进行消息的传递。广播模式一定没有路由键的存在(routing key),将消息从路由器发送到所有绑定的队列中去(即消息会发送到所有和指定路由器绑定的队列中去)。
伪代码演示
生产者:
//routingKey可以指定也可以不指定,这里我们给一个空字符串""
rabbitTemplate.convertAndSend(Constants.FANOUT_EXCHANGE_NAME, "", message);
消费者:
/**
*使用模糊匹配模式
*/
@Component
@RabbitListener(queues = Constants.FANOUT_QUEUE_TEST)
public class FanoutConsumer {
@RabbitHandler
public void process(String test) {
System.out.println(test);
}
}