一、消息队列学习
MQ是一个互联网架构中常见的解耦利器。
什么时候不使用MQ?
上游实时关注执行结果
什么时候使用MQ?
1)数据驱动的任务依赖,多个任务需要轮流执行,轮流订阅上一个任务。
2)上游不关心多下游执行结果,上游执行完发送到MQ,多下游订阅MQ。
3)异步返回执行时间长
死信队列多了一个过期的机制,到期会自动去尝试消费,通过死信交换机做匹配,选择想要的消费失败的消息。
https://ke.qq.com/course/288116#term_id=100341172 入门视频
消息中间件是在消息传输过程中保存消息的容器。队列的主要目的是提供路由并保证消息的传递。
特点:
1异步处理模式
2多个应用程序调用关系为松耦合关系
传递模型:
1、点多点模型PTP
每个消息只用一个消费者
发送者和接收者没有时间依赖
接受者确认消息接受和处理成功
2、发布-订阅模型Pub/Sub
一对多关系,通过订阅主题,发布者建立一个订阅,订阅者保持持续的活动状态以接收消息。
每个消息可以有多个订阅者
客户端只有订阅后才能接收到消息,有时间依赖。
持久订阅 订阅关系建立后,消息不会消失,不管订阅者是否都在线
非持久订阅 订阅者为了接受消息,必须一直在线
典型的应用案例
1、注册时发送邮件或发送短信
2、日志分析使用,多个服务产生的数据发送到中间件发送到分析服务。
3、消息复制,用于跨机房数据传输、搜索、离线数据计算等。
4、延迟消息发送和暂存,把中间件当成可靠的消息暂存地。接受消息,暂时先不发送。
二、RabbitMQ简介
MQ全称为Message Queue,即消息队列, RabbitMQ是由erlang语言开发,基于AMQP(Advanced Message Queue 高级消息队列协议)协议实现的消息队列,它是一种应用程序之间的通信方法,消息队列在分布式系统开发中应用非常广泛。RabbitMQ官方地址:http://www.rabbitmq.com/
ConnectionFactory、Connection、Channel
ConnectionFactory、Connection、Channel都是RabbitMQ对外提供的API中最基本的对象。Connection是RabbitMQ的socket链接,它封装了socket协议相关部分逻辑。ConnectionFactory为Connection的制造工厂。
Channel是我们与RabbitMQ打交道的最重要的一个接口,我们大部分的业务操作是在Channel这个接口中完成的,包括定义Queue、定义Exchange、绑定Queue与Exchange、发布消息等。
一、快速入门
工作模式:
组成部分说明:
Broker:消息队列服务进程,此进程包括两个部分:Exchange和Queue。
Exchange:消息队列交换机,按一定的规则将消息路由转发到某个队列,对消息进行过虑。
Queue:消息队列,存储消息的队列,消息到达队列并转发给指定的消费方。
Producer:消息生产者,即生产方客户端,生产方客户端将消息发送到MQ。
Consumer:消息消费者,即消费方客户端,接收MQ转发的消息。
消息发布接收流程:
-----发送消息-----
1、生产者和Broker建立TCP连接。
2、生产者和Broker建立通道。
3、生产者通过通道消息发送给Broker,由Exchange将消息进行转发。
4、Exchange将消息转发到指定的Queue(队列)
----接收消息-----
1、消费者和Broker建立TCP连接
2、消费者和Broker建立通道
3、消费者监听指定的Queue(队列)
4、当有消息到达Queue时Broker默认将消息推送给消费者。
5、消费者接收到消息。
消息生产者(Producer)
一个发送消息的程序,主要是发送消息。
消息队列(Queue)
队列是生活在RabbitMQ中的邮箱的名称。尽管消息流经RabbitMQ和您的应用程序,但它们只能存储在队列中。一个队列只受主机内存和磁盘限制的约束,它本质上是一个很大的消息缓冲区。许多生产者可以发送进入一个队列的消息,并且许多消费者可以尝试从一个队列接收数据。这就是我们代表队列的方式:
消息生产者(Consumer)
一个消费者是一个程序,主要是等待接收消息。
1)基础概念
基础结构图:
broker:代理人,简单来说就是消息队列服务器实体。
exchange:消息交换机,它指定消息按什么规则,路由到哪个队列。
queue:消息队列载体,每个消息都会被投入到一个或多个队列。
binding:绑定,它的作用就是把exchange和queue按照路由规则绑定起来。
routing key:路由关键字,exchange根据这个关键字进行消息投递。
vhost:虚拟空间,一个broker里可以开设多个vhost,用作不同用户的权限分离。
producer:消息生产者,就是投递消息的程序。
consumer:消息消费者,就是接受消息的程序。
channel:消息通道,在客户端的每个连接里,可建立多个channel,每个channel代表一个会话任务。
2)重点介绍一些比较重要基础概念
① Quque:(队列)
Quque(队列)是RabbitMQ的内部对象,用于存储信息,有下图(1-3-2-1)表示(1-3-2-1)
RabbitMQ中的信息只能存储在Quque中,生产者(下图中的P)生产者消息并最终投递到Quque中,消费者(如图中1-3-2-2的C)可以从Quque中获取消息并消费。(1-3-2-2)
多个消费者可以订阅同一个Quque,这时Quque中的消息会被平均分摊给多个消费者进行处理,而不是每个消费者都收到所有消息并处理。
② Message acknowlegment:(消息回执)
在实际应用中,可能会发生消费者收到Quque中的消息,但没有处理完成就宕机的情况,这种情况下,就可能导致信息丢失,为了避免这种情况发生,我们可以要求消费者在消费完消息后发送一个回执给RabbitMQ,RabbitMQ收到消息回执(Message acknowledge)后,才将该消息从Quque中移除。如果RabbitMQ没有收到回执,并检测到消费者的RabbitMQ链接断开,则RabbitMQ 会将该消息发送给其他消费者(如果存在多个消费者的情况下)进行处理,这里不存在timeout的概念,一个消费者处理消费时间不管多么长也不会导致该消息被发送给其他消费者,除非它的RabbitMQ连接断开;
注意:这里会产生一个问题,如果开发人员再处理业务完成逻辑后,忘记发送回执给RabbitMQ,这将会导致严重的bug---Quque中堆积的消息会越来越多;消费者重启会重复消费这些消息并重复执行业务逻辑。
③Message durability:(消息持久化)
如果我们希望即使在RabbitMQ在重启的情况下,也不会丢失消息,那么我们将Quque与Message都设置成可持久化的(durability),这样就可以保证绝大部分情况下我们的RabbitMQ消息不会丢失。但依然解决不了小概率的丢失事件的发生(比如 RabbitMQ服务器已经接收到生产者的消息,但是,还没有来的及持久化该消息时,RabbitMQ服务器就断电了或者宕机了),如果我们需要对这种小概率事件也要管理起来的话,那么我们需要用到事务。
④ Prefetch count (预取数目)
前面我们提到了如果有多个消费者同时订阅同一个Quque中的消息,Quque中的消息会被平摊给多个消费者。这时如果每个消息的处理时间不同,就有可能导致某些消费者一直很忙,而另一些消费者很快处理完手头上工作,并一直空闲的情况下。我们可以通过设置prefetch count=1,则Quque每次给每个消费者发送一条消息;消费者处理完这条消息后Quque会再给消费者发送一条消息。
⑤ Exchange (交换器)
上一节我们看到生产者将消息投递到Quque中,实际上这在RabbitMQ是不可能发生的,实际上的情况是,生产者将消息发送到Exchange(交换器,下图中X),Exchange将消息路由到一个或者多个Quque中或者丢弃。
Exchange是按照什么逻辑将消息路由到Quque的?这将在Binding一节详谈。
RabbitMQ中的Exchange有四种类型,不同的类型有着不同的路由策略,这将在Exchange Types一节详谈
⑥ routing key(路由key)
生产者在将消息发送给Exchange的时候,一般会指定一个routing key,来指定这个路由规则,而这个routing key需要与 Exchange Type 与binding key 联合使用才能最终生效。
在Exchange Tpye 与binding key 固定的情况下(在正常使用情况下,这些内容都是配置好的),我们的生产者就可以在发送消息给Exchange的时候,通过指定routing key 来指定消息流的流向哪里。
⑦ Binding (绑定)
RabbitMQ 中通过Binding 将Exchange 与Quque关联起来,这样RabbitMQ就知道如何正确地将消息路由到指定的Quque了
⑧ Exchange Type (更换类型)
RabbitMQ常用的Exchange Tpye 有fanout、direct、top、headers这四种
⑩ direct (重定向)
direct类型的Exchange路由规则也很简单,它会把消息路由到那些binding key与routing key完全匹配的Queue中。
⑪ topic(主题)
前面讲到direct类型的Exchange路由规则是完全匹配binding key与routing key,但这种严格的匹配方式在很多情况下不能满足实际业务需求。topic类型的Exchange在匹配规则上进行了扩展,它与direct类型的Exchage相似,也是将消息路由到binding key与routing key相匹配的Queue中,但这里的匹配规则有些不同,它约定:
(1)routing key为一个句点号“. ”分隔的字符串(我们将被句点号“. ”分隔开的每一段独立的字符串称为一个单词),如“stock.usd.nyse”、“nyse.vmw”、“quick.orange.rabbit”
(2)binding key与routing key一样也是句点号“. ”分隔的字符串
(3)binding key中可以存在两种特殊字符“*”与“#”,用于做模糊匹配,其中“*”用于匹配一个单词,“#”用于匹配多个单词(可以是零个)】
以上图中的配置为例,routingKey=”quick.orange.rabbit”的消息会同时路由到Q1与Q2,routingKey=”lazy.orange.fox”的消息会路由到Q1,routingKey=”lazy.brown.fox”的消息会路由到Q2,routingKey=”lazy.pink.rabbit”的消息会路由到Q2(只会投递给Q2一次,虽然这个routingKey与Q2的两个bindingKey都匹配);routingKey=”quick.brown.fox”、routingKey=”orange”、routingKey=”quick.orange.male.rabbit”的消息将会被丢弃,因为它们没有匹配任何bindingKey。
⑫ headers
headers类型的Exchange不依赖于routing key与binding key的匹配规则来路由消息,而是根据发送的消息内容中的headers属性进行匹配。
在绑定Queue与Exchange时指定一组键值对;当消息发送到Exchange时,RabbitMQ会取到该消息的headers(也是一个键值对的形式),对比其中的键值对是否完全匹配Queue与Exchange绑定时指定的键值对;如果完全匹配则消息会路由到该Queue,否则不会路由到该Queue。
该类型的Exchange没有用到过(不过也应该很有用武之地),所以不做介绍。
⑬ RPC(远程过程调用)
MQ本身是基于异步的消息处理,前面的示例中所有的生产者(P)将消息发送到RabbitMQ后不会知道消费者(C)处理成功或者失败(甚至连有没有消费者来处理这条消息都不知道)。
但实际的应用场景中,我们很可能需要一些同步处理,需要同步等待服务端将我的消息处理完成后再进行下一步处理。这相当于RPC(Remote Procedure Call,远程过程调用)。在RabbitMQ中也支持RPC。
RabbitMQ中实现RPC的机制是:
(1)客户端发送请求(消息)时,在消息的属性(MessageProperties,在AMQP协议中定义了14中properties,这些属性会随着消息一起发送)中设置两个值replyTo(一个Queue名称,用于告诉服务器处理完成后将通知我的消息发送到这个Queue中)和correlationId(此次请求的标识号,服务器处理完成后需要将此属性返还,客户端将根据这个id了解哪条请求被成功执行了或执行失败)
(2)服务器端收到消息并处理
(3)服务器端处理完消息后,将生成一条应答消息到replyTo指定的Queue,同时带上correlationId属性
(4)客户端之前已订阅replyTo指定的Queue,从中收到服务器的应答消息后,根据其中的correlationId属性分析哪条请求被执行了,根据执行结果进行后续业务处理
二、安装
erlang环境的配置:
由于rabbitMQ是erlang语言开发,所有rabbitMQ运行必须依托于erlang环境。
erlang的下载地址:http://erlang.org/download/otp_win64_22.0.exe
安装完成后配置环境变量:ERLANG_HOME=F:\erlang\erl10.4(安装目录)
path中添加%ERLANG_HOME%\bin;
rabbitMQ安装:
rabbitMQ下载地址:https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.7.15/rabbitmq-server-3.7.15.exe
安装成功后会自动创建RabbitMQ服务并且启动。
1)从开始菜单启动RabbitMQ
完成在开始菜单找到RabbitMQ的菜单:
说明:
RabbitMQ Service-install :安装服务
RabbitMQ Service-remove 删除服务
RabbitMQ Service-start 启动
RabbitMQ Service-stop 启动
2)安装管理插件
安装rabbitMQ的管理插件,方便在浏览器端管理RabbitMQ
管理员身份运行 rabbitmq-plugins.bat enable rabbitmq_management
3、启动成功 登录RabbitMQ
进入浏览器,输入:http://localhost:15672
初始账号和密码:guest/guest
登录成功!
来源:CSDN
作者:子墨秋风
链接:https://blog.csdn.net/weixin_35650916/article/details/103487749