简谈RabbitMQ
一、先简单了解什么是RabbitMQ
- RabbitMQ(消息队列/消息中间件)是流行的开源消息队列系统,是AMQP(Advanced Message Queuing Protocol高级消息队列协议)的标准实现。用erlang(面向并发)语言开发。RabbitMQ具有良好的性能和实效性,同时还支持集群和负载部署,非常适用于在较大规模的分布式系统中使用。
- Java常见的消息队列技术:RabbitMQ、ActiveMQ、Redis(List数据格式)、JMS(Java Message Service)、Kafka、RocketMQ等。
- 下载地址 RabbitMQ官网:http://www.RabbitMQ.com/
消息队列比较:http://blog.youkuaiyun.com/sunxinhere/article/details/7968886
RabbitMQ下载地址:http://www.RabbitMQ.com/download.html
二、安装(Linux-3.7.X)
三、安装erlang依赖:
安装erlang的rpm库(命令如下)
rpm -ivh erlang-20.3.8.7-1.el6.x86_64.rpm
四、安装socat依赖:
安装socat的rpm库(命令如下)
yum install tcp_wrappers
rpm -ivh socat-1.7.3.0-1.el6.x86_64.rpm
五、安装RabbitMQ:
rpm -ivh rabbitmq-server-3.7.7-1.el6.noarch.rpm
启动RabbitMQ:service rabbitmq-server start/stop/restart
查看RabbitMQ的启动状态 service rabbitmq-server status
六、RabbitMQ配置
启动RabbitMQ后执行:
1、rabbitmqctl add_user admin 123456(创建用户)
2、rabbitmqctl set_user_tags admin administrator(将创建好的用户加入管理员)
3、rabbitmqctl set_permissions -p “/” admin “.” “.” “.*”(授权)
4、rabbitmq-plugins enable rabbitmq_management 启动RabbitMQ管理页面
5、重启MQ服务、开放5672/15672/25672端口。在浏览器输入ip:15672后出现RabbitMQ管理台。
注:
5672:当前RabbitMQ的端口。
15672:RabbitMQ管理台端口。
25672:RabbitMQ集群通信端口。
启动后页面如下:
七、消息队列运行原理
从上图可以看出、生产者、消息队列、消费者是最重要的三个概念:
- 生产者(Producer):创建消息到消息队列中。
- 消息队列(Queue):存储消息。
- 消费者(Consumer):监听指定消息队列,当消息队列接收到消息后,获取消息并处理。
- RabbitMQ:创建消息队列,并提供API给生产者和消费者进行存取消息。
- 生产者产生消息并调用RabbitMQ的API将消息加入到对应的消息队列中,消费者通过RabbitMQ的API从消息队列中获取消息进行消费。
八、RabbitMQ核心
RabbitMQ的核心由虚拟机、交换机、队列、绑定这四部分组成。
1.虚拟机(Virtual Host)
在RabbitMQ中虚拟机主要是用于控制权限颗粒度,RabbitMQ默认的虚拟机路径为/。一个虚拟机至少包含一组交换机、队列和绑定。
例如admin的virtual host为/,zs的virtual host为/test。假设RabbitMQ Server中有/test /hello /demo,那么admin可以操作全部虚拟机下的队列而zs只可以操作/test下的队列。
2.交换机/路由器(Exchange)
RabbitMQ中的交换机本身并不进行消息的存储,主要用做进行消息的转发到指定规则的队列内。生产者在传递消息时并不是直接传到队列中,而是先发送给交换机,交换机会通过消息中的routing_key按照特定的路由算法转发给路由绑定的对应队列。Exchange可以和多个Queue绑定,Exchange本身也可以进行持久化、临时、自动删除。
九、路由规则
- 直接交换器/点对点(Direct)
Direct的工作方式类似单播,Exchange会将x消息转发至ROUTING_KEY完全匹配的队列中。
- 广播交换器(Fanout)
Fanout的工作方式就是广播,Exchange会将消息转发至所有与其绑定的队列中,而不管ROUTING_KEY的是什么。
3. 主题交换器(Topic) Topic的工作方式是模糊匹配,Exchange会将消息转发和ROUTING_KEY匹配模式相同的所有队列。比如ROUTING_KEY为user.dj的Message会转发给绑定匹配模式为包含user.dj的队列(表是匹配一个任意词组,#表示匹配0个或多个词组)。
绑定(binding)
- 所谓的binding就是将交换机与一个特定的队列绑定起来,且交换机与队列的关系可以是一对一、一对多、多对多。
消息队列(queue)
- Queue是用来存储消息的容器,RabbitMQ提供了FIFO(先进先出)的机制,可以缓存消息也可以将消息持久化、临时或者自动删除。
- 设置为持久化的队列,queue中的消息会在server本地硬盘存储一份,防止系统奔溃后数据丢失。
- 设置为临时队列,queue中的数据在系统重启之后就会丢失。
- 设置为自动删除的队列,当不存在用户(生产者和消费者)连接到server,队列中的数据会被自动删除。(消费者消费完消息后消息就不存在了和设置了什么状态无关)
Message(消息体)
- Message:由Header和Body组成,Header是由生产者添加的各种属性的集合,包括Message是否被持久化、由哪个Message
Queue接受、优先级是多少等。而Body是真正需要传输的数据。
十、使用场景
业务异步处理
场景说明:用户注册后,需要发注册邮件和注册短信。传统的做法有两种串行的方式和并行的方式。
1.1. 串行: 1.2. 并行:
1.3. 补充MQ优化:
应用解耦/通知
场景:用户下单后,订单系统需要通知库存系统,传统的做法就是订单系统调用库存系统的接口。但是这样做的话如果库存系统执行失败就会导致订单创建失败,或并发过大的情况下会导致系统雪崩的情况。
MQ优化
订单系统:用户下单后,订单系统完成持久化处理,将消息写入消息队列,返回用户订单下单成功。
库存系统:订阅下单的消息,获取下单消息,进行库存操作。 如果库存系统出现故障,可采用死信机制,重试执行并做人工通知预警。
流量削峰/抢购秒杀
场景:秒杀活动,一般会因为流量过大,导致应用挂掉,为了解决这个问题,一般在应用前端加入消息队列。
作用:
1、可以控制活动人数,超过此一定阀值的订单直接丢弃。
2、可以缓解短时间的高流量压垮应用(应用程序按自己的最大处理能力获取订单) 。
1、用户的请求,服务器收到之后,首先写入消息队列,加入消息队列长度超过最大值,则直接抛弃用户请求或跳转到错误页面。
2、秒杀业务根据消息队列中的请求信息,再做后续处理。
延迟处理
场景:用户下单后因某种原因放弃了付款,如果放任不管的话,会造成商品无法回仓,严重的话会导致商品无法卖出。我们通常的业务处理都是45分钟后自动将该订单取消,并对商品进行回仓操作。
通常的技术解决方案有:
- 长轮询(服务器压力过大,不可取)。
- 定时轮询(会造成,订单更新不及时,慎用)。
- MQ延迟处理(推荐)。
1、利用死信机制(TTL),将未付款的订单加入到死信队列中,并设置消息的超时时间为45分钟。
2、消息超时后,MQ会自动通知对应消费,进行订单更新以及回仓操作。
3、在进行订单更新时,先判断订单状态是否为待付款,如果不是,不做任何操作。
死信机制(DLX)
1.思考:引入消息队列可以给我们带来很大的好处,但同时也暴露出一个弊端,就是消息的可靠性,以及消息队列产品的性能及稳定。
2.问题:消费出现问题时,队列中的第一条消息一直无法消费,新消息在后面排队,会导致消息堆积。通过死信机制可以很好的解决此类问题的产生。
3.简介:死信机制中包含:死信队列(Q)和死信交换机(EX),其实死信队列、交换机与普通队列、交换机没有什么不同,只是被赋予了特殊的意义,处理特殊的消息而已。
触发条件:
1、消息被拒绝,并且requeue = false。
2、消息TTL过期(x-message-ttl)。
3、队列达到最大长度(x-max-length)。
死信流程:
生产者 --> 消息 --> 交换机 --> 队列 --> 变成死信 --> DLX交换机 -->死信队列 --> 死信消费者
项目集成(spring-rabbit)
加入依赖包
配置连接信息
Spring-RabbitMQ基础配置
队列配置
配置路由
消费监听