一、前言

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

 二、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社区很活跃;

三、结束

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

我们为什么要使用RabbitMQ?的更多相关文章

  1. 消息队列——RabbitMQ学习笔记

    消息队列--RabbitMQ学习笔记 1. 写在前面 昨天简单学习了一个消息队列项目--RabbitMQ,今天趁热打铁,将学到的东西记录下来. 学习的资料主要是官网给出的6个基本的消息发送/接收模型, ...

  2. RabbitMq应用二

    在应用一中,基本的消息队列使用已经完成了,在实际项目中,一定会出现各种各样的需求和问题,rabbitmq内置的很多强大机制和功能会帮助我们解决很多的问题,下面就一个一个的一起学习一下. 消息响应机制 ...

  3. 如何优雅的使用RabbitMQ

    RabbitMQ无疑是目前最流行的消息队列之一,对各种语言环境的支持也很丰富,作为一个.NET developer有必要学习和了解这一工具.消息队列的使用场景大概有3种: 1.系统集成,分布式系统的设 ...

  4. RabbitMq应用一的补充(RabbitMQ的应用场景)

    直接进入正题. 一.异步处理 场景:发送手机验证码,邮件 传统古老处理方式如下图 这个流程,全部在主线程完成,注册->入库->发送邮件->发送短信,由于都在主线程,所以要等待每一步完 ...

  5. RabbitMq应用一

    RabbitMq应用一 RabbitMQ的具体概念,百度百科一下,我这里说一下我的理解,如果有少或者不对的地方,欢迎纠正和补充. 一个项目架构,小的时候,一般都是传统的单一网站系统,或者项目,三层架构 ...

  6. 缓存、队列(Memcached、redis、RabbitMQ)

    本章内容: Memcached 简介.安装.使用 Python 操作 Memcached 天生支持集群 redis 简介.安装.使用.实例 Python 操作 Redis String.Hash.Li ...

  7. 消息队列性能对比——ActiveMQ、RabbitMQ与ZeroMQ(译文)

    Dissecting Message Queues 概述: 我花了一些时间解剖各种库执行分布式消息.在这个分析中,我看了几个不同的方面,包括API特性,易于部署和维护,以及性能质量..消息队列已经被分 ...

  8. windows下 安装 rabbitMQ 及操作常用命令

    rabbitMQ是一个在AMQP协议标准基础上完整的,可服用的企业消息系统.它遵循Mozilla Public License开源协议,采用 Erlang 实现的工业级的消息队列(MQ)服务器,Rab ...

  9. RabbitMQ + PHP (三)案例演示

    今天用一个简单的案例来实现 RabbitMQ + PHP 这个消息队列的运行机制. 主要分为两个部分: 第一:发送者(publisher) 第二:消费者(consumer) (一)生产者 (创建一个r ...

  10. RabbitMQ + PHP (二)AMQP拓展安装

    上篇说到了 RabbitMQ 的安装. 这次要在讲案例之前,需要安装PHP的AMQP扩展.不然可能会报以下两个错误. 1.Fatal error: Class 'AMQPConnection' not ...

随机推荐

  1. 不带parent指针的successor求解

    问题: 请设计一个算法,寻找二叉树中指定结点的下一个结点(即中序遍历的后继).给定树的根结点指针TreeNode* root和结点的值int p,请返回值为p的结点的后继结点的值.保证结点的值大于等于 ...

  2. SUSE12SP3-Mycat(4)rule.xml配置详解

    简介 rule.xml 里面就定义了我们对表进行拆分所涉及到的规则定义.我们可以灵活的对表使用不同的分片算法, 或者对表使用相同的算法但具体的参数不同.这个文件里面主要有 tableRule 和 fu ...

  3. 【视频】ASP.NET Core MVC 2.* 入门

    比较初级的入门教程,网址在B站:https://www.bilibili.com/video/av33728783/ 内容如下: 1. ASP.NET Core 简介和开发工具 2. ASP.NET ...

  4. MacBook IDEA激活码(附视频)

    Windows激活请看这里:IDEA激活码 此教程实时更新,请放心使用:如果有新版本出现猪哥都会第一时间尝试激活: idea官网下载地址:https://www.jetbrains.com/idea/ ...

  5. ES6躬行记(21)——类的继承

    ES6的继承依然是基于原型的继承,但语法更为简洁清晰.通过一个extends关键字,就能描述两个类之间的继承关系(如下代码所示),在此关键字之前的Man是子类(即派生类),而在其之后的People是父 ...

  6. PyCharm出现TabError: inconsistent use of tabs and spaces in indentation最简单实用的解决办法

    本文使用PyCharm的格式化代码功能解决TabError: inconsistent use of tabs and spaces in indentation. 当把代码从别处复制进来PyChar ...

  7. IOS多态在项目中的应用

    今天我们讲述一个知识点(大家可能遗漏的) 多态是面试程序设计(OOP)一个重要特征,但在iOS中,可能比较少的人会留意这个特征,实际上在开发中我们可能已经不经意的使用了多态.比如说: 有一个table ...

  8. .net 配置swagger

    第一步: 在nuget.org中查找Swashbuckle并下载 在nuget.org中查找Swagger.net.UI,并下载 第二步: 下载完之后,App_Start多了三个文件 Swagger. ...

  9. c#编写一个简单的http服务器

    先来张我的帅照哈哈哈 好了不臭美了   上代码 世间万物 只有想不到 没有做不到  哈哈哈  仔细阅读代码     我要凑够 150个字  哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈 ...

  10. Java SimpleDateFormat处理日期与字符串的转换

    1.为什么要使用SimpleDateFormat? 在Java中,如果我们想获取当前时间,一般会使用Date类的无参构造函数,如下所示,我们获取到当前时间并输出: import java.util.D ...