1.概念
1.1消息和消息队列
消息(Message)是指在应用间传送的数据。消息可以非常简单,比如只包含文本字符串,也可以更复杂,可能包含嵌入对象。
消息队列(MessageQueue)是一种应用间的通信方式,消息发送后可以立即返回,由消息系统来确保消息的可靠传递。消息发布者只管把消息发布到MQ中而不用管谁来取,消息使用者只管从MQ中取消息而不管是谁发布的。这样发布者和使用者都不用知道对方的存在。
1.2看场景理解MQ
如果商品服务和订单服务是两个不同的微服务,在下单的过程中订单服务需要调用商品服务进行扣库存操作。按照传统的方式,下单过程要等到调用完毕之后才能返回下单成功,如果网络产生波动等原因使得商品服务扣库存延迟或者失败,会带来较差的用户体验,如果在高并发的场景下,这样的处理显然是不合适的,那怎么进行优化呢?这就需要消息队列登场了
消息队列提供一个异步通信机制,消息的发送者不必一直等待到消息被成功处理才返回,而是立即返回。消息中间件负责处理网络通信,如果网络连接不可用,消息被暂存于队列当中,当网络畅通的时候在将消息转发给相应的应用程序或者服务,当然前提是这些服务订阅了该队列。如果在商品服务和订单服务之间使用消息中间件,既可以提高并发量,又降低服务之间的耦合度
2.常见的几种消息中间件
常见的消息中间件有ActiveMQ、RabbitMQ、RocketMQ、Kafka等等各种,以及JMS、AMQP等各种协议
2.1几种协议
2.1.1JMS
JMS全称JavaMessageService,类似于JDBC,不同于JDBC,JMS是JavaEE的消息服务接口,JMS主要有两个版本:1.0、2.0,两者相比,后者主要是简化了收发消息的代码
考虑到消息中间件是一个非常常用的工具,所以JavaEE为此制定了专门的规范JMS
不过和JDBC一样,JMS作为规范,他只是一套接口,并不包含具体的实现,如果我们要使用JMS,那么一般还需要对应的实现,这就像使用JDBC需要对应的驱动一样
开源的支持JMS的消息中间件有Kafka、ActiveMQ等
JMS具有两种通信模式:
①Point-to-PointMessagingDomain(点对点)
在点对点通信模式中,应用程序由消息队列,发送方,接收方组成。每个消息都被发送到一个特定的队列,接收者从队列中获取消息,队列保留着消息,直到他们被消费或超时
每个消息只要一个消费者
发送者和接收者在时间上是没有时间的约束,也就是说发送者在发送完消息之后,不管接收者有没有接受消息,都不会影响发送方发送消息到消息队列中
发送方不管是否在发送消息,接收方都可以从消息队列中去到消息
接收方在接收完消息之后,需要向消息队列应答成功
②Publish/SubscribeMessagingDomain(发布/订阅模式)
在发布/订阅消息模型中,发布者发布一个消息,该消息通过topic传递给所有的客户端。该模式下,发布者与订阅者都是匿名的,即发布者与订阅者都不知道对方是谁。并且可以动态的发布与订阅Topic。Topic主要用于保存和传递消息,且会一直保存消息直到消息被传递给客户端。
一个消息可以传递个多个订阅者(即:一个消息可以有多个接受方)
发布者与订阅者具有时间约束,针对某个主题(Topic)的订阅者,它必须创建一个订阅者之后,才能消费发布者的消息,而且为了消费消息,订阅者必须保持运行的状态
为了缓和这样严格的时间相关性,JMS允许订阅者创建一个可持久化的订阅。这样,即使订阅者没有被激活(运行),它也能接收到发布者的消息
2.1.2AMQP
AMQP(AdvancedMessageQueuingProtocol,高级消息队列)是一个进程间传递异步消息的网络协议。
AMQP协议的一些具体的消息中间件产品:ActiveMQ、RabbitMQ
AMQP工作过程
发布者(Publisher)发布消息(Message),经由交换机(Exchange)。
交换机根据路由规则将收到的消息分发给与该交换机绑定的队列(Queue)。
最后AMQP代理会将消息投递给订阅了此队列的消费者,或者消费者按照需求自行获取。
2.1.3JMSVsAMQP
2.1.4MQTT
MQTT(MessageQueuingTelemetryTransport,消息队列遥测传输)是IBM开发的一个即时通讯协议,目前看来算是物联网开发中比较重要的协议之一了,该协议支持所有平台,几乎可以把所有联网物品和外部连接起来,被用来当做传感器和Actuator(比如通过Twitter让房屋联网)的通信协议,它的优点是格式简洁、占用带宽小、支持移动端通信、支持PUSH、适用于嵌入式系统。
2.1.5XMPP
XMPP(可扩展消息处理现场协议,ExtensibleMessagingandPresenceProtocol)是一个基于XML的协议,多用于即时消息(IM)以及在线现场探测,适用于服务器之间的准即时操作。核心是基于XML流传输,这个协议可能最终允许因特网用户向因特网上的其他任何人发送即时消息,即使其操作系统和浏览器不同。它的优点是通用公开、兼容性强、可扩展、安全性高,缺点是XML编码格式占用带宽大。
2.2几种MQ的区别
ActiveMQ
ActiveMQ是Apache出品,最流行的,能力强劲的开源消息总线。它是一个完全支持JMS规范的的消息中间件。丰富的API,多种集群架构模式让ActiveMQ在业界成为老牌的消息中间件,在中小型企业颇受欢迎.
ActiveMQ使用完全支持JMS1.1和J2EE1.4规范的JMSProvider实现,少量代码就可以高效地实现高级应用场景,并且支持可插拔的传输协议,如:in-VM,TCP,SSL,NIO,UDP,multicast,JGroupsandJXTAtransports。支持常用的多种语言客户端如C++、Java、.Net,、Python、Php、Ruby等。
现在的ActiveMQ分为两个版本:
ActiveMQClassic
ActiveMQArtemis
这里的ActiveMQClassic就是原来的ActiveMQ,而ActiveMQArtemis是在RedHat捐赠的HornetQ服务器代码的基础上开发的,两者代码完全不同,后者支持JMS2.0,使用基于Netty的异步IO,大大提升了性能,更为神奇的是,后者不仅支持JMS协议,还支持AMQP协议、STOMP以及MQTT,可以说后者的玩法相当丰富。
Kafka
Kafka是LinkedIn开源的分布式发布-订阅消息系统,目前归属于Apache顶级项目。Kafka主要特点是基于Pull的模式来处理消息消费,追求高吞吐量,一开始的目的就是用于日志收集和传输。0.8版本开始支持复制,不支持事务,对消息的重复、丢失、错误没有严格要求,适合产生大量数据的互联网服务的数据收集业务。
Kafka具有以下特性:
快速持久化:通过磁盘顺序读写与零拷贝机制,可以在O(1)的系统开销下进行消息持久化
高吞吐:在一台普通的服务器上既可以达到10W/s的吞吐速率
高堆积:支持topic下消费者较长时间离线,消息堆积量大
完全的分布式系统:Broker、Producer、Consumer都原生自动支持分布式,通过Zookeeper可以自动实现更加复杂的负载均衡
支持Hadoop数据并行加载
RocketMQ
RocketMQ是阿里开源的消息中间件,它是纯Java开发,具有高吞吐量、高可用性、适合大规模分布式系统应用的特点。RocketMQ思路起源于Kafka,但并不是Kafka的一个Copy,它对消息的可靠传输及事务性做了优化,目前在阿里集团被广泛应用于交易、充值、流计算、消息推送、日志流式处理、binglog分发等场景
RocketMQ将阿里内部多款MQ产品(Notify、Metaq)进行整合,只维护核心功能,去除了所有其他运行时依赖,保证核心功能最简化,在此基础上配合阿里上述其他开源产品实现不同场景下MQ的架构,目前主要用于订单交易系统。
RocketMQ具有以下特点:
保证严格的消息顺序
提供针对消息的过滤功能
提供丰富的消息拉取模式
高效的订阅者水平扩展能力
实时的消息订阅机制
亿级消息堆积能力
RabbitMQ
RabbitMQ是使用Erlang语言开发的开源消息队列系统,基于AMQP协议来实现。AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。AMQP协议更多用在企业系统内对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在其次。
工作过程:生产者发送消息-消息交换机-把消息路由给消息队列-消费者消费消息
ZeroMQ
ZeroMQ号称最快的消息队列系统,它专门为高吞吐量/低延迟的场景开发,在金融界的应用中经常使用,偏重于实时数据通信场景。ZeroMQ不是单独的服务,而是一个嵌入式库,它封装了网络通信、消息队列、线程调度等功能,向上层提供简洁的API,应用程序通过加载库文件,调用API函数来实现高性能网络通信。
ZeroMQ的特性:
无锁的队列模型:对于跨线程间的交互(用户端和session)之间的数据交换通道pipe,采用无锁的队列算法CAS,在pipe的两端注册有异步事件,在读或者写消息到pipe时,会自动触发读写事件
批量处理的算法:对于批量的消息,进行了适应性的优化,可以批量的接收和发送消息
多核下的线程绑定,无须CPU切换:区别于传统的多线程并发模式,信号量或者临界区,ZeroMQ充分利用多核的优势,每个核绑定运行一个工作者线程,避免多线程之间的CPU切换开销
几种MQ比较:
作者:_静水流深
链接: