概述
近年来,随着互联网的快速发展,IT业务架构愈发复杂。由于消息型中间件对业务系统具有解耦、削峰、异步等功能,早已成为各大公司IT业务架构不可或缺的重要中间件之一。
在众多MQ消息队列组件里,RabbitMQ具有 erlang 语言本身的并发优势,性能时效性可达微秒级,单机吞吐量上万级,镜像集群模式可实现消息数据高可用,社区活跃度较高,管理界面使用十分方便,集群开箱即用。而百胜中国品牌系统众多,对消息队列的主要需求有:高性能、高可用、资源独立互不影响、集群快速交付、故障快速定位处理等。这些诉求,均是rabbitmq的优点。因此rabbitmq作为消息型队列在百胜中国的消费者IT应用系统中,已得到了大量使用。百胜S级业务系统使用的rabbitmq节点实例已经超过了1000个。
为了规范rabbitmq的部署和运维工作、指导开发人员正确地使用rabbitmq,IT运维团队结合rabbitmq的技术特点以及公司实际现状,制定了百胜中国rabbitmq标准使用规范。
本文档的面向对象为:公司所有与Rabbitmq相关的IT架构设计、开发、运维人员。
1,介绍
RabbitMQ 是Rabbit 技术公司基于 AMQP(高级消息队列协议) 标准,采用 Erlang 语言开发的消息型队列中间件,能够达到对业务的解耦、削峰、异步的功能。
2,RabbitMQ相关概念
消息
消息一般分为两部分,消息体和标签,标签主要用来描述这条消息,消息体是消息的内容,是一个json体或者数据等。
生产者发送消息,消费者消费消息,生产者与消费者彼此并无直接关系。
生产者(Producer)
向队列发送消息的一方。发布消息的最终目的在于将消息内容传递给其他系统/模块,使对方按照约定处理该消息。
消费者(Consumer)
接收消息的一方。消费者订阅RabbitMQ的队列,当消费者消费一条消息时,只是消费消息的消息体。在消息路由的过程中,会丢弃标签,存入到队列中的只有消息体。
队列(Queue)
队列是用于存储消息的,生产者将消息送到队列,消费者从队列中获取和消费消息。多个消费者可以同时订阅同一个队列,队列里的消息分配给不同的消费者。
代理(Broker)
消息中间件的服务节点。
消息中间件的作用
消息中间件凭借其独到的特性,在不同的应用场景下可以展现不同的作用。总的来说,消息中间件的作用可以概括如下。
解耦 :
在项目启动之初来预测将来会碰到什么需求是极其困难的。消息中间件在处理过程中间插入了一个隐含的、基于数据的接口层,两边的处理过程都要实现这一接口,这允许你独立地扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束即可。
冗余(存储):
有些情况下,处理数据的过程会失败。消息中间件可以把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险。在把一个消息从消息中间件中删除之前,需要你的处理系统明确地指出该消息已经被处理完成,从而确保你的数据被安全地保存直到你使用完毕。
扩展性:
因为消息中间件解耦了应用的处理过程,所以提高消息入队和处理的效率是很容易的,只要另外增加处理过程即可,不需要改变代码,也不需要调节参数。
削峰:
在访问量剧增的情况下,应用仍然需要继续发挥作用,但是这样的突发流量并不常见。如果以能处理这类峰值为标准而投入资源,无疑是巨大的浪费。使用消息中间件能够使关键组件支撑突发访问压力,不会因为突发的超负荷请求而完全崩溃。
可恢复性:
当系统一部分组件失效时,不会影响到整个系统。消息中间件降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入消息中间件中的消息仍然可以在系统恢复后进行处理。
顺序保证:
在大多数使用场景下,数据处理的顺序很重要,大部分消息中间件支持一定程度上的顺序性。
缓冲:
在任何重要的系统中,都会存在需要不同处理时间的元素。消息中间件通过一个缓冲层来帮助任务最高效率地执行,写入消息中间件的处理会尽可能快速。该缓冲层有助于控制和优化数据流经过系统的速度。
异步通信:
在很多时候应用不想也不需要立即处理消息。消息中间件提供了异步处理机制,允许应用把一些消息放入消息中间件中,但并不立即处理它,在之后需要的时候再慢慢处理。
3,典型应用场景
RabbitMQ作为一款热门的消息队列中间件,具备高效可靠的消息异步传递机制,主要用于不同系统间的数据交流和传递,在企业解决方案、金融支付、电信、电子商务、社交、即时通信、视频、物联网、车联网等众多领域都有广泛应用。
异步通信
将业务中属于非核心或不重要的流程部分,使用消息异步通知的方式发给目标系统,这样主业务流程无需同步等待其他系统的处理结果,从而达到系统快速响应的目的。
如网站的用户注册场景,在用户注册成功后,还需要发送注册邮件与注册短信,这两个流程使用RabbitMQ消息服务通知邮件发送系统与短信发送系统,从而提升注册流程的响应速度。
图1 串行发送注册邮件与短信流程
图2 借助消息队列异步发送注册邮件与短信流程
错峰流控与流量削峰
在电子商务系统或大型网站中,上下游系统处理能力存在差异,处理能力高的上游系统的突发流量可能会对处理能力低的某些下游系统造成冲击,需要提高系统的可用性的同时降低系统实现的复杂性。电商大促销等流量洪流突然来袭时,可以通过队列服务堆积缓存订单等信息,在下游系统有能力处理消息的时候再处理,避免下游订阅系统因突发流量崩溃。消息队列提供亿级消息堆积能力,3天的默认保留时长,消息消费系统可以错峰进行消息处理。
另外,在商品秒杀、抢购等流量短时间内暴增场景中,为了防止后端应用被压垮,可在前后端系统间使用RabbitMQ消息队列传递请求。
图3 消息队列应对秒杀大流量场景
系统解耦
以电商秒杀、抢购等流量短时间内暴增场景为例,传统做法是,用户下单后,订单系统发送查询请求到库存系统,等待库存系统返回请求结果给订单系统。如果库存系统发生故障,订单系统获取不到数据,订单失败。这种情况下,订单系统和库存系统两个子系统高耦合。
图4 系统高耦合
引入RabbitMQ消息队列,当用户下单后,将消息写入到RabbitMQ消息队列中,然后返回用户下单成功。
库存系统订阅下单的消息,消费下单消息,然后进行库操作。即使库存系统出现故障,也不影响用户下单。
图5 系统解耦
高可用
镜像队列是开源RabbitMQ 2.6.0版本新增的一个功能,允许集群将队列镜像到其他代理上,当集群某一代理宕机后,队列能自动切换到镜像中的其他代理,保证服务的可用性。
普通队列,由于队列以及队列内容仅存储在单代理上,当该代理故障后,对应的队列不可用。
RabbitMQ引入镜像队列机制,将队列镜像到集群中的其他代理上,每一个镜像队列包含一个主队列和多个从队列,并分布在集群的不同代理上。
4,Kafka与RabbitMQ的差异
Kafka采用拉取(Pull)方式消费消息,吞吐量相对更高,适用于海量数据收集与传递场景,例如日志采集和集中分析。RabbitMQ在吞吐量方面略有逊色,但支持更多的消息队列功能。
以下从性能、数据可靠性、服务可用性、功能等方面给出具体的对比分析,供用户选型参考。
性能
消息中间件的性能主要衡量吞吐量,Kafka的吞吐量比RabbitMQ要高出1~2个数量级,RabbitMQ的单机QPS在万级别,Kafka的单机QPS能够达到百万级别。
Kafka如果开启幂等、事务等功能,性能也会有所降低。
数据可靠性
Kafka与RabbitMQ都具备多副本机制,数据可靠性较高。
服务可用性
Kafka采用集群部署,分区与多副本的设计,使得单代理宕机对服务无影响,且支持消息容量的线性提升。
华为云分布式消息服务RabbitMQ版支持集群部署,集群代理数量有多种规格。
功能
Kafka与RabbitMQ都是比较主流的两款消息中间件,具备消息传递的基本功能,但在一些特殊的功能方面存在差异,以下给出Kafka与RabbitMQ两个开源社区版本的比较。
| 功能项 | Kafka(1.1.0/2.3.0版本) | RabbitMQ(3.7.17版本) |
|---|---|---|
| 优先级队列 | 不支持 | 支持。建议优先级大小设置在0-10之间。 |
| 延迟队列 | 不支持 | 支持 |
| 死信队列 | 不支持 | 支持 |
| 重试队列 | 不支持 | 不支持 |
| 消费模式 | 客户端主动拉取 | 支持客户端主动拉取以及服务端推送两种模式。 |
| 广播消费 | 支持 | 支持 |
| 消息回溯 | 支持。Kafka支持按照offset和timestamp两种维度进行消息回溯。 | 不支持。RabbitMQ中消息一旦被确认消费就会被标记删除。 |
| 消息堆积 | 支持。考虑吞吐因素,Kafka的堆积效率比RabbitMQ总体上要高。 | 支持 |
| 持久化 | 支持 | 支持 |
| 消息追踪 | 不支持 | 支持。RabbitMQ中可以采用Firehose或者rabbitmq_tracing插件实现,但开启rabbitmq_tracing插件会影响性能,建议只在定位问题过程中开启。 |
| 消息过滤 | 支持 | 不支持,但可以自行封装。 |
| 多租户 | 不支持 | 支持 |
| 多协议支持 | 只支持Kafka自定义协议。 | RabbitMQ基于AMQP协议实现,同时支持MQTT、STOMP等协议。 |
| 跨语言支持 | 采用Scala和Java编写,支持多种语言的客户端。 | 采用Erlang编写,支持多种语言的客户端。 |
| 流量控制 | 支持client和user级别,通过主动设置可将流控作用于生产者或消费者。 | RabbitMQ的流控基于Credit-Based算法,是内部被动触发的保护机制,作用于生产者层面。 |
| 消息顺序性 | 支持单分区(partition)级别的顺序性。 | 不支持。需要单线程发送、单线程消费并且不采用延迟队列、优先级队列等一些高级功能整体配合,才能实现消息有序。 |
| 安全机制 | 支持SSL、SASL身份认证和读写权限控制。 | 与Kafka相似 |
| 幂等性 | 支持单个生产者单分区单会话的幂等性。 | 不支持 |
| 事务性消息 | 支持 | 支持 |
分布式消息服务提供的Kafka与RabbitMQ,在兼容开源协议的基础上,对版本特性做了部分支持或者增强。
公司Rabbitmq架构
云上架构:
SLB ->rabbitmq
创建静态用户名密码
- 登录云消息队列 RabbitMQ 版控制台,然后在左侧导航栏选择实例列表。
- 在实例列表页面的顶部菜单栏选择地域,然后在实例列表中,单击目标实例名称。
- 在左侧导航栏,单击静态用户名密码。
- 在静态用户名密码页面,单击创建用户名密码。
- 在创建用户名密码面板,输入AccessKey ID和AccessKey Secret,然后单击确定。
说明
AccessKey ID和AccessKey Secret需要在阿里云RAM控制台获取,具体获取方式,请参见创建AccessKey。
静态用户名密码页面,显示创建的静态用户名与密码,密码处于隐藏状态。
- 在创建的静态用户名密码的密码列,单击显示密码,可查看用户名的密码。
云下架构:
VIP (2个 Keepalived) -> 2个 Haproxy -> 3个 Rabbitmq(Keepalived、Haproxy、Rabbitmq混部)
资源申请
需求方:
- 乾坤平台申请创建应用名称
- 申请3台机器(参考:资源申请标准)
- jira申请部署Rabbitmq(参考:Rabbitmq集群申请 )
资源申请标准:
三台机器构建Rabbitmq集群,采用混部模式(keepalive、haproxy、rabbitmq)
| 机器 | CPU | 内存 | 磁盘、挂载目录 | 中间件 | vip | 应用名称 |
|---|---|---|---|---|---|---|
| 机器1 | 4 | 8 | 200g、/opt | Keepalived(云下)Haproxy(云下)Rabbitmq(云上、云下) | xxx.xxx.xxx.xxx | 乾坤CD需要填写:同系统多套MQ的情况下,通过名称区别 |
| 机器2 | 4 | 8 | 200g、/opt | Keepalived(云下)Haproxy(云下)Rabbitmq(云上、云下) | ||
| 机器3 | 4 | 8 | 200g、/opt | Rabbitmq(云上、云下) |
申请应用、服务器:
乾坤平台申请应用:qk.hwwt2.com/
CD->我的申请->创建应用申请:
技术栈类型选择:rabbitmq
应用名称需要自行定义(同系统多套MQ的情况下,通过名称区别,监控告警中也会携带此名称):
监控
- Rabbitmq中间件可用性监控:http://172.25.99.208:3000/d/Wu4xkdEZk/techops-rabbitmq
UP/DOWN : 10个监控项保障MQ的可用性
Details : UP/DOWN 监控项对应的详细内容
当UP/DOWN的监控项绿色变红后,可通过Details信息找到具体节点和问题监控项,执行预案并通知相关人员
- 业务监控:
业务层面监控需要定制化,应用运维整理好监控需求后,发送邮件到技术运维(CN-RSC_IT_TechOPS@YumChina.com),技术运维根据需求交付表盘给应用运维。
规范
使用规范
- 所有队列、路由建议使用持久化
- 优先级队列级别设置建议为10(权重越大表示优先执行,是否使用高优先级队列由开发Leader、架构一起确认)
- 延迟队列延迟时间根据业务设定(默认未安装,涉及到延迟队列走jira申请安装)
- 程序支持重连MQ
- 所有接收器设置其ack为手动响应,且在listener使用后必须回写,防止队列阻塞
- 所有数据发送采用Json格式,且存储数据信息尽量小于100K。
- 交换机、队列、路由在创建后,属性不可更改,如有需要,需申请运维协助(建议使用新的队列,旧的队列数据处理完后可以删除)
- 交换机、队列的创建/删除只能提交运维,开发不允许自行创建。通过用户权限来进行隔离。
- 运维定期监控队列、交换机的使用情况,每个月出一份队列交换机的使用情况,如果6个月以上没人使用,需要被清理(清理前发邮件通知各相关方)
命名规范
exchange命名规范:(名字之间使用 . 作为分割)
exchange.[使用的平台名称].[业务类型]
举例说明:
exchange.kfc.preorder.menu.listener
queue命名规范:(名字之间使用 . 作为分割)
1.queue.[使用的平台名称].[ 业务名].[功能]
exchange.kfc.preorder.menu.listener
2.queue.[使用的平台名称].[业务名].[功能]
名词解释:
使用的平台名称:kfc.delivery、kfc.preorder
业务名: order、storeinfo
功能:具体的功能
举例说明:
消息队列(queue.sso.login~~.~~sms)
延时消息队列(queue.sso.login.delay.sms_expired)
topic队列(queue.sso.login.new_user)