#博学谷IT学习技术支持#
个人笔记后续会进行内容改进
同步通讯&异步通讯
Mq五种队列
消息可靠性(publisher、consumer消息确认)
持久化
同步通讯和异步通讯:
同步通讯:
优点:时效性比较高
缺点:耦合度高、
性能下降、
额外的资源消耗、
级联失败问题
异步通讯:
优点:不需要很强的失效性
性能的提升、
故障隔离、
耦合度低、
流量削峰
缺点:架构复杂、
需要依赖broker的可靠、安全、性能
Mq:消息中间件
追求可用性:Kafka、 RocketMQ 、RabbitMQ
追求可靠性:RabbitMQ、RocketMQ
追求吞吐能力:RocketMQ、Kafka
追求消息低延迟:RabbitMQ、Kafka
Rabbitmq的常见角色:
Publisher:生产者
Consumer:消费者
Queue:队列
Exchange:交换机
Rabbitmq五种消息队列:
Basicqueue 基本消息队列
Workqueue 工作消息队列
(发布订阅)
Fanout exchange 广播
Direct exchange 路由
Topic exchage 主题
Springamqp:
SpringAMQP是基于RabbitMQ封装的一套模板,并且还利用SpringBoot对其实现了自动装配
Springamqp提供的三个功能:
自动声明交换机,队列,及其绑定关系
基于注解的监听模式、异步接收消息
封装rabbittemplate工具,用于发送消息
Basic queue队列流程:
配置rabbitmq的连接信息到application.yml
Publisher调用rabbittemplate的convertandsend方法把队列名称和消息发送出去
Consumer使用rabbitlistener注解监听publisher发送的队列
Work queue队列流程:
一个publisher对应多个consumer,每个consumer平均分配publisher的消息。可以修改consumer的配置文件使每个consumer只能获取一条消息,处理完才能获取下一条消息
Fanout exchange队列:
编写配置类声明交换机和队列的关系。
其他不变
Direct exchange队列:
消息发送方不变调用rabbittemplate的send方法发送消息。多一个key,根据key进行路由
接收方使用rabbitlistener注解绑定关系:
@rabbitlistener(bindings=@Queuebinding(
Value=@Queue(name=”q1), 队列名称
Exchange=@Exchange(name=”e1”,type=Excahngetypes.DIRECT), 交换机名称
Key={“red}/”blue” key
))
Topic exchange队列:
与direct基本无差别。区别在routingkey上topic的key可以使用通配符
#:代表多个或0个词
*:代表一个词
默认的传递对象会被序列化。需要在配置类中配置json转换器:
@Bean
Public Messageonverter jsonMessageConverson(
Return new Jackson2JsonMessageconverter();
)
消息可靠性:
Publisherconsumer消息确认
消息持久化
死信交换机
Mq集群
消息可靠性:
消息丢失的原因:
发送时丢失:
生产者发送的消息未送达exchange
消息到达exchange后未到达queue
MQ宕机,queue将消息丢失
consumer接收到消息后未消费就宕机
Rabbitmq解决方法:
生产者确认机制
mq持久化
消费者确认机制
失败重试机制
配置流程:
Publisher配置
1、
application.yml
publish-confirm-type:开启publisher-confirm,这里支持两种类型:
simple:同步等待confirm结果,直到超时
correlated:异步回调,定义ConfirmCallback,MQ返回结果时会回调这个ConfirmCallback
publish-returns:开启publish-return功能,同样是基于callback机制,不过是定义ReturnCallback
template.mandatory:定义消息路由失败时的策略。true,则调用ReturnCallback;false:则直接丢弃消息
2、
全局ReturnCallback
Consumer配置:
定义ConfirmCallback
持久化:
交换机持久化配置:
@Bean
public DirectExchange simpleExchange(){
// 三个参数:交换机名称、是否持久化、当没有queue与其绑定时是否自动删除
return new DirectExchange("simple.direct", true, false);}
队列持久化:
@Bean
public Queue simpleQueue(){
// 使用QueueBuilder构建队列,durable就是持久化的
return QueueBuilder.durable("simple.queue").build();
}
消息持久化:
可以设置消息的属性(MessageProperties),指定delivery-mode:PERSISTENT
消费者确认:
manual:手动ack,需要在业务代码结束后,调用api发送ack。
auto:自动ack,由spring监测listener代码是否出现异常,没有异常则返回ack;抛 出异常则返回nack
none:关闭ack,MQ假定消费者获取消息后会成功处理,因此消息投递后立即被删除
失败重试:
在开启重试模式后,重试次数耗尽,如果消息依然失败,则需要有MessageRecovery接口来处理,它包含三种不同的实现:
RejectAndDontRequeueRecoverer:重试耗尽后,直接reject,丢弃消息。默认就是这种方式
ImmediateRequeueMessageRecoverer:重试耗尽后,返回nack,消息重新入队
RepublishMessageRecoverer:重试耗尽后,将失败消息投递到指定的交换机
比较优雅的一种处理方案是RepublishMessageRecoverer,失败后将消息投递到一个指定的,专门存放异常消息的队列,后续由人工集中处理。
1)在consumer服务中定义处理失败消息的交换机和队列
@Bean
public DirectExchange errorMessageExchange(){
return new DirectExchange("error.direct");
}
@Bean
public Queue errorQueue(){
return new Queue("error.queue", true);
}
@Bean
public Binding errorBinding(Queue errorQueue, DirectExchange errorMessageExchange){
return BindingBuilder.bind(errorQueue).to(errorMessageExchange).with("error");
}
2)定义一个RepublishMessageRecoverer,关联队列和交换机
@Bean
public MessageRecoverer republishMessageRecoverer(RabbitTemplate rabbitTemplate){
return new RepublishMessageRecoverer(rabbitTemplate, "error.direct", "error");
}