zoukankan      html  css  js  c++  java
  • 别再说你不会RabbitMQ,这里有全网最全RabbitMQ总结!

    自己总结的RabbitMQ的教程,有不恰当的地方欢迎小伙伴指出。

    我们先来看一下一条消息在RabbitMQ中的流转过程

    全网最全RabbitMQ总结,别再说你不会RabbitMQ

    图示的主要流程如下

    整个流程主要就4个参与者message,exchange,queue,consumer,我们就来认识一下这4个参与者

    消息可以设置一些列属性

    全网最全RabbitMQ总结,别再说你不会RabbitMQ

    接收消息,并根据路由键转发消息到所绑定的队列,常用的属性如下

    全网最全RabbitMQ总结,别再说你不会RabbitMQ

    我们最常使用的就是type属性,下面就详细解释type属性

    全网最全RabbitMQ总结,别再说你不会RabbitMQ

    发送到该交换机的消息都会路由到与该交换机绑定的所有队列上,可以用来做广播

    不处理路由键,只需要简单的将队列绑定到交换机上

    Fanout交换机转发消息是最快的

    全网最全RabbitMQ总结,别再说你不会RabbitMQ

    把消息路由到BindingKey和RoutingKey完全匹配的队列中

    全网最全RabbitMQ总结,别再说你不会RabbitMQ

    前面说到,direct类型的交换器路由规则是完全匹配RoutingKey和BindingKey。topic和direct类似,也是将消息发送到RoutingKey和BindingKey相匹配的队列中,只不过可以模糊匹配。

    全网最全RabbitMQ总结,别再说你不会RabbitMQ

    假如现在有2个RoutingKey为java.lang和java.util.concurrent的消息,java.lang会被路由到Consumer1和Consumer2,java.util.concurrent会被路由到Consumer2。

    全网最全RabbitMQ总结,别再说你不会RabbitMQ

    headers类型的交换器不依赖于路由键的匹配规则来路由消息,而是根据发送消息内容中的headers属性进行匹配。headers类型的交换器性能差,不实用,基本上不会使用。

    队列的常见属性如下

    全网最全RabbitMQ总结,别再说你不会RabbitMQ

    arguments中可以设置的队列的常见参数如下

    全网最全RabbitMQ总结,别再说你不会RabbitMQ

    来回顾一下上面说的各种exchange机器路由规则

    全网最全RabbitMQ总结,别再说你不会RabbitMQ

    消息的获得方式有2种

    那我们应该拉取消息还是推送消息?get是一个轮询模型,而consumer是一个推送模型。get模型会导致每条消息都会产生与RabbitMQ同步通信的开销,这一个请求由发送请求帧的客户端应用程序和发送应答的RabbitMQ组成。所以推送消息,避免拉取

    消息的确认方式有2种

    消费者在消费消息的时候,可以指定autoAck参数

    String basicConsume(String queue, boolean autoAck, Consumer callback)

    autoAck=false: RabbitMQ会等待消费者显示回复确认消息后才从内存(或者磁盘)中移出消息

    autoAck=true: RabbitMQ会自动把发送出去的消息置为确认,然后从内存(或者磁盘)中删除,而不管消费者是否真正的消费了这些消息

    手动确认的方法如下,有2个参数

    basicAck(long deliveryTag, boolean multiple)

    deliveryTag: 用来标识信道中投递的消息。RabbitMQ 推送消息给Consumer时,会附带一个deliveryTag,以便Consumer可以在消息确认时告诉RabbitMQ到底是哪条消息被确认了。RabbitMQ保证在每个信道中,每条消息的deliveryTag从1开始递增

    multiple=true: 消息id<=deliveryTag的消息,都会被确认

    myltiple=false: 消息id=deliveryTag的消息,都会被确认

    消息一直不确认会发生啥?

    如果队列中的消息发送到消费者后,消费者不对消息进行确认,那么消息会一直留在队列中,直到确认才会删除。如果发送到A消费者的消息一直不确认,只有等到A消费者与rabbitmq的连接中断,rabbitmq才会考虑将A消费者未确认的消息重新投递给另一个消费者

    确认消息只有一种方法

    而拒绝消息有两种方式

    basicNack和basicReject的区别只有一个,basicNack支持批量拒绝

    deliveryTag和multiple参数前面已经说过。

    requeue=true: 消息会被再次发送到队列中

    requeue=false: 消息会被直接丢失

    chapter_6到chapter_10主要简述了消息发布时的权衡

    全网最全RabbitMQ总结,别再说你不会RabbitMQ

    我们最常用的就是失败通知和发布者确认当消息不能被路由到某个queue时,我们如何获取到不能正确路由的消息呢?

    mandatory是channel.basicPublish()方法中的参数

    mandatory=true: 交换器无法根据路由键找到一个符合条件的队列,那么RabbitMQ会调用Basic.Return命令将消息返回给生产者

    mandatory=false: 出现上述情形,则消息直接被丢弃

    当消息被发送后,消息到底有没有到达exchange呢?默认情况下生产者是不知道消息有没有到达exchange

    RabbitMQ针对这个问题,提供了两种解决方式

    而发布者确认有三种编程方式

    异步confirm模式的性能最高,因此经常使用,我想把这个分享的细一下

    写过异步confirm代码的小伙伴应该对这段代码不陌生,可以看到这里也有deliveryTag和multiple。但是我要说的是这里的deliveryTag和multiple和消息的ack没有一点关系。

    confirmListener中的ack: rabbitmq控制的,用来确认消息是否到达exchange

    消息的ack: 上面说到可以自动确认,也可以手动确认,用来确认queue中的消息是否被consumer消费

    生产者在发送消息的时候如果不设置 mandatory 参数那么消息在未被路由到queue的情况下将会丢失,如果设置了 mandatory 参数,那么需要添加 ReturnListener 的编程逻辑,生产者的代码将变得复杂。如果既不想复杂化生产者的编程逻辑,又不想消息丢失,那么可以使用备用交换器,这样可以将未被路由到queue的消息存储在RabbitMQ 中,在需要的时候去处理这些消息

    RabbitMQ中与事务机制相关的方法有3个

    全网最全RabbitMQ总结,别再说你不会RabbitMQ

    消息成功被发送到RabbitMQ的exchange上,事务才能提交成功,否则便可在捕获异常之后进行事务回滚,与此同时可以进行消息重发因为事务会榨干RabbitMQ的性能,所以一般使用发布者确认代替事务

    消息做持久化,只需要将消息属性的delivery-mode设置为2即可

    RabbitMQ给我们封装了这个属性,即MessageProperties.PERSISTENT_TEXT_PLAIN,详细使用可以参考github的代码

    当我们想做消息的持久化时,最好同时设置队列和消息的持久化,因为只设置队列的持久化,重启之后消息会丢失。只设置队列的持久化,重启后队列消失,继而消息也丢失

    DLX,全称为Dead-Letter-Exchange,称之为死信交换器。当一个消息在队列中变成死信(dead message)之后,它能被重新发送到另一个交换器中,这个交换器就是DLX,绑定DLX的队列就称之为死信队列。DLX也是一个正常的交换器,和一般的交换器没有区别,实际上就是设置某个队列的属性

    消息变成死信一般是由于以下几种情况

    死信交换器和备用交换器的区别

    备用交换器: 1.消息无法路由时转到备用交换器 2.备用交换器是在声明主交换器的时候定义的

    死信交换器: 1.消息已经到达队列,但是被消费者拒绝等的消息会转到死信交换器。2.死信交换器是在声明队列的时候定义的

    qos即服务端限流,qos对于拉模式的消费方式无效

    使用qos只要进行如下2个步骤即可

    basicQos(int prefetchSize, int prefetchCount, boolean global)

    全网最全RabbitMQ总结,别再说你不会RabbitMQ

    转发+关注截图私信我免费领取更多java架构资料、源码、笔记

  • 相关阅读:
    DS博客作业02--栈和队列
    指针
    C语言博客作业04--数组
    函数
    留言板
    第三周-自主学习任务-面向对象基础与类的识别
    DS博客作业05--查找
    DS博客作业04--图
    DS博客作业03--树
    DS博客作业02--栈和队列
  • 原文地址:https://www.cnblogs.com/ming569/p/13724332.html
Copyright © 2011-2022 走看看