咱们为何要使用RabbitMQ?

 1、前言
服务器

       这篇文章就是讲RabbitMQ的好处,你可能要说RocketMQ很好呀,咱们主要看上的就是RabbitMQ支持多语言的客户端,很符合咱们公司的现状,不要咱们花费功夫去搞一个客户端,因此下面请你们不要吐槽,咱们就来静心听听RabbitMQ的好;网络

 2、RabbitMQ异步

      在消息队列的一发一收中,咱们来看下RabbitMQ怎么让咱们放心使用的?首先咱们来看下RabbitMQ发收的过程:性能

      发消息的过程(生产者):设计

      1.链接到RabbitMQ Borker,创建一个链接(Connection),开启一个信道(Channel);接口

      2.声明交换机(Exchange);队列

      3.声明队列(Queue);事务

      4.经过路由键(Binding Key)将交换机与路由器绑定;路由

      5.发送消息(消息包含路由键(Routing Key)和交换机等内容)到RabbitMQ Borker;同步

      6.交换机根据接收到路由键去匹配到相应的队列中,若是找到则放入到对应的队列中,找不到则退回(这里是根据配置信息来的);

      7.关闭;

      收消息的过程(消费者):

      1.链接到RabbitMQ Borker,创建一个链接,开启一个信道;

      2.请求接收RabbitMQ Borker中队列的消息;

      3.等待RabbitMQ Borker回应返回队列中相应的消息;

      4.消费者接收到消息,返回确认(ack);

      5.RabbitMQ移除队列中对应的消息;

      6.关闭;

      针对上面的过程咱们首先来谈下生产者RabbitMQ是如何确保一条消息被投递到RabbitMQ Borker中的,没有使用过消息队列可能听到这里有点懵,这里简单说一下,当生产者发送一条消息的时候,可能由于网络的缘由或者RabbitMQ服务器宕机了,这个时候咱们就没法知道一条消息是否被成功的投递到RabbitMQ中,针对这些状况RabbitMQ给咱们提供两种机制来处理这个问题,一种是事务机制,另一种是消息确认机制。事务机制我想你们都很明白了,RabbitMQ客户端提供与事务机制相关的方法有三个:channel.txSelect、channel.txCommit以及channel.txRollback。channel.txSelect用于将当前信道设置成事务模式,channel.txCommit用于提交事务,channel.txRollback用于事务回滚。当事务开启之后,发送消息给RabbitMQ,若是消息提交成功,那么说明RabbitMQ必定收到了消息,不然咱们能够经过异常来捕获,而后经过txRollback回滚,固然这种方式性能很差,事务机制将消息串行化,致使发送一条消息必须等待结果。这种方式不太好,那么咱们接下来探讨一下消息确认机制,涉及到消息确认机制的相关方法有两个channel.confirmSelect以及channel.waitForConfirms,首先使用confirmSelect将信道设置成为消息确认模式,当使用消息确认模式的时候,该信道上每发布一条消息都会生成惟一的ID,当消息匹配到相应的队列之后,就会返回一个确认的ack,这个时候生产者就知道投递消息成功了,若是RabbitMQ发生宕机或者错误之后,会返回nack,则表示投递失败,当使用waitForConfirms实际上是将异步的模式串行化,咱们还能够经过addConfirmLister经过ConfirmListener这个回调接口来处理返回值。RabbitMQ经过这两种机制保证消息能被正确投递,生产环境中都是使用批量提交,固然实际生产的时候单纯这样仍是不可以保证消息被正确投递,好比说生产者发送消息时候网络断了一下,就不能保证消息被投递过,因此下一篇我会使用延时队列和消息打标的方式来保证消息会被100%投递到RabbitMQ中,固然也不能说是100%只能说是99.好多个9;

      接下来咱们来探讨下消费者消费的问题,若是消费者在接受到消息之后,好比出现宕机,那么这条消息也就丢失掉了。RabbitMQ针对这种状况,也提供了消息确认机制。当消费订阅队列设置autoAck设置为fals的时候,RabbitMQ经过打标的方式,等收到消息确认的时候将队列中的消息移除出去,若是设置为true,当发送成功之后就将消息移除。当autoAck为fals的时候,RabbitMQ内部会有两种消息,一种是等待投递消息,另一种是等待确认的消息,若是RabbitMQ一直没有收到消费者确认的消息,而且消费此消息的消费者断开,那么RabbitMQ会从新发送该条消息,RabbitMQ从新投递消息的依据就是消费者的该消息链接断开。消费端能够经过重试机制保证消息能被正常消费,若是重试还消费不掉,那么还能够利用下死信队列,经过死信队列中的内容分析程序中可能存在的异常;提到了死信队列,咱们这里也介绍一下,消息成为死信有3种状况:消费端消息被拒绝,并设置requeue参数为false、消息过时以及队列达到最大长度,绑定死信队列的交换机就是死信交换机(DLX),当队列中有死信的时候,RabbitMQ会自动将消息从新发布到设置DLX上,从而被路由死信队列中;

     RabbitMQ自己是能够将交换机、队列以及消息都持久化的,固然是不建议将消息持久化的,成本过高。RabbitMQ支持集群模式,是经过多副本的方式实现集群模式,在RabbitMQ中叫作镜像队列,当Master宕机之后会按照下面步骤进行:

     1.与Master相关联的客户端会所有断开;

     2.选举最老的Savle节点做为Master,若是这个时候全部Salve都没处于同步状态,则未同步的消息会被丢失掉;

     3.出于对消息可靠性的考虑,新的Master会从新入队全部客户端未确认的消息;

     4.若是客户端连着slave,而且Basic.Consume消费时指定了x-cancel-on-ha-failover参数,那么客户端会接收到一个Consumer Cancellation Notification通知。若是未指定x-cancal-on-ha-failover参数,那么消费者就没法感知master宕机,会一直等待下去。

     另外RabbitMQ还支持优先级队列、多协议、多租户等等,性能方面的话能知足咱们公司业务,记得好像咱们这边高峰期达到4W-5W/s,最主要的RabbitMQ社区很活跃;

3、结束

     下一篇我会使用Java和C#分别去实现上面生产者和消费者的模式,本文主要参考厮大的书和工做中使用RabbitMQ的经验, 另外在推荐下厮大的书《RabbitMQ实战指南》和《深刻理解Kafka:核心设计与实践原理》,讲的真的好,欢迎你们加群438836709,欢迎你们关注我!

      

相关文章
相关标签/搜索