1 搭建项目环境
1.1创建mevan项目
1.2修改 pom 文件添加 RabbitMQ 坐标
<dependencies>
<!-- rabbitmq-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
</dependencies>
1.3修改全局配置文件,添加 RabbitMQ 相关的配置
#application配置文件
spring:
rabbitmq:
host: 192.168.160.135
username: admin
password: admin
⦁ direct 交换器
当有多个消息服务场景是采取访问方式:
direct 交换器是 RabbitMQ 默认交换器。默认会进行公平调度(轮询)一对一。所有接受者依次从消息队列中获取值。Publisher 给哪个队列发消息,就一定是给哪个队列发送消息。对交换器绑定的其他队列没有任何影响。
操作RabbitMQ 的接口:负责发送
org.springframework.amqp.rabbit.core.RabbitTemplate;
与redis一样都是通过RabbitTemplate类似的模板类来创建的
接收消息
/*
@RabbitListener:
* bindings:绑定队列
* @QueueBinding:绑定队列的详细属性
* value=@Queue(value="mydirect" : 配置队列名称
* autoDelete = "false":是否是可删除的临时队列(是否持久化,true用完之后自动从队列中删除)
*/
@RabbitListener(
bindings=@QueueBinding(
value=@Queue(value="mydirect",autoDelete = "false"),
exchange=@Exchange(value="directExchange",type= ExchangeTypes.DIRECT),
key="com.product.sms"
)
)
#依赖
<!-- Spring Boot的父项目,声明所有Spring Boot相关版本 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
</parent>
<dependencies>
<!-- rabbitmq-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope> <!--scope为test表示依赖项目仅仅参与测试相关的工作,包括测试代码的编译,执行。比较典型的如junit -->
</dependency>
⦁ fanout 交换器
扇形交换器,实际上做的事情就是广播(群发),fanout 会把消息发送给所有的绑定在当前交换器上的队列。对应 Consumer 依然采用公平调度方式(轮询)。
FanoutExchange:fanout 交换器Binding:绑定交换器和队列BindingBuilder:Binding 的构建器
⦁ topic 交换器(主题)
允许在路由键(RoutingKey)中出现匹配规则。
路由键的写法和包写法相同。com.product.*.* 格式。在绑定时可以带有下面特殊符号,中间可以出现:
* : 代表一个单词(两个.之间内容)
# : 0 个或多个字符(0-n)
加在key里面 如: com.product.*
接收方依然是公平调度,同一个队列中内容轮换获取值。
TopicExchange:Topic 交换器
三种交换器的使用总结:
DirectExchange:
一对一:发送消息的时候指定: 路由键+DirectExchange交换器
TopicExchange:
主题: 发送消息的时候指定: 路由键(加入主题)+TopicExchange交换器
如果这里的路由键不加主题,效果和一对一类似
com.product.* com.product.#
FanoutExchange:
群发: 发送消息的时候指定: FanoutExchange交换器 省略路由键
ACK机制
为了避免内存溢出情况发生,开启重试机制即可。
rabbitmq重试机制应答模式
NONE
可以称之为自动回调,即使无响应或者发生异常均会通知队列消费成功,会丢失数据。
AUTO(默认)
自动检测异常或者超时事件,如果发生则返回noack,消息自动回到队尾,但是这种方式可能出现消息体本身有问题,返回队尾其他队列也不能消费,造成队列阻塞。
MANUAL
手动回调,在程序中我们可以对消息异常记性捕获,如果出现消息体格式错误问题,手动回复ack,接着再次调用发送接口把消息推到队尾。
#配置mq
spring:
rabbitmq:
host: 192.168.160.135
username: admin
password: admin
listener:
direct:
acknowledge-mode: manual
template:
retry:
enabled: true #开启重试
max-attempts: 3 #默认的重试的次数3
publisher-confirm-type: correlated #开启消息发送交换机的确认类型为交互
publisher-returns: true #开启消息发送队里回调
关于rabbitmq从生产者发送消息到exchange然后到指定队列的整个流程示意图
什么时候消息退回?
1、消息是否能找到对应的exchange,即生产者的消息是否能够准确投递到指定的exchange中,如果找不到,则会被退回;
2、消息投递到exhange成功,但是没有找到合适的队列,即消息无法被路由到指定的queue中去,导致消息无法被投递和消费,也会被退回;
3、最后,消息被某个消费者消费,但是没有确认(ACK)
退回这个词可以认为是程序中处理未被确认的消息的一致机制,或者说一种处理方式,在rabbitmq中可以是退回这条未被确认的消息,或者是丢弃掉可以根据业务场景具体使用;
消息中间件在开发中可以看作是”秘书”
总经理---->秘书(消息中间件)----->通知各个部门处理