一、消息传输模型
从消息传输模型上,大致可以抽象为以下几种:
(1)点对点模型(Point-to-point)
基础模型中,只有一个发送者、一个接收者和一个分布式队列。
在P2P模型中,有几个关键术语:消息队列(Queue)、发送者(Sender)、接收者(Receiver)。每个消息都被发送到一个特定的队列,接收者从队列中获取消息。队列保留着消息,直到它们被消费或超时。
- 每个消息只有一个消费者(Consumer)(即一旦被消费,消息就不再在消息队列中)
- 发送者和接收者之间在时间上没有依赖性,也就是说当发送者发送了消息之后,不管接收者有没有正在运行,它不会影响到消息被发送到队列。
- 接收者在成功接收消息之后需向队列应答成功。
如果你希望发送的每个消息都应该被成功处理的话,那么你需要P2P模型。
(2)生产者消费者模型(Producer–consumer)
在该模型,三个角色一般称为生产者(Producer)、分布式队列(Queue)、消费者(Consumer)。如果发送者和接收者都可以有多个部署实例,甚至不同的类型;但是共用同一个队列,这就变成了标准的生产者消费者模型。
(3)发布订阅模型(Pub/Sub)
在该模型,三个角色一般称为发布者(Publisher),分布式队列(Queue),订阅者(Subscriber)。如果只有一类发送者,发送者将产生的消息实体按照不同的主题(Topic)分发到不同的逻辑队列。每种主题队列对应于一类接收者。这就变成了典型的发布订阅模型。
- 每个消息可以有多个消费者。
- 发布者和订阅者之间有时间上的依赖性。针对某个主题(Topic)的订阅者,它必须创建一个订阅之后,才能消费发布者的消息,而且,为了消费消息,订阅者必须保持运行的状态。
二、开源的分布式消息队列类型
看下业界,开源的分布式消息队列有很多种,侧重的维度也略有不同,包括支持的消息模型也有一些差异,如果按是否有独立进程来看,可以分为两个大类:
(一)Broker
Broker类的分布式消息队列,是指有独立部署进行的分布式服务,即发送者把消息发布到Broker进程,再由Broker进程推(或者是拉)给订阅者。
RabbitMq
RabbitMQ是使用Erlang编写的一个开源的消息队列,本身支持很多的协议:AMQP,XMPP, SMTP, STOMP,也正因如此,它非常重量级,更适合于企业级的开发。同时实现了Broker构架,这意味着消息在发送给客户端时先在中心队列排队。对路由,负载均衡或者数据持久化都有很好的支持。
RocketMq
RocketMq是由阿里研发团队开发的分布式队列,侧重在消息的顺序投递、高吞吐量、可靠性,在阿里内部大量使用,多次在云栖社区中被提及是“淘宝双11”的保障。目前已捐赠给Apache软件基金会。
Nats
Ruby-Nats作者开发,Derek Collison自称做了20多年的MQ,并经历过TIBOC、Rendezvous、EMC公司. 目前由Apcera公司维护,提供源码、二进制文件以及Docker镜像,用户有爱立信、HTC、百度、西门子、Vmware.Nats用Golang编写,Nats的设计思念中消息的成功投递不做保证,需要发送者自己维护,因此Nats在应用场景上还是比较有局限性。
Nats-streaming
目前由Apcera公司维护,也采用Golang编写,在保证吞吐量和时延的基础上,解决了Nats消息投递一致性的问题。之前和Apcera的Community Manager有过接触,Apcera目前只有5位工程师在进行开发维护,所以Nats-streaming目前支持的客户端API还比较少,只有Go、Java、Nodejs、C#,CAPI支持可能要到2017年中。
Kafka
Kafka是Apache下的一个子项目,是一个高性能跨语言分布式发布/订阅消息队列系统,而Jafka是在Kafka之上孵化而来的,即Kafka的一个升级版。具有以下特性:快速持久化,可以在O(1)的系统开销下进行消息持久化;高吞吐,在一台普通的服务器上既可以达到10W/s的吞吐速率;完全的分布式系统,Broker、Producer、Consumer都原生自动支持分布式,自动实现负载均衡;支持Hadoop数据并行加载,对于像Hadoop的一样的日志数据和离线分析系统,但又要求实时处理的限制,这是一个可行的解决方案。Kafka通过Hadoop的并行加载机制统一了在线和离线的消息处理。Apache Kafka相对于ActiveMQ是一个非常轻量级的消息系统,除了性能非常好之外,还是一个工作良好的分布式系统。
ActiveMq
ActiveMQ是Apache下的一个子项目。 类似于ZeroMQ,它能够以代理人和点对点的技术实现队列。同时类似于RabbitMQ,它少量代码就可以高效地实现高级应用场景。
(二)Brokerless
Brokerless类的消息队列,主要采用api的方式,编译到应用程序中,在应用程序间进行点对点的通信。
ZeroMq
ZeroMQ号称最快的消息队列系统,尤其针对大吞吐量的需求场景。ZeroMQ能够实现RabbitMQ不擅长的高级/复杂的队列,但是开发人员需要自己组合多种技术框架,技术上的复杂度是对这MQ能够应用成功的挑战。ZeroMQ具有一个独特的非中间件的模式,你不需要安装和运行一个消息服务器或中间件,因为你的应用程序将扮演这个服务器角色。你只需要简单的引用ZeroMQ程序库,可以使用NuGet安装,然后你就可以愉快的在应用程序之间发送消息了。但是ZeroMQ仅提供非持久性的队列,也就是说如果宕机,数据将会丢失。其中,Twitter的Storm 0.9.0以前的版本中默认使用ZeroMQ作为数据流的传输(Storm从0.9版本开始同时支持ZeroMQ和Netty作为传输模块)。
NanoMq
在技术选型时,我们一般从三个维度上去考量,吞吐量、时延、可靠性,不同的业务场景对两个维度的技术指标会有比较大的差异。 比如阿里的rocketmq,因为面临秒级的高并发场景,因此会十分看中吞吐量和消息的可靠性(不丢、顺序投递),而时延基本在100ms的级别,再比如kafka,最高的设计初衷也是做为分布式日志系统,因为看中的也是高吞吐量和可靠性。但对于游戏业务,实时音视频业务,不太会面临瞬间的访问高峰,而对低时延、时延稳定性会更加看中,一般认为消息投递应该在1-4ms以内。
三、思考
对比一下Android的消息模型,Handler属于生产者消费者模型(Producer–consumer)。Eventbus和RxJava属于发布订阅模型(Pub/Sub)。
其实对比一下你会发现,这些思想都是想通的,只是处理的业务场景不一样而已。相对来说Android的框架还算是简单的,服务端的框架(如:kafka)就复杂多了。当你做过服务端,再去在学习Android,你会发现基本都是服务端的那些框架原理在移动端的实现。反正万变不离其宗。当你了解服务端的架构,再去结合移动端实际情况,改造一下架构,你会收获更多。
本文参考文章:
网友评论