• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

Rabbit MQ入门和消息分发机制

武飞扬头像
J.King
帮助1

一、消息队列简介

1.1 什么是 MQ

消息队列,又叫做消息中间件。是只用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通信来进行分布式系统的集成。通过提供消息传递和消息队列模型,可以在分布式环境下拓展进程的通信。

1.2 为什么要使用 MQ

1.2.1 异步

同步通信:发出一个调用请求之后,在没有得到结果之前,就不返回。由调用者主动等待这个调用的结果。

异步通信:调用在发出之后,这个调用就直接返回了,所以没有返回结果。也就是说,当一个异步过程调用发出后,调用者不会马上得到结果。而是在调用发出后,被调用者通过状态、通知来通知调用者,或通过回调函数处理这个调用。

举个例子:
大家都用过手机银行的跨行转账功能。大家用APP的转账功能的时候,有一个实时模式,有一个非实时模式。

实时转账实际上是异步通信,因为这个里面涉及的机构比较多,调用链路比较长,本行做了一些列的处理之后,转发给银联或者人民银行的支付系统,再转发给接收行,接受行处理以后再原路返回。

所以转账以后会有一行小字提示:具体到账时间以对方行处理为准,也就是说转出行只保证了这个转账的消息发出。那为什么到账时间又这么快呢?很多时候我们转账之后,不用几秒钟对方就收到了。是因为大部分的MQ都有一个低延迟的特性,能在短时间内处理非常多的消息。

很多理财软件提现也是一样,先提交请求,到账时间不定。这个是用MQ实现系统间异步通信的一个场景。

异步通信不需要客户端等待,可以减少客服端性能消耗,大大地提升用户体验。

1.2.2 解耦

多线程或者线程池是可以实现解耦的,但是每一个需要并行执行的地方都引入线程,又会带来线程或者线程池的管理问题。

比如订单系统退货流程,只需要把退货的消息发送到消息队列上,由各个下游的业务系统自己创建队列,然后监听队列消费消息。

学新通

  • 订单系统只需要把退货的消息发送到消息队列上,由各个下游的业务系统自己创建队列,然后监听队列消费消息。
    如果其他系统做了网络迁移,以前需要在订单系统配置和修改IP、端口、接口地址,现在不需要,因为它不需要关心消费者在网络上的什么位置,只需要配置MQ服务器的地址。
  • 如果某一个下游系统宕机了或者在停机升级,调用接口超时会导致订单系统业务逻辑失败。引入 MQ 以后没有任何影响,消息保存在 MQ 服务器,什么时候下游系统恢复了自己去消费就OK了。
  • 假如下游业务系统运行正常,但是消费出了问题,比如改代码该出问题了或者数据库异常,生产者也不会受到影响。因为它只关心一件事情,就是消息有没有成功地发送到 MQ 服务器。

1.2.3 削峰

你平时流量很低,但是你要做秒杀活动00 :00的时候流量疯狂怼进来,你的服务器,RedisMySQL各自的承受能力都不一样,你直接全部流量照单全收肯定有问题啊,直接就打挂了。

那怎么办?

简单,把请求放到队列里面,然后至于每秒消费多少请求,就看自己的服务器处理能力,你能处理5000QPS你就消费这么多,可能会比正常的慢一点,但是不至于打挂服务器,等流量高峰下去了,你的服务也就没压力了。

你看阿里双十一12:00的时候这么多流量瞬间涌进去,他有时候是不是会慢一点,但是人家没挂啊,或者降级给你个友好的提示页面,等高峰过去了又是一条好汉了。

1.2.4 实现广播通信

实现一对多通信。以订单系统退货为例,如果新增了积分系统,需要获取订单状态变化信息,只需要增加队列监听就可以了,生产者没有任何代码修改。

比如你买了辆保时捷,如果要让村里所有人知道,只要跟一个大妈说一下就行了。

作用小结:

  • 对于数据量大或者处理耗时长的操作,我们可以引入MQ实现异步通信,减少客户端的等待,提升响应速度,优化客户体验。
  • 对于改动影响大的系统之间,可以引入MQ实现解耦,减少系统之间的直接依赖,提升可维护性和可扩展性。
  • 对于会出现瞬间的流量峰值的系统,我们可以引入MQ实现流量削峰,达到保护应用和数据库的目的。
  • 一对多的广播通信。

1.3 使用 MQ 带来的一些问题

1.3.1 系统复杂性

本来蛮简单的一个系统,我代码随便写都没事,现在你凭空接入一个中间件在那,我是不是要考虑去维护他,而且使用的过程中是不是要考虑各种问题,比如消息重复消费消息丢失消息的顺序消费等等,

1.3.2 数据一致性

这个其实是分布式服务本身就存在的一个问题,不仅仅是消息队列的问题,但是放在这里说是因为用了消息队列这个问题会暴露得比较严重一点。

比如你下单的服务自己保证自己的逻辑成功处理了,你成功发了消息,但是优惠券系统,积分系统等等这么多系统,他们成功还是失败你就不管了?

我说了保证自己的业务数据对的就好了,其实还是比较不负责任的一种说法,这样就像个渣男,没有格局这样呀你的路会越走越窄的

所有的服务都成功才能算这一次下单是成功的,那怎么才能保证数据一致性呢?

分布式事务:把下单,优惠券,积分,都放在一个事务里面一样,要成功一起成功,要失败一起失败。

1.3.3 可用性降低

原来是两个节点的通信,现在还需要独立运行一个服务。虽然一般的MQ都有很高的可靠性和低延迟的特性,但是一旦网络或者MQ服务器出现问题,就会导致请求失败,严重地影响业务。

1.4 AMPQ

1.4.1 AMPQ 是什么

AMQP ( Advanced Message Queuing Protocol)高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。

1.4.2 AMQP 架构

学新通

二、RabbitMQ 简介

RabbitMQ 是一个开源的 AMQP 实现,服务器端用 Erlang 语言编写,支持多种客户端。用于在分布式系统中存储转发消息,在易用性、拓展性、高可用性等方面表现不俗。

2.1 工作模型

由于RabbitMQ实现了AMQP协议,所以RabbitMQ的工作模型也是基于AMQP的。理解这张图片至关重要。

学新通

2.2 Producer

Producer:生产者,就是投递消息的一方。生产者创建消息,然后发布到 RabbitMQ中。

消息一般可以包含两个部分:消息体和附加信息。

  • 消息体(payload): 在实际应用中,消息体一般是一个带有业务逻辑结构的数据,比如一个JSON字符串。当然可以进 一步对这个消息体进行序列化操作。 附加信息 用来表述这条消息,比如目标交换器的名称、路由键和一些自定义属性 等等。
  • 附加信息:用来表述这条消息,比如目标交换器的名称、路由键和一些自定义属性等等。

2.3 Broker

Broker:消息中间件的服务节点 。

对于 RabbitMQ 来说,一个 RabbitMQ Broker 可以简单地看作一个 RabbitMQ 服务节点,或者 RabbitMQ 服务实例。也可以将一个 RabbitMQ Broker看作一台 RabbitMQ 服务器。

2.4 .Connection

无论是生产者发送消息,还是消费者接收消息,都必须要跟Broker之间建立一个连接,这个连接是一个 TCP 的长连接。

如果把 Connection 比作一条光纤电缆的话,那么 Channel 信道就比作成光纤电缆中的其中一束光纤。一个 Connection 上可以创建任意数量的 Channel。

2.5 Channel

Channel:频道或信道,是建立在Connection连接之上的一种轻量级的连接。

如果所有的生产者发送消息和消费者接收消息,都直接创建和释放 TCP 长连接的话,对于 Broker 来说肯定会造成很大的性能损耗,也会浪费时间。

所以在 AMQ P里面引入了 Channel 的概念,它是一个虚拟的连接。我们把它翻译成通道,或者消息信道。这样我们就可以在保持的TCP长连接里面去创建和释放 Channel,大大了减少了资源消耗。

不同的 Channel 是相互隔离的,每个 Channel 都有自己的编号。对于每个客户端线程来说,Channel 就没必要共享了,各自用自己的 Channel。

大部分的操作是在 Channel 这个接口中完成的,包括定义队列的声明queueDeclare、交换机的声明 exchangeDeclare、队列的绑定queueBind、发布消息basicPublish、消费消息basicConsume等。

2.6 RoutingKey

RoutingKey:路由键。生产者将消息发给交换器的时候,一般会指定一个 RoutingKey,用来指 定这个消息的路由规则。

RoutingKey 需要与交换器类型和绑定键( BindingKey )联合使用。在交换器类型和绑定键( BindingKey )固定的情况下,生产者可以在发送消息给交换器时,通过指定RoutingKey 来决定消息流向哪里。

2.7 Exchange

Exchange:交换器,生产者将消息发送到 Exchange (交换器,通常也可以用大写的“X”来表示), 由交换器将消息路由到一个或者多个队列中。如果路由不到,或返回给生产者,或直接丢弃。

2.8 Queue

Queue:队列,是 RabbitMQ 的内部对象,用于存储消息。

2.9 Binding

Binding:绑定,RabbitMQ 中通过绑定将交换器与队列关联起来,在绑定的时候一般会指定一个绑定键 ( BindingKey ) ,这样 RabbitMQ 就知道如何正确地将消息路由到队列了。

2.10 Exchange 类型

RabbitMQ 常用的交换器类型有fanoutdirecttopicheaders 这四种

fanout:(广播)扇型交换机它会把所有发送到该交换器的消息路由到所有与该交换器绑定的队列中

学新通

direct:直连交换机它会把消息路由到那些 BindingKey 和 RoutingKey完全匹配的队列中

学新通

headers:头交换机 不依赖于路由键的匹配规则来路由消息,而是根据发送的消息内容中的 headers 属性进行 匹配

Topic:主题:一个队列与主题类型的交换机绑定时,可以在绑定键中使用通配符。

支持两个通配符:

  • #代表0个或者多个单词
  • *代表不多不少一个单词

单词 ( word )指的是用英文的点“”隔开的字符。例如a.bc.def是3个单词。

学新通

以上图为例,有4个队列绑定到我创建的主题类型的交换机,使用不同的绑定键。

解读:

  • 第一个队列支持路由键以junior开头的消息路由,后面可以有单词,也可以没有。
  • 第二个队列支持路由键以netty结尾,前面可以有也可以没有单词的消息路由。
  • 第三个队列支持路由键以senior开头,并且后面是一个单词的消息路由。
  • 第四个队列支持路由键以jvm结尾,并且前面是一个单词的消息路由。

2.11 Consumer

Consumer:消费者,就是接收消息的一方。

消费者连接到 RabbitMQ 服务器,并订阅到队列 上 。 当消费者消费一条消息时,只是消费消息的消息体 (payload ) 。在消息路由的过程中,消息的标签会丢 弃,存入到队列中的消息只有消息体,消费者也只会消费到消息体,也就不知道消息的生产者是谁,当 然消费者也不需要知道 。

三、RabbitMQ 特点

  • 支持多客户端:对主流开发语言(Python、Java、Ruby、PHP、C#、JavaScript.Go、Elixir、Objective-C、Swift等)都有客户端实现
  • 灵活的路由:通过交换机(Exchange)实现消息的灵活路由
  • 权限管理:通过用户与虚拟机实现权限管理
  • 插件系统:支持各种丰富的插件扩展,同时也支持自定义插件
  • 与Spring集成::Spring 对 AMQP 进行了封装
  • 高可靠::RabbitMQ提供了多种多样的特性让你在可靠性和性能之间做出权衡,包括持久化、发送应答、发布确认以及高可用性。
    ve-C、Swift等)都有客户端实现
  • 灵活的路由:通过交换机(Exchange)实现消息的灵活路由
  • 权限管理:通过用户与虚拟机实现权限管理
  • 插件系统:支持各种丰富的插件扩展,同时也支持自定义插件
  • 与Spring集成::Spring 对 AMQP 进行了封装
  • 高可靠::RabbitMQ 提供了多种多样的特性让你在可靠性和性能之间做出权衡,包括持久化、发送应答、发布确认以及高可用性。
  • 集群与扩展性:多个节点组成一个逻辑的服务器,支持负载。高可用队列:通过镜像队列实现队列中数据的复制

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhfjkfjf
系列文章
更多 icon
同类精品
更多 icon
继续加载