消息中间件剖析

什么是消息中间件

消息中间件是一套系统(或平台),用于应用程序之间进行通讯,系统经过消息传递完成交互。数据库

消息中间件的主要特色有如下几个。编程

1. 分布式:消息中间件都是分布式的,所以才能够提供异步、解耦等功能。缓存

2. 可靠性:基于消息的通讯是可靠的,消息不会丢失。大多数消息中间件都提供将消息持久化到磁盘的功能。服务器

3. 异步:经过消息中间件,可将远程同步调用拆解成为异步调用。对于不须要获取远程调用结果的应用场景来讲,性能提高明显。异步

4. 松耦合:消息直接由中间件存储和分发。消息生产者只需关注如何将消息发送给消息中介服务器;消费者只需关注如何从中介服务器订阅。生产者和消费者之间是彻底解耦的,不须要知道彼此的存在。分布式

5. 事件驱动:能够将复杂的应用系统重构成为事件驱动的系统。事件溯源(Event Sourcing),表示一个对象从建立到消亡,会通过的多种状态。若是把对象的状态变化都存储下来,不但能够根据状态变化记录获取对象的当前状态,也能够回溯对象的变化过程。消息中间件能很好地支持这样的系统设计方式,将触发对象状态变化的事件放入消息队列。性能

在带来好处的同时,引入消息中间件也有一些须要注意的地方。spa

1. 分布式带来的复杂性:消息中间件都是分布式的,引入分布式会大大增长系统复杂度,在不一样主机、不一样进程之间的调用和调试,会带来更多的不稳定性。分布式系统还会增长对外部系统的依赖。即便本身的系统没有问题,也可能会由于依赖系统出问题而致使系统不稳定。所以,Martin Fowler曾说:“分布式调用的第一原则就是不要分布式。”.net

2. 同步调用应该考虑其余方式:尽管消息中间件也可用于同步调用,但这并非它的长项,同步调用能够考虑使用HTTPNIO等其余方式。设计

3. 消息中介(Broker):可理解为消息中间件的服务器。消息中介用于存储消息,而且维护消息消费者和消息队列之间的订阅关系(也可由消费者本身维护)

消息在中介如何存储,是决定消息中间件功能和性能的最重要因素。目前来讲,最主要的两种存储消息的方式是kv存储和顺序存储。后文将详细介绍两种不一样存储引擎消息中间件的区别。

 

       

1. 消息生产者(Producer):与消息消费者一块儿组成消息中间件的客户端。生产者用于发送消息到消息中介。

客户端链接服务器通常能够选择TCPHTTP等协议。内网基于长链接的TCP协议效率更高,公网能够考虑HTTP协议穿透防火墙。

2. 消息消费者(Consumer):与消息生产者一块儿组成消息中间件的客户端。消费者用于从消息中介得到消息并交给业务系统使用。

消息的消费分红推送和拉取两种模式。推送是消息中介主动将消息发送给消息消费者,拉取则是消息消费者主动从消息中介获取消息。两种模式的使用场景不太同样,各有优缺点,下文也会详细介绍。

为了便于理解,在这里将消息中间件和关系型数据库作一个比较:

1. 消息中介至关于数据库的服务器;

2. 消息生产者至关于使用INSERT语句的SQL客户端;

3. 消息消费者至关于使用SELECT语句的SQL客户端。

固然这个比较不是很是恰当。例如根据实现方式不一样,消息的删除可能由消费者发起,也可能由消息中介主动发起。但能比较直观说明,消息中间件是由服务器和客户端组成,以及它们所承担的职责。

JMS

JMS的全称是Java Message Service,即Java消息服务,定义了Java平台消息中间件的技术规范。JMS只提供了应用程序对消息中间件操做的接口规范,并未提供实现,其实现由各个消息中间件厂商的驱动程序来提供,和Java的另外一个规范标准JDBC类似。遵循JMS规范的消息中间件都使用统一的API

JMS定义了消息的编程模型,如链接工厂、会话、消息目的地、消息生产者、消息消费者、消息体、消息优先级和消息类型等。本文并不会详细介绍JMS,有兴趣了解请查阅相关资料。但会重点介绍JMS中定义的消息类型,由于后面介绍的几种消息中间件如何支持消息类型是本文的关键之一。

消息类型分为点对点和发布/订阅两种。

1. 点对点(Point To Point):消息生产者将消息发送到消息队列(Queue)中,只有一个消费者可以消费此消息,消费完成以后消息即删除。

这里应该注意的是,任意一个消费者均可以消费这个消息,但消息绝对不会被两个消费者重复消费。

消息的消费者和生产者没有时间依赖,能够先发送消息,再启动消费者。

2展现了JMS的点对点消息类型。

2. 发布/订阅(Publish/Subscribe:消息生产者将消息发送到消息主题(Topic)中,全部订阅这个主题的消费者均可以消费此消息,当全部订阅者都消费完成以后才能删除消息。

消息的生产者和消费者之间有时间依赖,只有事先订阅这个主题的消费者才可消费。若是先发送消息,后订阅主题,那么订阅以前的消息将不能被这个订阅者消费。

订阅者又可分为持久化订阅和非持久化订阅。若是持久化的订阅者在订阅以后离线,收到的消息仍会在订阅者再次上线时收到,不会错过消息。而非持久化的订阅者一旦离线,离线时的消息将被错过。

3展现了JMS的发布/订阅消息类型。

最后,须要介绍消息传递语义(Message Delivery Semantics)。消息传递的担保有3种级别:最多一次(At Most Once),至少一次(At Least Once)和精确地仅发送一次(Exactly Once)。

【最多一次】

消息只发送或消费一次,不管消息中介是否收到消息,或者消息是否已消费成功,都不会再次发送。

这样作的问题是,消息可能会丢失。虽然客户端发送了消息,但消息中介还来不及存储就崩溃,那么这条消息就会丢失。

【至少一次】

若是消息中介没有明确告诉客户端消息已经收到,那么客户端会从新发送或消费这条消息。

这样作的问题是,消息可能会重复发送或消费。例如消息已经存到了消息中介,但还没来得及给客户端发送确认信息,消息中介就崩溃了。那么等消息中介从新启动以后,客户端会从新发送这条消息,形成重复。

【精确地仅发送一次】

既不会多也不会少发送消息。通常经过事务来实现,只有消息中介收到客户端确认处理成功的信息,才会提交事务,不然在通过必定时间限制以后消息会回滚。精确地仅发送一次消息,不会丢失也不会有重复的消息,但要达到这一点,对性能的损耗很是大。

JMS要求消息精确地仅发送一次。

应用场景

【业务解耦】

各个业务系统仅须要处理本身的业务逻辑,而且发送事件消息到消息中间件。下游业务系统直接订阅消息中间件的队列或主题获取事件。这样不但解耦了系统间的依赖,并且使调用异步化,提高了系统的性能。图4显示了如何经过消息中间件将订单系统解耦。

【削峰填谷】

若是上游系统的吞吐能力强于下游系统,那么在上游系统满负荷时将冲垮下游系统。使用消息中间件的定时定量推送或者定时定量拉取,可在上游峰值时堆积消息,在峰值过去时慢慢消费,加强系统的缓冲能力。图5显示了如何经过消息中间件缓冲业务洪峰,而且使用定时定量分流消费消息。

【广播通知】

系统一个状态的改变,须要通知多个相关系统,可经过消息订阅的方式推送给各个订阅者系统。好比数据库值的改变,须要通知全部的缓存系统更新,能够把数据库值改变发送消息给消息中间件,而后各缓存订阅相关主题,收到消息后更新本身的缓存。图6显示了数据中心如何经过广播通知已订阅的缓存系统更新数据。

【日志分析】

日志分析每每须要处理大量日志,不可能存储在一台物理机上。消息中间件可提供一个集群,用来存储海量消息,将其缓存到消息中间件。比较经常使用的日志分析系统是使用日志收集组件(如Flume)收集,存储到高吞吐量的消息中间件(如Kafka),供实时分析系统(如Storm)分析日志。图7描述了日志分析系统的基本组成部分。

消息中间件概览

1展现了目前比较流行的消息中间件的简单对比,但愿对读者的选型有所帮助。

转自http://m.blog.csdn.net/article/details?id=51868006

相关文章
相关标签/搜索