RabbitMQ属性的基本设置

1. 消息如何保障100%的投递成功

  1. 什么是生产端的可靠性投递
  • 保障消息的成功发出
  • 保障MQ节点的成功接收
  • 发送端收到的MQ节点(Broker)确认应答
  • 完善的消息进行补偿机制
  1. 生产端-可靠性投递(一)

解决方案:

  • 消息落库,对消息状态进行打标
  • 消息的延迟投递,做二次确认,回调检查
  1. 消息信息落库,对消息状态进行打标
    RabbitMQ属性的基本设置_第1张图片
  2. 生产端-可靠性投递(二)
    RabbitMQ属性的基本设置_第2张图片

2. 幂等性概念

  1. 幂等性是什么
    简单通俗:执行一百条语句,得到相同的结果
  2. 消费端实现幂等性,就意味着,我们的消息永远不会消费多次,即时我们收到了多条一样的消息
  3. 消费端-幂等性保障
    业界主流的幂等性操作:
    唯一ID + 指纹码机制,利用数据库主键去重
    利用Redis的原子性去实现
  • 唯一ID + 指纹码机制
    唯一ID + 指纹码机制,利用数据库主键去重
    SELECT COUNT(1) FROM T_ORDER WHERE ID = 唯一ID + 指纹码
    好处:实现简单
    坏处:高并发下有数据库写入的性能瓶颈
    解决方案:跟进ID进行分库分表进行算法路由
  • 利用Redis原子特性实现
    使用Redis进行幂等,需要考虑的问题
    第一:我们是否要进行数据落库,如果落库的话,关键解决的问题是数据库和缓存如何做到原子性
    第二:如果不进行落库,那么都存储到缓存中,如何设置定时同步的策略

3. Confirm确认消息

  1. 理解Confirm消息确认机制
    消息的确认,是指生产者投递消息后,如果Broker收到消息,则会给我们生产者一个应答
    生产者进行接收应答,用来确定这条消息是否正常的发送到Broker,这种方式也是消息的可靠性投递的核心保障
  2. 如何实现Confirm确认消息
    第一步:在channel上开启确认模式:channel.confirmSelect()
    第二步:在channel上添加监听:addConfirmListener,监听成功和失败的返回结果,根据具体的结果对消息进行重新发送,或记录日志等后续处理

4. Return消息机制

  1. Return Listener用于处理一些不可路由的消息
  2. 我们的消息生产者,通过制定一个Exchange和RoutingKey,把消息送达到某一个队列中去,然后我们的消费者监听队列,进行消费处理操作
  3. 但是在某些情况下,如果我们在发送消息的时候,当前的exchange不存在或者指定的路由key路由不到,这个时候如果我们需要监听这种不可达的消息,就是使用Return Listener
  4. 在基础API中有一个关键的配置项:
    Mandatory:如果为true,则监听器会接收到路由不可达的消息,然后进行后续处理,如果为false,那么broker端自动删除该消息

5. 消费端限流

  1. RabbitMQ提供了一种qos(服务质量保证)功能,即在非自动确认消息的前提下,如果一定数目的消息(通过基于consume或者channel设置qos的值)未被确认前,不进行消费新的消息
  2. 方法:
    void BasicQos(uint prefetchSize,ushort prefetchCount,bool global)
  3. 参数说明:
    prefetchSize:0
    prefetchCount:会告诉RabbitMQ不要同时给一个消费者推送多余N个消息,即一旦有N个消息还没有ack,则该consumer将block掉,直到有消息ack
    global:true\false是否将上面设置应用于channel
    简单说:就是上面限制是channel级别的还是consumer级别

注意:prefetchSize和global这两项,rabbitmq没有实现,暂且不研究prefetch_count在no_ask=false的情况下生效,即在自动应答的情况下这两个值是不生效的

6. SimpleMessageListenerContainer

简单消息监听容器

  1. 设置事务特性,事务管理器,事务属性,事务容量(并发),是否开启事务,回滚消息等
  2. 设置消费者数量,最小最大数量,批量消费
  3. 设置消息确认和自动确认模式,是否重回队列,异常捕获handler函数
  4. 设置消费者标签生成策略,是否独占模式,消费者属性等
  5. 设置具体的监听器,消息转换器等

注意:SimpleMessageListenerContainer可以进行动态设置,比如在运行中的应用可以动态的修改其消费者数量的大小,接收消息的模式等

7. MessageListenerAdapter

MessageListenerAdapter即消息监听适配器
核心属性:

  1. defaultListenerMethod 默认监听方法名称:用于设置监听方法名称
  2. Delegate 委托对象:实际真实的委托对象,用于处理消息
  3. queueOrTagToMethodName 队列标识与方法名称组成的集合
    可以一一进行队列与方法名称的匹配
    队列和方法名称绑定,即指定队列里的消息会被绑定的方法所接受处理

8. MessageConverter消息转换器

我们在进行发送消息的时候,正常情况下消息体为二进制的数据方式进行传输,如果希望内部帮我们进行转换,或者指定自定义的转换器,就需要用到MessaageConverter

自定义常用转换器:MessageConverter,一般来讲都需要实现这个接口
重写这两个方法:
toMessage:java对象转换为Message
fromMessage:Message对象转换为java对象

  • Json转换器
    Jackson2JsonMessageConverter:可以进行java对象的转化功能
    DefaultJackson2JavaTypeMapper映射器:可以进行java对象的映射关系
    自定义二进制转换器:比如图片类型,PDF,PPT,流媒体

9. publisher-confirms

  • publisher-confirms,实现一个监听器用于监听Broker端给我们返回的确认请求:RabbitTemplate.ConfirmCallback
  • publisher-returns,保证消息对Broker端是可达的,如果出现路由键不可达的情况,则使用监听器对不可达的消息进行后续的处理,保证消息的路由成功:RabbitTemplate.ReturnCallback

注意:在发送消息的时候对template进行配置mandatory=true保证监听有效

10. RabbitListener注解使用

首先配置手工确认模式,用于ACK的手工处理,这样我们可以保证消息的可靠性送达,或者再消费端失败的时候可以做到重回队列,根据业务记录日志等处理
可以设置消费端的监听个数和最大个数,用于控制消费端的并发情况

  • 消费端监听@RabbitMQListener注解
    @RabbitListener是一个组合注解,里面可以注解配置
    @QueueBinding,@Queue,@Exchange直接通过这个组合注解
    一次性搞定消费端交换机,队列,绑定,路由,并且配置监听功能等

示列代码:

@RabbitListener( bindings = @QueueBinding(
					value = @Queue( value = "queue-1", durable = "true"),
					exchange = @Exchange( value = "exchange-1",
					durable = "true",
					type = "topic",
					ignoreDeclarationExceptions = "true",
					key = "springboot.*" )
                             )
)
@RabbitHandler
public void onMessage(Message message,Channel channel) throws Exception{}

再与SpringBoot整合时建议不要使用注解的方式直接写死,建议将设置写到配置文件中,然后将key写入注解中,这样方便更改,如下:
配置文件:

spring.rabbitmq.listener.order.queue.name=queue-2
spring.rabbitmq.listener.order.queue.durable=true
spring.rabbitmq.listener.order.exchange.name=exchange-2
spring.rabbitmq.listener.order.exchange.durable=true
spring.rabbitmq.listener.order.exchange.type=topic
spring.rabbitmq.listener.order.exchange.ignoreDeclarationExceptions=true
spring.rabbitmq.listener.order.key=springboot.*

代码注解:

@RabbitListener( bindings = @QueueBinding(
					value = @Queue( value = "${spring.rabbitmq.listener.order.queue.name}", 
					durable = "${spring.rabbitmq.listener.order.queue.durable}"),
					exchange = @Exchange( value = "${spring.rabbitmq.listener.order.exchange.name}",
					durable = "${spring.rabbitmq.listener.order.exchange.durable}",
					type = "${spring.rabbitmq.listener.order.exchange.type}",
					ignoreDeclarationExceptions = "${spring.rabbitmq.listener.order.exchange.ignoreDeclarationExceptions}",
					key = "${spring.rabbitmq.listener.order.key}" )
                             )
)
@RabbitHandler
public void onMessage(Message message,Channel channel) throws Exception{}

光大的技术爱好者们,confirm中的第二条如果有解决方案,欢迎留言

你可能感兴趣的:(MQ)