1. 消息中间件选型:
目前开源的消息中间件主要有:
ActiveMQ、RabbitMQ、Kafka、RocketMQ、ZeroMQ
对于消息中间件的选型,要从以下几个维度进行考量:
功能、性能、可靠性和可用性、运维管理、社区力度及生态发展。
1.1 功能维度:
如果一款消息中间件的功能达不到要求,就要进行二次开发,这样会增加项目的技术难度、复杂度以及延长项目周期。从功能维度上考量,选择消息中间件应最大程度的实现开箱即用。
功能维度又可以划分出多个子维度,主要有以下几个方面:
– 优先级队列: 优先级队列不同于先进先出队列,优先级高的消息具备优先被消费的特权,这样可以为下游提供不同消费级别的保证。
– 延时队列: Kafka不支持,RabbitMQ支持。
– 重试队列: Kafka和RabbitMQ都不支持重试队列,不过可以改造支持。
– 死信队列: Kafka不支持,RabbitMQ支持。
– 消费模式: 消费模式分为 “推模式”(push)和 “拉模式”(pull)。推模式是指由broker主动推送消息至消费端,实时性较好,但需要做流控机制以保证broker推送过来的消息不会压垮消费端。拉模式是指消费端主动向broker请求拉取(一般是定时 或 定量)消息,实时性较差,但可以根据自身的处理能力控制拉取的消息量。Kafka的消费模式支持拉模式,而RabbitMQ支持推模式+拉模式。
– 广播消费: 消息一般有两种传递模式:“点对点模式”(P2P)和“发布/订阅模式”(Pub-Sub)。点对点模式而言,消费被消费以后,队列中不会再存储消息,所以消费者不可能消费已经被消费过的消息。虽然队列支持多个消费者,但是一条消息只能被一个消费者消费一次;发布/订阅模式定义了如何向一个内容节点(Topic)发布和订阅消息,Topic可以认为是消息传递的中介,发送者将消息发布到某个Topic,消费者从Topic中订阅消息。主题使得消息的消费者和发布者保持相对独立。RabbitMQ是一种典型的点对点模式,而Kafka是一种典型的发布/订阅模式。
– 回溯消息: 指消息在消费完成后,还能消费之前被消费的消息。
– 消息堆积+持久化: 流量削峰是消息中间件的一个非常重要的功能,而这个功能其实得益于其消息堆积能力。消息堆积分“内存式堆积”和“磁盘式堆积”。RabbitMQ是典型的内存式堆积(在某些条件下也会触发内存中的消息换页到磁盘,但换页动作会影响吞吐);Kafka是一种典型的磁盘式堆积,所有的消息都存储到磁盘。一般来说,磁盘的容量会比内存的容量要大,其消息堆积能力也更强。
– 消息轨迹:
– 消息审计:
– 消息过滤:
– 多租户: 多租户是一种软件架构技术,主要用来实现多用户的环境下公用相同的系统或程序组件,并且仍可以确保各用户间数据的隔离性。RabbitMQ和Kafka都支持多租户。
– 多协议支持: 消息中间件支持的协议越多,其应用范围就越广,通用性越强,比如RabbitMQ能够支持MQTT协议就让其在物联网应用中获得一席之地,Kafka是基于本身的私有协议运转的。
– 跨语言支持: 跨语言的支持力度也可以从侧面反映出一个消息中间件的流行程度。
– 流量控制: 流量控制针对的是发送方和接收方速度不匹配的问题,提供一种速度匹配服务啦抑制发送速度,使接收方应用程序的读取速度与之相适应。通常的流控方法有 stop-and-wait停等模式、滑动窗口、令牌桶等。Kafka和RabbitMQ都支持流量控制。
– 消息顺序性:
– 安全机制:
– 消息幂等性:
–事务性消息:
1.2 性能维度:
– 吞吐量:
有时候消息中间件的性能指标比功能还重要,例如从功能维度上来说,RabbitMQ的优势要大于KafkaMQ,但是 Kafka的吞吐量要比Rabbit高出 1 至 2个数量级,一般RabbitMQ的单机QPS在 万级别之内,而Kafka的单机QPS可以维持在十万级别,甚至可以达到百万级别。 消息中间件的吞吐量始终会受到底层硬件的限制,包括网卡、内存、磁盘。以网卡为例,如果单机单网卡带宽为 1Gbps,如果要达到百万级的吞吐,就要求消息体的大小不能超过 134B(1GB/8/1000000),毕竟在带宽有限的情况下,只有消息足够“小”,消息数量才能足够“大”。
– 时延:
时延作为性能维度的一个重要指标,却往往在消息中间件领域被忽视,因为一般用消息中间件的场景对时效性的要求并不是很高,如果要求时效性完全可以采用RPC的方式实现。 消息中间件具备消息堆积的能力,消息堆积越大也就意味着端到端的时延就越长,与此同时延时队列也是某些消息中间件的一大特色。当然,如果使用的消息中间件在时延性能方面比较优秀,那么对于整体系统的性能将会是一个不小的提升。(PS:消息队列的作用是提供 消息缓存的能力,对于消息时延敏感的场景需要使用RPC。)
1.3 可靠性和可用性:
消息中间件的“可靠性”是指 对消息不丢失的保障程度;
消息中间件的“可用性”是指 无故障运行的时间百分比,通常用几个9来衡量。
从狭义的角度来说,分布式系统架构是一致性协议理论的应用实现,对消息可靠性和可用性而言也可以追溯到消息中间件背后的 一致性协议。
Kafka采用的是类似PacificA 的一致性协议,通过ISR 来保证多副本之间的同步,并且支持强一致性语义(通过acks实现)。
对应的RabbitMQ是通过镜像唤醒队列实现多副本及强一致性语义的。多副本可以保证在master节点宕机异常之后可以提升slave作为新的master而继续提供服务来保障可用性。
就目前而言,在金融支付领域使用RabbitMQ居多,而在日志处理、大数据等方面Kafka使用居多。 随着RabbitMQ性能的不断提升和Kafka可靠性的进一步增强,相信彼此都能在以前不擅长的领域分得一杯羹。
1.4 运维管理:
无论扩容、降级、版本升级、集群节点部署,还是故障处理,都离不开管理工具的应用,一个配套完备的管理工具集可以在遇到变更时做到事半功倍。Kafka和RabbitMQ都有多个产品可以提供自动化运维的功能。
1.5 社区力度及生态发展:
选择一款“流行”的消息中间件,其更新力度大,不仅可以迅速弥补之前的不足,而且也能顺应技术的快速发展来变更一些新的功能。而如果选择了一款“生僻”的消息中间件,可能在某些方面得心应手,但是版本更新缓慢,在遇到棘手问题时也难以得到社区的支持而越陷越深。
参考内容:
《深入理解Kafka核心设计与实践原理》第11章节