架构对比
RabbitMQ是一个通用的消息代理,通过包括点对点、请求/响应及发布订阅在内的多种消息通信模式。其采用的是一种智能代理/傻瓜消费的模式,侧重消息的持续投递与处理,并通过代理本身来维护消费者自身状态。RabbitMQ是一个设计成熟的消息代理中间件,支持包括Java, node.js, .NET, Ruby, PHP等在内的多种客户端,并且提供有多种插件来扩展自身功能。
RabbitMQ支持异步或者同步消息通信,生产者将消息发送到交换器中,消费者则从消息队列中获取消息。交换器将生产者从消息队列中解耦,避免了实际运用中消息路由的硬编码问题。RabbitMQ同时支持分布式部署,多个服务节点可以在完全不依赖外部其他服务(一些集群服务插件,比如:AWS APIs,DNS, Consul等等除外)的前提下组成一个服务集群。
Kakfa是一个高吞吐量的发布订阅消息系统和流处理平台,类似于服务器集群中的日志系统,Kafka以主题的形式为消息流提供了持久消息存储。
Kafka中的每一个消息都包含一个键、值以及时间戳,与RabbitMQ相反,Kafka采用的是一种傻瓜代理/智能消费的模式,Kakfa只记录未读消息,相应的Kafka采取的是为所有的消息保留一定的时间窗口,同时,消费者负责各自记录自身读取消息的实际位置(.log)。因此,通过适合的客户端代码,Kafka可以以非常小的代价支持大量的消费者和数据。如图所示,Kafka本身需要借助外部服务(比如ZooKeeper)来实现相应功能,在这点上,较之RabbitMQ,Kafka就略显难懂和不易用。
需求与场景
Kafka本身包含消息代理,这也是其最为显出和最受欢迎的部分,因此也常用于流式处理。除此之外,Kafka最近也引入了Kafka Streams,作为与Spark、Flink、Beam、Google Cloud Data Flow和Spring Cloud Data Flow类似的流平台备选方案。Kafka的主要应用场景包含:网站行为跟踪、度量,日志聚合、流式处理、事件溯源及提交日志等等,其中,消息路由是应用场景之一,其中,以下消息路由场景最适宜Kafka:
-
从A到B的流不需要复杂的路由,最大吞吐量(100k/sec+),至少包含一次按分区顺序路由。
-
当应用需要访问流历史,至少包含一次按分区顺序路由。与其他传统的消息中间件(消息一旦路由,即会被从消息队列中删除)不同,Kafka提供持久消息存储,客户端根据需要进行事件回溯。
-
流式处理
-
事件溯源
RabbitMQ提供的是通用的消息路由解决方案,通常用于服务器的快速响应。还可以用于路由消息给多个消费者或者实现高负载(20k+/s)下的负载均衡。RabbitMQ最适用于以下场景:
-
应用包含多种协议:AMQP 0-9-1, STOMP, MQTT, AMQP 1.0.
-
应用需要确保单个消息级别粒度的一致性控制/路由保证(Kafka已新增事务支持)
-
应用需要多种消息路由方式:点对点、请求/响应、发布订阅
-
包含多个服务与应用的路由交互,且路由逻辑复杂。
RabbitMQ也可以适用于Kafka的一些业务场景,比如,借助Apache Cassandra,RabbitMQ也可以实现消息回溯功能,借助LevelDB,RabbitMQ可以提供无限消息队列功能,但所有的这些都非RabbitMQ自身功能。
开发者经验
RabbitMQ插件众多,社区成熟,文档完善,官方支持多种客户端:Java, Spring, .NET, PHP, Python, Ruby, JavaScript, Go, Elixir, Objective-C, Swift等等。
在这方面,Kafka则仍有很大的进步空间,目前Kafka官方仅支持Java客户端, 但目前有很多开源社区、生态提供其他客户端或者SDK支持。
安全性与管理
这两点上都是RabbitMQ的强项,这主要得益于其强大的插件架构。比如,RabbitMQ管理插件提供了HTTP API,一个基于浏览器的UI用以管理和监控,同时还包含用以操作的客户端工具。RabbitMQ还提供了用以监控、审计和问题排查的API和工具。除了支持TLS之外,通过内置数据存储、LDAP或其他https认证的提供方,RabbitMQ还支持RBAC,此外还支持使用x509而非简单的用户名和密码认证。一些其他的身份验证方法也可以直接通过插件的形式进行开发实现。
Kafka在这方面来说就略显不足,在安全性方面,Kafka 0.9提供了基于访问控制和kerberos/plain/scram认证的TLS,JAAS角色,其通过客户端来管理安全策略。
性能
Kafka性能卓越,最高可达100k/s,这也是促使很多人选择kafka的重要原因所在。当然了,每秒处理消息的速率是很难表述和量化的,因为在很大程度上,这个指标都依赖于实际环境和硬件设施。
在不考虑可靠性的前提下,通过单个Rabbit队列达到20K/s的处理效率也并非难事,但RabbitMQ内部消息队列是基于Erlang实现的轻量级线程支持,由本地操作系统上的线程池协同调度,因而,RabbitMQ的性能瓶颈在于CPU的时钟周期的获取。
从本质上来讲,如何尽可能的提高每秒消息的处理数量归根结底也即是如何在单个环境中尽可能的提高并发度,比如通过多个消息队列间的智能路由(这样,多个消息队列就可以并发执行)。例如,通过大约30个节点即可实现每秒100万处理效率,但实际运用中3-7个服务节点组成的服务集群即可满足我们日常使用的绝大部分场景。