rabbitMQ的入门指南
1.docker安装rabbitmq
docker pull rabbitmq:management #拉取镜像
docker run -d --name rabbitmq --publish 5671:5671 \
--publish 5672:5672 --publish 4369:4369 --publish 25672:25672 \
--publish 15671:15671 --publish 15672:15672 rabbitmq:management
# 安装
4369 – erlang发现端口
5672 – client端通信端口
25672 – 集群通信端口
15672 – 管理界面UI端口 默认账号密码 guest guest
基本名词
虚拟主机
在管理界面中创建,以“/”开头,类似Linux
队列
生产者的消息放入的地方,存储转发
交换机
队列绑定交换机,交换机不存储消息
消费者绑定队列,交换机,生产者绑定交换机
Work模型:一个消息只能被消费一次,防止业务堆积,可采用能者多劳
订阅模型分类
Fanout:广播,将消息交给所有绑定到交换机的队列
Direct:定向,把消息交给符合指定routing key 的 列
在路由模式中,我们将添加一个功能 - 我们将只能订阅一部分消息。 例如,我们只能将重要的错误消
息引导到日志文件(以节省磁盘空间),同时仍然能够在控制台上打印所有日志消息。
但是,在某些场景下,我们希望不同的消息被不同的队列消费。这时就要用到Direct类型的Exchange。
在Direct模型下,队列与交换机的绑定,不能是任意绑定了,而是要指定一个RoutingKey(路由key)
消息的发送方在向Exchange发送消息时,也必须指定消息的routing key。
Topic:通配符,把消息交给符合routing pattern(路由模式) 的队列
Topic
类型的Exchange
与Direct
相比,都是可以根据RoutingKey
把消息路由到不同的队列。只不过Topic
类型Exchange
可以让队列在绑定Routing key
的时候使用通配符!
Routingkey
一般都是有一个或多个单词组成,多个单词之间以”.”分割,例如: item.insert
#
:匹配一个或多个词
*
:匹配不多不少恰好1个词
举例
audit.#
:能够匹配audit.irs.corporate
或者 audit.irs
audit.*
:只能匹配audit.irs
发送消息简单模型
1、获取连接
Connection connection = ConnectionUtil.getConnection()
2、从连接中创建通道
Channel channel = connection.createChannel();
3、声明创建队列
channel.queueDeclare()
4、向指定队列中发送消息
channel.basicPublish()
5、关闭管道和连接
接收消息简单模型
1、获取连接
Connection connection = ConnectionUtil.getConnection()
2、从连接中创建通道
Channel channel = connection.createChannel();
3、声明创建队列,与发送方的一样的队列名
channel.queueDeclare()
4、定义队列的消费者
new DefaultConsumer(channel) 重写handleDelivery()
5、监听队列,第二个参数:是否自动进行消息确认
channel.basicConsumer(队列名,自动确认)
SpringBoot中的使用
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
配置文件
我们在application.yml中添加一些有关RabbitMQ的配置:
spring:
rabbitmq:
host: 172.16.116.100
username: fengge
password: fengge
virtual-host: /fengge
template:
exchange: gmall.item.exchange
publisher-confirms: true
- template:有关
AmqpTemplate
的配置- exchange:缺省的交换机名称,此处配置后,发送消息如果不指定交换机就会使用这个
- publisher-confirms:生产者确认机制,确保消息会正确发送,如果发送失败会有错误回执,从而触发重试
发送消息到mq的方法
@Autowired
private AmqpTemplate amqpTemplate;
private void sendMessage(Long id, String type){
// 发送消息
try {
amqpTemplate.convertAndSend("miaosha.test","a.b",id);
} catch (Exception e) {
logger.error("{}商品消息发送异常,商品id:{}", type, id, e);
}
}
这里没有指定交换机,因此默认发送到了配置中的:gmall.item.exchange
convertAndSend(交换机的名称,rountingKey,消息)三个参数
注意:这里要把所有异常都try起来,不能让消息的发送影响到正常的业务逻辑
服务接收消息
同样需要依赖和配置文件,同上
编写监听器
@Component
public class SpuInfoListener {
@Autowired
private SearchService searchService;
/**
* 处理insert的消息
*
* @param id
* @throws Exception
*/
@RabbitListener(bindings = @QueueBinding(
value = @Queue(value = "队列名称", durable = "true"),
exchange = @Exchange(
value = "交换机名称",
ignoreDeclarationExceptions = "true",
type = ExchangeTypes.TOPIC),
key = {"item.insert"}))
public void listenCreate(Long id) throws Exception {
if (id == null) {
return;
}
// 收到消息后的业务逻辑
this.searchService.createIndex(id);
}
}