rabbitMQ.md
一、消息中间件概述
- 对于一些无需即时返回切耗时的操作提取出来进行异步处理,应用程序建通信方式,大大节省服务器请求响应时间提高系统吞吐量。
1. 应用场景
- 异步处理:如上
- 应用解耦合:生产和消费通过mq交互
- 削峰填谷:
2. AMQP和JMS
3. rabbitMQ erlang语言开发基于AMPQ协议
3-1. 模式
- 简单模式
- work模式
- Publish/Subscribe发布订阅模式
- Routing路由模式
- Topics主题模式
- RPC远程调用模式(不太算MQ)
二、安装配置rabbitmq
- # 安装socat
- yum -y install gcc socat
- # 安装erlang
- rpm -ivh erlang-22.0.7-1.el7.x86_64.rpm
- # 安装rabbitmq
- rpm -ivh rabbitmq-server-3.7.17-1.el7.noarch.rpm
- # 启动管理页面配置
- rabbitmq-plugins enable rabbitmq_management
- ## 配置远程guest登录
- cd /usr/share/doc/rabbitmq-server-3.7.17
- cp rabbitmq.config.example /etc/rabbitmq/rabbitmq.config
- ## 配置文件的双百分号是注释;逗号是换行配置;下处配置打开去掉上百分号和逗号
- {loopback_users,{}}
- # 启动
- ## centos6
- /sbin/service rabbitmq-server restart
- ## centos7
- systemctl restart rabbitmq-server
- # web地址
- localhost:15672
1. 用户角色
超管administrator,监控着monitoring,策略制定这policymaker,普管management,其他
2. 虚拟主机 virtual hosts:类似mysql的数据库db,数据不互通
三、rabbitmq入门
依赖amqp-clent
1. 消息生产者
1-1. 架构
1-2. 代码
1-3. debug
2. 消息消费者
四、AMQP
1. 相关概念
2. rabbitmq运转流程
3. 生产者流转过程
4. 消费者流转过程
五、rabbitMQ工作模式
1. work queue 工作队列模式1生产单队列多消费(默认exchange绑定到默认队列上)
2. 发布订阅模式:1生成多队列多消费增加了exchage交换机协调多个队列
交换机类型
- fanout模式绑定的队列们收到的消息同样条数一模一样
3. 路由模式
4. Topics 通配符模式
topic_exchange需要绑定队列,否则消息会丢失
顺序:生产连接-频道-交换机-队列-交换机-频道-消费连接
六、springboot整合rabbitMQ
1. 生产者
- 依赖
spring-boot-starter-web 使用springmvc进行测试
spring-boot-starter-amqp mq依赖
spring-boot-starter-test 单元测试 - 配置
1-1. 配置文件
- #端口
- server:
- port: 8888
- spring:
- rabbitmq:
- host: localhost
- username: guest
- password: 123456
- virtual-host: /itcast
- port: 5672
1-2. 配置类
1-3. 测试接口
2. 消费者
七、RabbitMQ 高级
1. 过期时间TTL
1-1. 队列级设置过期时间
配置文件
导入配置:启动类加如下注解
- "classpath:/spring/spring-rabbitmq-xml")
单元测试
1-2. 消息级别过期时间(针对每一个消息)
expiration字段单位是微秒,而且是字符串型数字才有效。queue和message两个级别以值小的生效。
2. 死信队列:不是一个而是一类
2-1. 死信队列配置:过期时间,队列里消息长度等处理
3. 配置文件源码结合消息流程解读
4. 延迟队列
延迟时间+死信队列结合实现
4-1. 使用场景
5. 消息确认机制
确认并且保证消息被送达,提供了两种方式:发布确认和事务(两者不可同时使用)。在channel为事务时不可引入确认模式;同样channel为确认模式时,不可使用事务。
两种确保消息送达:
- channel发布确认
- channel事务
发布确认两种处理:
- 消息发送成功确认
- 消息发送失败回调
5-1. 确认机制-发布确认配置
confirm-callback, return-callback 区别
测试发送失败
- public void testFailQueueTest() throws InterruptedException{
- //exchange 正确,queue错误,confirm被回调,ack=ture,returen被回调,replyText:NO_ROUTE
- //exchange错误 replyText:NOT_FOUND no exchange
- rabbitTemplate.convertAndSend("test_fail_exchange","","测试消息发送失败的确认应答");
- }
5-2. 确认机制-事务支持
当与发布确认机制同时使用时报
- cannot switch from tx to confirm mode
- #解决注释掉以下两句配置
- publisher-confirms="true"
- publisher-returens="true"
回滚注解
6. 消息追踪
6-1. 消息追踪分析
Payload就是消息内容
八、RabbitMQ 集群
因为Rabbtimq本身基于Erlang编写,该语言天然具备分布式特性(通过同步Erlang集群各节点的magic cookie来实现),因此rmq不需要想amq和kafka需要zk做集群实现HA和元数据保存。
1. 集群搭建
- #停止命令
- rabbitmqctl -n rabbit-1 stop_app
- #两节点集群1为主
- #1.
- #启动1;1的web端口是15672
- RABBITMQ_NODE_PORT=5672 RABBITMQ_NODENAME=rabbit-1 rabbitmq-server start &
- #启动2:2的web端口是15673
- RABBITMQ_NODE_PORT=5673 RABBITMQ_SERVER_START_ARGS="-rabbitmq_management listener [{port,15673}]" RABBITMQ_NODENAME=rabbit-2 rabbitmq-server start &
- #2操作主节点
- #停止1
- rabbitmqctl -n rabbit-1 stop_app
- #清楚节点历史数据,否则无法将节点加入集群
- rabbitmqctl -n rabbit-1 reset
- #启动应用
- rabbitmqctl -n rabbit-1 start_app
- #3操作从节点
- rabbitmqctl -n rabbit-2 stop_app
- rabbitmqctl -n rabbit-2 reset
- rabbitmqctl -n rabbit-2 join_cluster rabbit-1@'Server-node'#服务器主机名
- rabbitmqctl -n rabbit-1 start_app
- #4验证集群
- rabbitmqctl cluste status -n rabbit-1
2. 集群监控
2-1. 界面监控
自带web界面弊端
- 没有告警
- 无法接入到其他公司的监控系统统一管理(所以一般在小企业小集群中用)
2-2. 日志监控
tracing 消息追踪
2-3. 定制自己的监控系统
开发监控程序:依赖httpclient及jackson的jar
httpclient,jackon-databind,jackson-annotations,jackon-core
demo可以百度MonitorRabbitMQ
2-4. Zabbix监控RabbitMQ
强大的分布式监视及网络监视企业级开源软件搭建配置要求较高由运维负责
九、rabbitMQ高可用集群(扩展)
1. 集群架构模式
1-1. 主备模式:用于并发少的场景
1-2. 远程模式:异地集群同步场景
1-3. 镜像队列模式:HAProxy+keepalive;数据不丢失,高并发
1-4. 多活模式:异地数据复制比远程模式好
2. 镜像队列模式集群搭建
2-1. 节点规划
- # 复制主节点的erlang.cookie文件到其他所有从节点
- ## 停止mq的运行
- ## 拷贝/var/lib/rabbitmq/.erlang.cookie文件到其他节点
- ## 修改权限
- chmod 400 /var/lib/rabbitmq/.erlang.cookie
- # 停掉所有mq节点然后使用集群方式启动
- ## 主节点
- systemctl stop rabbitmq-server
- systemctl start rabbitmq-server
- ## 从节点如截图
指定镜像队列策略,消息同步验证
- #修改集群名称
- rabbitmqctl set_cluster_name rabbitmq_cd_itcast
- #移除其他节点(在非server2节点上执行移除server2节点)
- rabbitmqctl forget_cluster_node rabbit@server2
- #查看信息
- rabbitmqctl cluster_status
2-2. HAProxy实现负载均衡
2-2-1. 安装
2-2-2. 配置
- #cfg配置文件
- #logging options
- global
- log 127.0.0.1 lacal0 info
- maxconn 5120
- #ha的安装地址
- chroot /usr/local/haproxy
- uid 99
- gid 99
- daemon
- quiet
- nbproc 20
- pidfile /var/run/haproxy.pid
- defaults
- log global
- #使用四层代理模式 “mode http”为7层代理模式
- mode tcp
- #if you set mode to tcp.then you mast change tcplog into httplog
- option tcplog
- option dontlognull
- retries 3
- option redispatch
- maxconn 2000
- contimeout 5s
- ## 客户端空闲超时时间为30s,则HA发起重连机制
- clitimemout 30s
- ## 服务端连接超时时间为15s,则HA发起重连机制
- srvtimeout 15s
- #front-end IP for consumers and producters
- listen rabbitmq_cluster
- bind 192.168.13.104:5672
- #配置tcp模式
- mode tcp
- #balance url_param userid
- #简单的轮询
- balance roundrobin
- #rabbitmq集群节点配置 inter每隔5s集群健康检查2次正确证明服务可用,2次失败证明服务不可用并且配置主备机制
- server server1 192.168.13.101:5672 check inter 5000 rase 2 fail 2
- server server2 192.168.13.102:5672 check inter 5000 rase 2 fail 2
- server server3 192.168.13.103:5672 check inter 5000 rase 2 fail 2
- #配置haproxy web监控,查看统计信息
- listen stats
- bind 192.168.13.104:8100 #注意此处的ip地址我们配置了两台机器
- mode http
- option httplog
- stats enable
- #设者haproxy监控地址为http://192.168.13.104:8100/rabbitmq-stats
- stats uri /rabbitmq-stats
- stats refresh 5s
105 haproxy节点的配置跟上述104一致,ip修改成对应ip地址即可
haproxy监控web效果
yml里rabbit的配置地址改为haproxy的任一台节点ip地址即可。虽说生产两条一条server1接收一条server2接收,单两个rabbitmq节点会做消息同步
2-3. Keepalive实现HAProxy的HA高可用集群
原理VRRP协议:把多台路由设备虚拟成一台对外。
2-3-1. 安装
2-3-2. 配置
配置文件需要的脚本及状态查询
要测试高可用的虚拟ip的ip漂移功能;对应application.yml的rabbitmq配置ip配置成虚拟ip地址=》对应使用那么多组件加上rabbit还要做节点消息同步,肯定性能有所下降。
十、rabbitMq 应用与面试
1. 消息堆积
堆积的影响-产生堆积的情况-解决办法
1-1. 场景描述及测试代码
1-2. 性能提升的解决方案(27小时-》0.5小时)
2. 消息丢失
2-1. 保证消息不丢的三块处理
- 生产者确认
- 数据持久化
- 消费者确认
消费者丢失导致消息重发的两种场景:1.消费者主动关闭连接2.消费者挂掉。
3. 消息有序
3-1. 乱序场景1:多消费竞争消费
场景1解决方案
3-2. 乱序场景2:单消费者多线程处理竞争消费
场景2解决方案:使用java内存队列
4. 消费ACK未响应导致重发消息重复消费
如果消费消息的业务是幂等性操作(同一个操作执行多次,结果不变)就算重复消费也没问题,可以不做处理,如果不支持幂等性操作如:下单,减库存,扣款等,那么可以再消费者端每次消费成功后将该条消息id保存到数据库(幂等存储中),每次消费前查询该消息id,如果改消息id已经存在标识已经消费过,就不在消费否则就消费。
本方案采用redis存储消息id,因为redis单线程的性能也很好,提供很多原子性命令,如setnx命令存储消息id.