本篇文章主要是对《Rabbitmq实战》这本书的关键点做一些总结和整理,另外再加一些网上整理的扩展知识点。这里我截了一张图,方便识别
image.png

知识点

什么是Rabbitmq
各个角色
多租户模式
如何做持久化
集群模式
其他重要点

什么是Rabbitmq

简单的说就是一个用erlang编写的基于AMQP协议通信的消息队列中间件,通过它能够做到程序之间通讯的解耦、流控,能够做到对消息的持久化,保证在通讯过程中出现宕机等情况下消息不丢失。
如何安装见我另一篇文章《Rabbitmq安装部署》

各个角色

  • 生产者
  • 消费者
  • 信道/队列/交换器/绑定

    生产者

    生产者就是生产消息的一方,生产者创建完消息之后,将消息发送到rabbitmq。这里涉及到消息定义,消息主要有两部分构成:数据和标签。数据就是我们平时要发送给消费者的内容,标签主要是为了让rabbitmq知道消息的特征、要发送给谁。消息发后即忘。

    消费者

    消费者就是连接到rabbitmq上,并订阅某个队列,等待接收该队列的消息或者可以主动去拉取该队列的消息。消息的消费涉及到推和拉两种模式,下面是两种模式的介绍

  • 推模式(推荐):
    1、channel.basicConsume(queneName,consumer)方法将信道(channel)设置成投递模式,直到取消队列的订阅为止;在投递模式期间,当消息到达RabbitMQ时,RabbitMQ会自动地、不断地投递消息给匹配的消费者,而不需要消费端手动来拉取,当然投递消息的个数还是会受到channel.basicQos的限制。
    2、推模式将消息提前推送给消费者,消费者必须设置一个缓冲区缓存这些消息。优点是消费者总是有一堆在内存中待处理的消息,所以当真正去消费消息时效率很高。缺点就是缓冲区可能会溢出。
    3、由于推模式是信息到达RabbitMQ后,就会立即被投递给匹配的消费者,所以实时性非常好,消费者能及时得到最新的消息。
  • 拉模式:
    1、如果只想从队列中获取单条消息而不是持续订阅,则可以使用channel.basicGet方法来进行消费消息。
    2、拉模式在消费者需要时才去消息中间件拉取消息,这段网络开销会明显增加消息延迟,降低系统吞吐量。
    3、由于拉模式需要消费者手动去RabbitMQ中拉取消息,所以实时性较差;消费者难以获取实时消息,具体什么时候能拿到新消息完全取决于消费者什么时候去拉取消息。
    image.png

    信道/队列/交换器/绑定

    信道

    连接到mq之后,在通信之前会首先创建一个信道(channel),他是基于Tcp连接内的虚拟连接,可以复用一条Tcp连接,从而减少Tcp连接的创建和销毁成本,每条信道都会有一个id,我们和rabbitmq的所有交互都是通过信道完成的。ps:这里信道是如何实现共享一个tcp连接并且能够不影响吞吐率的需要再研究一下。
    image.png

    队列

    队列比较简单,就是一个存放了一组消息的数据结构,FIFO模式,生产者创建的消息最终就是被mq放到队列里去了,消费者也是最终通过队列获取到消息再进行消费,如果是多个消费者订阅一个队列的情况下,其中一个消费者消费成功了,消息就会从队列中被删除,消息失败的话消息就会被传递给下一个消费者(requeue设置为true)。当然mq的队列也有一些复杂点的使用,包括死信队列和优先级队列。
    死信队列:当消息没有被成功消费我们就可以把它丢入到死信队列中,哪些场景算没有成功呢?
    1、消息过期,也就是给消息或者队列设置了TTL时间;
    2、消息被拒绝,也就是消息basic.reject或者basic.nack,并且reququq=false;
    3、队列达到最大长度;
    对以上这三种消息成为死信消息之后,我们可以通过创建死信交换器,将死信消息丢入到指定的队列中,这个队列就可以称之为死信队列,关于死信队列更详细的介绍,参考https://www.jianshu.com/p/986...
    另外一个就是我们可以基于消息的优先程序创建优先级队列,如何创建优先级队列,参考https://blog.csdn.net/u013256...
    另外比较有用的两个设置参数,这里截取书上一段话:
    image.png

    交换器

    交换器可以理解为一个路由器,生产者在发送消息之后,mq会基于交换器的路由键(routing key)将消息丢入对应的队列中去。类型有:direct、fanout、topic、headers。对于四种类型的具体描述,参考https://www.jianshu.com/p/469...。(headers已经被淘汰,被direct取代)

    绑定

    绑定比较简单,就是通过routing key将交换器和队列进行关联起来,使得消息经过交换器之后能被发送到对应的队列里。

    多租户模式

    每个rabbitmq服务器都能创建虚拟消息服务器,这就是虚拟主机(vhost)。vhost可以理解为一个mini版的rabbitmq服务器,它也有自己的队列、交换器、绑定等角色,还有自己的一套权限控制。比如你可以用同一个rabbitmq分别创建测试环境、开发环境、生产环境的vhost,达到不同环境隔离的目的,而不用启动多个rabbitmq服务器。我们可以用rabbitmqctl去维护vhost,当然也可以通过web管理工具进行维护,参考:https://www.cnblogs.com/max19...

    如何做持久化

    我们在消息通信的时候有时需要保证消息不会丢失,即使是系统挂了,消息依然能够保留,这里就要说到消息的持久化。默认情况下,rabbitmq重启之后,队列、交换器都是会消失的,当然消失的也包括里面的消息。如何能做到不丢失呢?

  • 要持久化队列和交换器,设置其durable为true。
  • 次在消息发布的时候将投递模式(delivery_mode)设置为2,并通过上一步设置的持久化交换器发布到持久化队列里面。
    rabbitmq持久化消息是写入到磁盘上的一个持久化日志文件里,写入成功之后才会响应生产端成功,后续如果该消息被发到非持久化队列里,就会从持久性日志里移除。具体的持久化代码怎么写,参考:https://www.cnblogs.com/bigbe...

    问题

    持久化保证了我们的消息不丢失,同时也会带来一些问题,最主要的问题就是性能,因为它是写日志文件是涉及到磁盘交互的。另外在集群模式下会有一些问题,因为默认的情况下,集群中每个节点都是各自维护自己的消息队列,也就是其中一个节点宕机了,在其恢复前,该节点内的消息就无法被消费了。
    总得来说使用持久化机制要进行权衡考虑。

    集群模式

    平时我们在使用rabbitmq的时候,万一rabbitmq挂了怎么办,连带我们的相关服务业务不就有影响了。这时候我们就需要对rabbitmq做高可用,也就是部署rabbitmq集群。
    集群模式下,每个节点也可以选择将元数据信息存入到磁盘或者内存中,这就是我们看到DISK节点和RAM节点。默认情况下每个节点的队列都是各自维护的,也就是其中一个节点如果宕机了,那就意味着该节点所有队列中的所有消息都暂时消失了,直到恢复该节点。这时候你们可能已经意识到问题了,这样的话那如何能保证其中一个节点挂了,消息依然正常处理呢?
    这里就涉及到镜像队列的概念了,通过镜像队列,我们就可以将节点的消息都同步到其他节点。当然我们还得做持久化,所有在集群模式下必须要有DISK节点来保证持久化。这里又涉及到权衡取舍了,虽然保证了高可用,但是性能和存储空间方面又会受到影响,如果你的业务场景是不需要经常创建队列的,DISK节点影响就不大。
    正常集群搭建中,我们需要保证有至少2个DISK节点来做持久化,另外RAM节点的效率是要高于DISK节点的,交互上可以和RAM节点交互。
    如何搭建,参考:https://blog.csdn.net/qq_2853...

    其他重要点

    其他的重要点这里就是毫无逻辑的整理了一下,大概知道有这些点就可以了

  • erlang也有虚拟机,虚拟机上每个实例称为节点,erlang一个节点可以运行多个erlang应用程序,节点之间可以做本地通信(不管是否在同一台服务器上)。erlang上的应用程序崩溃了,erlang会自动尝试重启。
  • 日志目录在:/var/log/rabbitmq,可以以-detached方式以守护进程方式后台启动。
  • 以stop命令干净地进行关闭,防止消息没处理完丢失,rabbitmqctl管理操作参考https://www.cnblogs.com/wyt00...
  • 通过对rabbitmq.config配置改变监听端口以及占用的内存等信息,不存在这个文件自己新增一个。具体配置参考:https://www.cnblogs.com/wyt00...
  • 使用mnesia数据库,他是非关系型
  • rpc模式实现参考:https://blog.csdn.net/u013256...
  • 通过haproxy实现负载均衡,参考 https://www.cnblogs.com/Liang...
  • 延迟队列实现,参考https://www.cnblogs.com/mfran...

    总结

    由于知识点实在有点多,后面就做了一些简单的整理,还需要自己多去操作才能熟悉,文章记录只是作为快速回顾。以上也只是自己的理解,有什么问题大家也可以提出来一起探讨。


爱炒股的程序猿
50 声望4 粉丝

每天进步一点点


引用和评论

0 条评论