学习springBoot(9)RabbitMQ

400 阅读12分钟

在写代码之前先简单介绍下消息队列

MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法。MQ是消费-生产者模型的一个典型的代表,一端往消息队列中不断写入消息,而另一端则可以读取队列中的消息。

各种消息队列基本信息对比,从别处贴的,自己也还不是很懂。。。。

原址:blog.csdn.net/zollty/arti…

ActiveMQ RabbitMQ RocketMQ Kafka ZeroMQ
吞吐量 比RabbitMQ低 2.6w/s(消息做持久化) 11.6w/s 17.3w/s 29w/s
开发语言 Java Erlang Java Scala/Java C
主要维护者 Apache Mozilla/Spring Alibaba Apache iMatix,创始人已去世
成熟度 成熟 成熟 开源版本不够成熟 比较成熟 只有C、PHP等版本成熟
文档和注释 很少 较少 很少
订阅形式 点对点(p2p)、广播(发布-订阅) 提供了4种:direct, topic ,Headers和fanout。fanout就是广播模式 基于topic/messageTag以及按照消息类型、属性进行正则匹配的发布订阅模式 基于topic以及按照topic进行正则匹配的发布订阅模式 点对点(p2p)
持久化 支持少量堆积 支持少量堆积 支持大量堆积 支持大量堆积 不支持
顺序消息 不支持 不支持 支持 支持 不支持
消息回溯 不支持 不支持 支持指定时间点的回溯 支持指定分区offset位置的回溯 不支持
性能稳定性 一般 较差 很好
负载均衡 可以支持 可以支持 支持较好 支持很好 不支持
集群方式 支持简单集群模式,比如'主-备',对高级集群模式支持不好。 支持简单集群,'复制'模式,对高级集群模式支持不好。 常用 多对'Master-Slave' 模式,开源版本需手动切换Slave变成Master 天然的‘Leader-Slave’无状态集群,每台服务器既是Master也是Slave 不支持
管理界面 一般 较好 一般

言归正传,今天的主角还是rabbit , 别的以后有时间在一一研究,首先还是先了解一下rabbit的基础知识,继续贴了。。

原址:blog.csdn.net/dreamchaser…

RabbitMQ是MQ的一种。下面详细介绍一下RabbitMQ的基本概念。

1、队列、生产者、消费者

  队列是RabbitMQ的内部对象,用于存储消息。生产者(下图中的P)生产消息并投递到队列中,消费者(下图中的C)可以从队列中获取消息并消费。

多个消费者可以订阅同一个队列,这时队列中的消息会被平均分摊给多个消费者进行处理,而不是每个消费者都收到所有的消息并处理。

2、Exchange、Binding

  刚才我们看到生产者将消息投递到队列中,实际上这在RabbitMQ中这种事情永远都不会发生。实际的情况是,生产者将消息发送到Exchange(交换器,下图中的X),再通过Binding将Exchange与Queue关联起来。

3、Exchange Type、Bingding key、routing key

  在绑定(Binding)Exchange与Queue的同时,一般会指定一个binding key。在绑定多个Queue到同一个Exchange的时候,这些Binding允许使用相同的binding key。

  生产者在将消息发送给Exchange的时候,一般会指定一个routing key,来指定这个消息的路由规则,生产者就可以在发送消息给Exchange时,通过指定routing key来决定消息流向哪里。

  RabbitMQ常用的Exchange Type有三种:fanout、direct、topic。

  fanout:把所有发送到该Exchange的消息投递到所有与它绑定的队列中。

  direct:把消息投递到那些binding key与routing key完全匹配的队列中。

  topic:将消息路由到binding key与routing key模式匹配的队列中。

  附上一张RabbitMQ的结构图:

最后来具体解析一下几个问题:

1、可以自动创建队列,也可以手动创建队列,如果自动创建队列,那么是谁负责创建队列呢?是生产者?还是消费者

  如果队列不存在,当然消费者不会收到任何的消息。但是如果队列不存在,那么生产者发送的消息就会丢失。所以,为了数据不丢失,消费者和生产者都可以创建队列。那么如果创建一个已经存在的队列呢?那么不会有任何的影响。需要注意的是没有任何的影响,也就是说第二次创建如果参数和第一次不一样,那么该操作虽然成功,但是队列属性并不会改变。

  队列对于负载均衡的处理是完美的。对于多个消费者来说,RabbitMQ使用轮询的方式均衡的发送给不同的消费者。

2、RabbitMQ的消息确认机制

  默认情况下,如果消息已经被某个消费者正确的接收到了,那么该消息就会被从队列中移除。当然也可以让同一个消息发送到很多的消费者。

  如果一个队列没有消费者,那么,如果这个队列有数据到达,那么这个数据会被缓存,不会被丢弃。当有消费者时,这个数据会被立即发送到这个消费者,这个数据被消费者正确收到时,这个数据就被从队列中删除。

 那么什么是正确收到呢?通过ack。每个消息都要被acknowledged(确认,ack)。我们可以显示的在程序中去ack,也可以自动的ack。如果有数据没有被ack,那么:

 RabbitMQ Server会把这个信息发送到下一个消费者。

 如果这个app有bug,忘记了ack,那么RabbitMQServer不会再发送数据给它,因为Server认为这个消费者处理能力有限。

而且ack的机制可以起到限流的作用(Benefitto throttling):在消费者处理完成数据后发送ack,甚至在额外的延时后发送ack,将有效的均衡消费者的负载。

3、常见术语

Broker:简单来说就是消息队列服务器实体 

Exchange:消息交换机,它指定消息按什么规则,路由到哪个队列 

Queue:消息队列载体,每个消息都会被投入到一个或多个队列 

Binding:绑定,它的作用就是把exchange和queue按照路由规则绑定起来 

Routing Key:路由关键字,exchange根据这个关键字进行消息投递 

vhost:虚拟主机,一个broker里可以开设多个vhost,用作不同用户的权限分离 

producer:消息生产者,就是投递消息的程序 

consumer:消息消费者,就是接受消息的程序 

channel:消息通道,在客户端的每个连接里,可建立多个channel,每个channel代表一个会话任务

4、Exchange(交换器四种类型)

Fanout :所有发送到Fanout Exchange的消息都会被转发到与该Exchange 绑定(Binding)的所有Queue上。Fanout Exchange 
不需要处理RouteKey 。只需要简单的将队列绑定到exchange上。这样发送到exchange的消息都会被转发到与该交换机绑定的所有
队列上。类似子网广播,每台子网内的主机都获得了一份复制的消息。所以,Fanout Exchange 转发消息是最快的。

Direct :所有发送到Direct Exchange的消息被转发到RouteKey中指定的Queue。Direct模式,可以使用rabbitMQ自带的Exchange:
default Exchange 。所以不需要将Exchange进行任何绑定(binding)操作。消息传递时,RouteKey必须完全匹配,才会被队列接收
,否则该消息会被抛弃。

Topic :所有发送到Topic Exchange的消息被转发到所有关心RouteKey中指定Topic的Queue上,Exchange 将RouteKey 和某Topic
进行模糊匹配。此时队列需要绑定一个Topic。可以使用通配符进行模糊匹配,符号“#”匹配一个或多个词,符号“*”匹配不多不少
一个词。因此“log.#”能够匹配到“log.info.oa”,但是“log.*” 只会匹配到“log.error”。所以,Topic Exchange 使用非常灵活。

header : 此类型的exchange和以上三个都不一样,其路由的规则是根据header来判断

5、RabbitMQ的5种模式与实例

5.1、简单模式(点对点):
    功能:一个生产者P发送消息到队列Q,一个消费者C接收
    
    生产者实现思路:
    
    创建连接工厂ConnectionFactory,设置服务地址127.0.0.1,端口号5672,设置用户名、密码、virtual
    host,从连接工厂中获取连接connection,使用连接创建通道channel,使用通道channel创建队列queue,使用通道channel向队列中发送消息,关闭通道和连接。
    
    消费者实现思路
    
    创建连接工厂ConnectionFactory,设置服务地址127.0.0.1,端口号5672,设置用户名、密码、virtualhost,从连接工厂中获取连接connection,使用连接创建通道channel,使用通道channel创建队列queue, 创建消费者并监听队列,从队列中读取消息。

5.2、工作队列模式Work Queue:
    功能:一个生产者,多个消费者,每个消费者获取到的消息唯一,多个消费者只有一个队列
    
    任务队列:避免立即做一个资源密集型任务,必须等待它完成,而是把这个任务安排到稍后再做。我们将任务封装为消息并将其发送给队列。后台运行的工作进程将弹出任务并最终执行作业。当有多个worker同时运行时,任务将在它们之间共享。
    
    
    生产者实现思路:
    
    创建连接工厂ConnectionFactory,设置服务地址127.0.0.1,端口号5672,设置用户名、密码、virtual
    host,从连接工厂中获取连接connection,使用连接创建通道channel,使用通道channel创建队列queue,使用通道channel向队列中发送消息,2条消息之间间隔一定时间,关闭通道和连接。
    
    消费者实现思路:
    
    创建连接工厂ConnectionFactory,设置服务地址127.0.0.1,端口号5672,设置用户名、密码、virtual
    host,从连接工厂中获取连接connection,使用连接创建通道channel,使用通道channel创建队列queue,创建消费者C1并监听队列,获取消息并暂停10ms,另外一个消费者C2暂停1000ms,由于消费者C1消费速度快,所以C1可以执行更多的任务。

5.3、发布/订阅模式Publish/Subscribe
    功能:一个生产者发送的消息会被多个消费者获取。一个生产者、一个交换机、多个队列、多个消费者
    
    生产者:可以将消息发送到队列或者是交换机。
    
    消费者:只能从队列中获取消息。
    
    如果消息发送到没有队列绑定的交换机上,那么消息将丢失。
    
    交换机不能存储消息,消息存储在队列中
    
    生产者实现思路:
    
    创建连接工厂ConnectionFactory,设置服务地址127.0.0.1,端口号5672,设置用户名、密码、virtual
    host,从连接工厂中获取连接connection,使用连接创建通道channel,使用通道channel创建队列queue,使用通道channel创建交换机并指定交换机类型为fanout,使用通道向交换机发送消息,关闭通道和连接。
    
    消费者实现思路:
    
    创建连接工厂ConnectionFactory,设置服务地址127.0.0.1,端口号5672,设置用户名、密码、virtual
    host,从连接工厂中获取连接connection,使用连接创建通道channel,使用通道channel创建队列queue,绑定队列到交换机,设置Qos=1,创建消费者并监听队列,使用手动方式返回完成。可以有多个队列绑定到交换机,多个消费者进行监听。

5.4、路由模式Routing
    说明:生产者发送消息到交换机并且要指定路由key,消费者将队列绑定到交换机时需要指定路由key
    
    生产者实现思路:
    
    创建连接工厂ConnectionFactory,设置服务地址127.0.0.1,端口号5672,设置用户名、密码、virtual
    host,从连接工厂中获取连接connection,使用连接创建通道channel,使用通道channel创建队列queue,使用通道channel创建交换机并指定交换机类型为direct,使用通道向交换机发送消息并指定key=b,关闭通道和连接。
    
    消费者实现思路:
    
    创建连接工厂ConnectionFactory,设置服务地址127.0.0.1,端口号5672,设置用户名、密码、virtual
    host,从连接工厂中获取连接connection,使用连接创建通道channel,使用通道channel创建队列queue,绑定队列到交换机,设置Qos=1,创建消费者并监听队列,使用手动方式返回完成。可以有多个队列绑定到交换机,但只要绑定key=b的队列key接收
    到消息,多个消费者进行监听。

5.5、通配符模式Topics  
    说明:生产者P发送消息到交换机X,type=topic,交换机根据绑定队列的routing key的值进行通配符匹配;符号#:匹配一个或者多个词lazy.# 可以匹配lazy.irs或者lazy.irs.cor
    
    符号*:只能匹配一个词lazy.* 可以匹配lazy.irs或者lazy.cor
    
    生产者实现思路:
    
    创建连接工厂ConnectionFactory,设置服务地址127.0.0.1,端口号5672,设置用户名、密码、virtual
    host,从连接工厂中获取连接connection,使用连接创建通道channel,使用通道channel创建队列queue,使用通道channel创建交换机并指定交换机类型为topic,使用通道向交换机发送消息并指定key=key.1,关闭通道和连接。
    
    消费者实现思路:
    
    创建连接工厂ConnectionFactory,设置服务地址127.0.0.1,端口号5672,设置用户名、密码、virtual
    host,从连接工厂中获取连接connection,使用连接创建通道channel,使用通道channel创建队列queue,绑定队列到交换机,设置Qos=1,创建消费者并监听队列,使用手动方式返回完成。可以有多个队列绑定到交换机,凡是绑定规则符合通配符规则的
    队列均可 以接收到消息,比如key.*,key.#,多个消费者进行监听。

基本的知识点上面这些应该都包含了,具体的实现代码下一篇在贴出来。