消息中间件(一)MQ详解及四大MQ比较

1、消息中间件相关知识

一、概述

消息队列已经逐渐成为企业IT系统内部通讯的核心手段。它具备低耦合、可靠投递、广播、流量控制、最终一致性等一系列功能,成为异步RPC的主要手段之一。当今市面上有不少主流的消息中间件,如老牌的ActiveMQ、RabbitMQ,煊赫一时的Kafka,阿里巴巴自主开发RocketMQ等。java

 

二、消息中间件的组成

      2.1 Brokerredis

消息服务器,做为server提供消息核心服务算法

      2.2 Producer数据库

消息生产者,业务的发起方,负责生产消息传输给broker,apache

      2.3 Consumer浏览器

消息消费者,业务的处理方,负责从broker获取消息并进行业务逻辑处理安全

      2.4 Topic服务器

主题,发布订阅模式下的消息统一聚集地,不一样生产者向topic发送消息,由MQ服务器分发到不一样的订阅者,实现消息的       广播网络

      2.5 Queuesession

队列,PTP模式下,特定生产者向特定queue发送消息,消费者订阅特定的queue完成指定消息的接收

      2.6 Message

消息体,根据不一样通讯协议定义的固定格式进行编码的数据包,来封装业务数据,实现消息的传输

 

3 消息中间件模式分类

      3.1 点对点

PTP点对点:使用queue做为通讯载体 

说明: 
消息生产者生产消息发送到queue中,而后消息消费者从queue中取出而且消费消息。 
消息被消费之后,queue中再也不存储,因此消息消费者不可能消费到已经被消费的消息。 Queue支持存在多个消费者,可是对一个消息而言,只会有一个消费者能够消费。

3.2 发布/订阅

Pub/Sub发布订阅(广播):使用topic做为通讯载体 

说明: 
消息生产者(发布)将消息发布到topic中,同时有多个消息消费者(订阅)消费该消息。和点对点方式不一样,发布到topic的消息会被全部订阅者消费。

queue实现了负载均衡,将producer生产的消息发送到消息队列中,由多个消费者消费。但一个消息只能被一个消费者接受,当没有消费者可用时,这个消息会被保存直到有一个可用的消费者。 
topic实现了发布和订阅,当你发布一个消息,全部订阅这个topic的服务都能获得这个消息,因此从1到N个订阅者都能获得一个消息的拷贝。

 

4 消息中间件的优点

      4.1 系统解耦

交互系统之间没有直接的调用关系,只是经过消息传输,故系统侵入性不强,耦合度低。

      4.2 提升系统响应时间

例如原来的一套逻辑,完成支付可能涉及先修改订单状态、计算会员积分、通知物流配送几个逻辑才能完成;经过MQ架构设计,就可将紧急重要(须要马上响应)的业务放到该调用方法中,响应要求不高的使用消息队列,放到MQ队列中,供消费者处理。

      4.3 为大数据处理架构提供服务

经过消息做为整合,大数据的背景下,消息队列还与实时处理架构整合,为数据处理提供性能支持。

      4.4 Java消息服务——JMS

Java消息服务(Java Message Service,JMS)应用程序接口是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通讯。 
JMS中的P2P和Pub/Sub消息模式:点对点(point to point, queue)与发布订阅(publish/subscribe,topic)最初是由JMS定义的。这两种模式主要区别或解决的问题就是发送到队列的消息可否重复消费(多订阅)。

 

5 消息中间件应用场景

       5.1 异步通讯

有些业务不想也不须要当即处理消息。消息队列提供了异步处理机制,容许用户把一个消息放入队列,但并不当即处理它。想向队列中放入多少消息就放多少,而后在须要的时候再去处理它们。

      5.2 解耦

下降工程间的强依赖程度,针对异构系统进行适配。在项目启动之初来预测未来项目会碰到什么需求,是极其困难的。经过消息系统在处理过程当中间插入了一个隐含的、基于数据的接口层,两边的处理过程都要实现这一接口,当应用发生变化时,能够独立的扩展或修改两边的处理过程,只要确保它们遵照一样的接口约束。

      5.3 冗余

有些状况下,处理数据的过程会失败。除非数据被持久化,不然将形成丢失。消息队列把数据进行持久化直到它们已经被彻底处理,经过这一方式规避了数据丢失风险。许多消息队列所采用的”插入-获取-删除”范式中,在把一个消息从队列中删除以前,须要你的处理系统明确的指出该消息已经被处理完毕,从而确保你的数据被安全的保存直到你使用完毕。

      5.4 扩展性

由于消息队列解耦了你的处理过程,因此增大消息入队和处理的频率是很容易的,只要另外增长处理过程便可。不须要改变代码、不须要调节参数。便于分布式扩容。

      5.5 过载保护

在访问量剧增的状况下,应用仍然须要继续发挥做用,可是这样的突发流量没法提取预知;若是觉得了能处理这类瞬间峰值访问为标准来投入资源随时待命无疑是巨大的浪费。使用消息队列可以使关键组件顶住突发的访问压力,而不会由于突发的超负荷的请求而彻底崩溃。

      5.6 可恢复性

系统的一部分组件失效时,不会影响到整个系统。消息队列下降了进程间的耦合度,因此即便一个处理消息的进程挂掉,加入队列中的消息仍然能够在系统恢复后被处理。

      5.7 顺序保证

在大多使用场景下,数据处理的顺序都很重要。大部分消息队列原本就是排序的,而且能保证数据会按照特定的顺序来处理。

      5.8 缓冲

在任何重要的系统中,都会有须要不一样的处理时间的元素。消息队列经过一个缓冲层来帮助任务最高效率的执行,该缓冲有助于控制和优化数据流通过系统的速度。以调节系统响应时间。

      5.9 数据流处理

分布式系统产生的海量数据流,如:业务日志、监控数据、用户行为等,针对这些数据流进行实时或批量采集汇总,而后进行大数据分析是当前互联网的必备技术,经过消息队列完成此类数据收集是最好的选择。

 

6 消息中间件经常使用协议

      6.1 AMQP协议

AMQP即Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不一样产品,不一样开发语言等条件的限制。 
优势:可靠、通用

      6.2 MQTT协议

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通信协议,有可能成为物联网的重要组成部分。该协议支持全部平台,几乎能够把全部联网物品和外部链接起来,被用来当作传感器和致动器(好比经过Twitter让房屋联网)的通讯协议。 
优势:格式简洁、占用带宽小、移动端通讯、PUSH、嵌入式系统

      6.3 STOMP协议

STOMP(Streaming Text Orientated Message Protocol)是流文本定向消息协议,是一种为MOM(Message Oriented Middleware,面向消息的中间件)设计的简单文本协议。STOMP提供一个可互操做的链接格式,容许客户端与任意STOMP消息代理(Broker)进行交互。 
优势:命令模式(非topic\queue模式)

      6.4 XMPP协议

XMPP(可扩展消息处理现场协议,Extensible Messaging and Presence Protocol)是基于可扩展标记语言(XML)的协议,多用于即时消息(IM)以及在线现场探测。适用于服务器之间的准即时操做。核心是基于XML流传输,这个协议可能最终容许因特网用户向因特网上的其余任何人发送即时消息,即便其操做系统和浏览器不一样。 
优势:通用公开、兼容性强、可扩展、安全性高,但XML编码格式占用带宽大

      6.5 其余基于TCP/IP自定义的协议

有些特殊框架(如:redis、kafka、zeroMq等)根据自身须要未严格遵循MQ规范,而是基于TCP\IP自行封装了一套协议,经过网络socket接口进行传输,实现了MQ的功能。

 

7 常见消息中间件MQ介绍

      7.1 RocketMQ

阿里系下开源的一款分布式、队列模型的消息中间件,原名Metaq,3.0版本名称改成RocketMQ,是阿里参照kafka设计思想使用java实现的一套mq。同时将阿里系内部多款mq产品(Notify、metaq)进行整合,只维护核心功能,去除了全部其余运行时依赖,保证核心功能最简化,在此基础上配合阿里上述其余开源产品实现不一样场景下mq的架构,目前主要多用于订单交易系统。

具备如下特色:

  • 可以保证严格的消息顺序
  • 提供针对消息的过滤功能
  • 提供丰富的消息拉取模式
  • 高效的订阅者水平扩展能力
  • 实时的消息订阅机制
  • 亿级消息堆积能力

官方提供了一些不一样于kafka的对比差别: 
https://rocketmq.apache.org/docs/motivation/

      7.2 RabbitMQ

使用Erlang编写的一个开源的消息队列,自己支持不少的协议:AMQP,XMPP, SMTP,STOMP,也正是如此,使的它变的很是重量级,更适合于企业级的开发。同时实现了Broker架构,核心思想是生产者不会将消息直接发送给队列,消息在发送给客户端时先在中心队列排队。对路由(Routing),负载均衡(Load balance)、数据持久化都有很好的支持。多用于进行企业级的ESB整合。

      7.3 ActiveMQ

Apache下的一个子项目。使用Java彻底支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,少许代码就能够高效地实现高级应用场景。可插拔的传输协议支持,好比:in-VM, TCP, SSL, NIO, UDP, multicast, JGroups and JXTA transports。RabbitMQ、ZeroMQ、ActiveMQ均支持经常使用的多种语言客户端 C++、Java、.Net,、Python、 Php、 Ruby等。

      7.4 Redis

使用C语言开发的一个Key-Value的NoSQL数据库,开发维护很活跃,虽然它是一个Key-Value数据库存储系统,但它自己支持MQ功能,因此彻底能够当作一个轻量级的队列服务来使用。对于RabbitMQ和Redis的入队和出队操做,各执行100万次,每10万次记录一次执行时间。测试数据分为128Bytes、512Bytes、1K和10K四个不一样大小的数据。实验代表:入队时,当数据比较小时Redis的性能要高于RabbitMQ,而若是数据大小超过了10K,Redis则慢的没法忍受;出队时,不管数据大小,Redis都表现出很是好的性能,而RabbitMQ的出队性能则远低于Redis。

      7.5 Kafka

Apache下的一个子项目,使用scala实现的一个高性能分布式Publish/Subscribe消息队列系统,具备如下特性:

  • 快速持久化:经过磁盘顺序读写与零拷贝机制,能够在O(1)的系统开销下进行消息持久化;
  • 高吞吐:在一台普通的服务器上既能够达到10W/s的吞吐速率;
  • 高堆积:支持topic下消费者较长时间离线,消息堆积量大;
  • 彻底的分布式系统:Broker、Producer、Consumer都原生自动支持分布式,依赖zookeeper自动实现复杂均衡;
  • 支持Hadoop数据并行加载:对于像Hadoop的同样的日志数据和离线分析系统,但又要求实时处理的限制,这是一个可行的解决方案。

      7.6 ZeroMQ

号称最快的消息队列系统,专门为高吞吐量/低延迟的场景开发,在金融界的应用中常用,偏重于实时数据通讯场景。ZMQ可以实现RabbitMQ不擅长的高级/复杂的队列,可是开发人员须要本身组合多种技术框架,开发成本高。所以ZeroMQ具备一个独特的非中间件的模式,更像一个socket library,你不须要安装和运行一个消息服务器或中间件,由于你的应用程序自己就是使用ZeroMQ API完成逻辑服务的角色。可是ZeroMQ仅提供非持久性的队列,若是down机,数据将会丢失。如:Twitter的Storm中使用ZeroMQ做为数据流的传输。

ZeroMQ套接字是与传输层无关的:ZeroMQ套接字对全部传输层协议定义了统一的API接口。默认支持 进程内(inproc) ,进程间(IPC) ,多播,TCP协议,在不一样的协议之间切换只要简单的改变链接字符串的前缀。能够在任什么时候候以最小的代价从进程间的本地通讯切换到分布式下的TCP通讯。ZeroMQ在背后处理链接创建,断开和重连逻辑。

特性:

  • 无锁的队列模型:对于跨线程间的交互(用户端和session)之间的数据交换通道pipe,采用无锁的队列算法CAS;在pipe的两端注册有异步事件,在读或者写消息到pipe的时,会自动触发读写事件。
  • 批量处理的算法:对于批量的消息,进行了适应性的优化,能够批量的接收和发送消息。
  • 多核下的线程绑定,无须CPU切换:区别于传统的多线程并发模式,信号量或者临界区,zeroMQ充分利用多核的优点,每一个核绑定运行一个工做者线程,避免多线程之间的CPU切换开销。

 

2、主要消息中间件的比较

 

综合选择RabbitMq