RabbitQM(消息队列)

前言  


简介:RabbitMQ 是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件)。RabbitMQ服务器是用Erlang语言编写的,最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。

AMQP,即 Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。消息中间件主要用于组件之间的解耦,消息的发送者无需知道消息使用者的存在,反之亦然。AMQP 的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。

使用场景:

1. 解耦:基于消息的模型,关心的是“通知”,而非“处理”。例如短信、邮件通知、缓存刷新等操作使用消息队列进行通知。

2. 异步提升效率:将不是必须的业务逻辑,异步处理。例如在用户注册系统,我们主要的业务逻辑就是把用户注册的信息进行持久化存储,而对于非主要业务进行异步处理(如消息通知),以提升用户注册响应。

3. 流量削峰:比数据库(mysql)写入速率快,并利用消息确认机制控制流量(并发)。

目录


一:消息中间件模型

二:模型图中的对象和属性

三:RabbitMQ常用命令

四:Spring Boot 之RabbitMQ示例

五:RabbitMQ 消息确认(ack)机制

六:RabbitMQ集群简介




 

一:消息中间件模型

1.1  一般模型图

1.2 RabbitMQ模型图

二:模型图中的对象和属性

2.1 生产者

            顾名思义就是生产消息对象的人

2.2 消费者

           就是消费消息的人

2.3 消息队列 

          存储消息的容器

属性 :

1 属性1:Name   名字
2 属性2:  Durability #定义该队列在重启后的是否存在
3 属性3:  Auto delete #当为yes时,当连接该队列的所有消费者断开连接时,该队列自动删除。
4 属性4:  Arguments #定义该队列的其它属性,例如该队列可以容纳的最大消息数量,一个消息在该队列的最大存活时间等等。
View Code

 

备注:下面是一个通过客户端java声明的一个消息队列queue对象

      Queue [name=xxtz, durable=true, autoDelete=false, exclusive=false, arguments={x-message-ttl=50000}, actualName=xxtz]

2.4 消息

         就是消息对象

属性:

1 属性1:Delivery mode #该消息是否持久化
2 属性2:Headers #消息的头部
3 属性3:Properties #消息的其它属性content_type,content_encoding,priority 。。。。。
4 属性4: body #消息的正文 
View Code

 

备注:通过Java声明的消息对象 :(Body:'那个谁: id = 130' MessageProperties [headers={}, contentType=text/plain, contentEncoding=UTF-8, contentLength=19, deliveryMode=PERSISTENT, priority=0, deliveryTag=0])

2.5 交换机

         即接受生产者传递过来的消息对象,并根据消息对象的属性和绑定的的策略来把消息路由到不同消息队列中。

属性:

1 属性1:Name
2 属性2:Type  交换机的类型,共四种,借助web参看 
3 属性3:Durability 持久化该交换机
4 属性4:Auto delete  当最后一个与该交换机绑定的queue,与之解绑后该交换机自动删除
5 属性5:Arguments 
View Code

 

备注:通过客户端java声明的一个交换机queue对象

      Exchange [name=xxtzExchange, type=direct, durable=true, autoDelete=false, internal=false, arguments={}]

备注:四种交换机绑定图

 

        图一:fanout交换机                              图二:direct交换机                                             图三:topic交换机

2.5.1 路由机制:

      direct :  根据关键字精确路由到queue中。支持一个queue绑定多个关键字时

      fanout:  忽略关键字,只要queue绑定了交换机,发送到该交换机的消息就会被转发到queue中

      topic    :   当声明绑定关系的时候可以使用匹配符*‘*’ (星号)‘#’(井号)

                      备注1:'*'(星号)精确匹配一个单词

                      备注2:'#'(井号)可以匹配多个单词

                      备注3: 单词之间需用'.'(英文点)分割

      header :   交换机绑定queue时,指定多个key=value属性。发送到该交换机中消息,交换机会取消息的头,并匹配绑定时的属性,并路由到匹配中的queue中。                 

三:RabbitMQ常用命令

3.1 https://www.cnblogs.com/jinliang374003909/p/10773189.html

四:Spring Boot 之RabbitMQ示例

    类似Spring与其它服务端的交互方式,如与mysql数据库服务器,Spring封装了一个jdbcTemplate。在于RabbitMQ服务器交互封装了一个AmqpTemplate对象,我们只需调用该对象的相关API即可。

4.1  发送消息步骤

步骤一:声明消息队列Queue

步骤二:声明交换机exchange

步骤三:声明绑定关系()

步骤四:通过调用AmqpTemplate对象api发送消息  

4.2  消费消息示例

步骤一:通过@RabbitListener (用于类上)注册消费者(监听者)

步骤二:通过@RabbitHandler(用于方法上) 注册消息者api用于处理监听到的消息。

五:RabbitMQ 消息确认(ack)机制

5.1  Confirm 确认 :即生产者需要确认消息已正确发布到服务器 

5.2  Return 消息机制 :即当rabbitMQ服务器无法路由指定消息到任何一个消息队列时(默认删除丢弃该消息),返回该消息给生产者

5.3  消费端 Ack 和 Nack 机制 : RabbitMQ推送消息到消费者,消费者需手动确认。服务端相应消费者的确认,并处理相应(删除该消息还是从新分配。。。。)

 

示例:发送 https://github.com/374003909/RabbitQM/blob/master/src/main/java/com/example/RabbitQM/ack/AckSender.java

示例:接受 https://github.com/374003909/rabbitqm2/blob/master/src/main/java/com/example/rabbitqm2/direct/XxtzReceiver3.java

六:RabbitMQ集群简介

前提条件

     *  唯一的节点名称,并配置在/etc/hosts目录下(可通过 ping  wxapp203 测试各节点是否联通)

172.16.50.216 wxapp216
172.16.50.203 wxapp203
172.16.50.211 wxapp211

  *   确保各节点下的.erlang.cookie(/var/lib/rabbitmq/.erlang.cookie)值相同,并且确保权限为600  (先修改权限chmod u+w .erlang.cookie)

备注:scp  wxapp203:/var/lib/rabbitmq/.erlang.cookie ./  (scp 基于ssh登陆进行安全的远程文件拷贝命令,需要验证密码)

5.1  一般集群

    *  关闭当前节点   rabbitmqctl stop_app

    *  重置当前节点   rabbitmqctl reset

    *  加入集群    rabbitmqctl join_cluster rabbit@wxapp203   

       备注1:默认是disk节点,我们可以指定参数--ram 创建ram节点  rabbitmqctl join_cluster --ram rabbit@wxapp203:

       备注2:建议集群中disk节点的数量为(n/2)+1 个

    *  启动当前节点   rabbitmqctl start_app  (加入集群)

备注1:查看集群状态  rabbitmqctl cluster_status

备注2:一般模式集群特征,集群通信依赖节点之间的通信,例如有两个节点A,B.

5.2 镜像集群

 通过设置集群策略来定制高可用集群

     命令:rabbitmqctl set_policy ha-all "^"  '{"ha-mode":"all"}'

     命令解释:

            rabbitmqctl  rabbitmq的集群管理工具(插件)

    set_policy   指定类型,设置策略

    ha-all          命名策略名称

    "^"               匹配模式,所用匹配(对正则表达式完全支持), 

    {"ha-mode":"all"}   策略类型all(供三种exactly,all,nodes),即集群中的所用节点都会复制一份queue。

                      ha-mode    策略对象的必选属性(关键词),

                      ha-params                    可选属性

备注1:如果如果结合java项目定义的策略不生效,可删除所用queue和exchange后重启项目(即重新定义queue和exchange)

备注2:常用策略类型,

exactly  {"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"}
nodes   {"ha-mode":"nodes","ha-params":["rabbit@nodeA", "rabbit@nodeB"]}
all {"ha-mode":"all"},即实例

备注3:查看镜像集群 

    方法一:查看UI页面

    方法二:rabbitmqctl list_queues name policy pid slave_pids 

参考资料 

https://www.rabbitmq.com/tutorials/tutorial-six-java.html 

https://www.cnblogs.com/ityouknow/p/6120544.html 

https://www.zouyesheng.com/rabbitmq.html

https://blog.csdn.net/hellozpc/article/details/81436980

项目地址 : https://github.com/374003909/RabbitQM






 

 四:分配策略

       即队列中的消息如何分配给不同消费者,假设这样的场景,一个消息队列中有多条消息,rabbitQM服务器发现了一个消费者,它是一次性的把所有消息分配给该消费者呢?还是该消费者消费了一个消息(假设消费一个消息需要10秒钟)后在分配另一个消息呢?如果先发现一个消费者后又发现一个消费者怎么分配?如果一次发现多个消费者消息又如何分配呢?。。。。。

分配策略一:

分配策略二:

测试Spring Boot默认的分配策略?

场景一:一次性发现两(多)个消费者。

  结论:消息队列中的消息平均分配给两个消费者,即一个消费者只消费偶数消息,另一个消费者只消费奇数消息

场景二:  一次性发现两(多)个消费者。在消费时其中一个消费者showdown了,怎么消费?

       结论:

场景三:先发现一个消费者后又发现一个消费者,怎么消费?

      结论:如果第一个消费者不死,第二个消费者不会消费到消息

分配策略小结:

       真对Spring Boot的默认分配策略分析,rabbitqm服务器在分配队列中的消息时,会先查看监控该队列的消费者,然后制定分配策略。分配策略一旦制定如果消费者不出意外,就按这个策略执行。但如果消费者发生意外导致不能正确相应服务器(Message acknowledgment 策略)。先前分配给该消费者的消息会重新被rabbitqm服务器分配(即一种递归策略)

 

     

 

posted @ 2019-06-03 22:43  爱我-中华  阅读(588)  评论(0编辑  收藏  举报