消息中间件

1前言

1.1概念

消息队列中间件(简称消息中间件)是指利用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通信来进行分布式系统的集成。

通过提供消息传递和消息排队模型,它可以在分布式环境下提供应用解耦、弹性伸缩、冗余存储、流量削峰、异步通信、数据同步等等功能,其作为分布式系统架构中的一个重要组件,有着举足轻重的地位。

1.2常用协议

1.2.1AMQP

AMQP即AdvancedMessageQueuingProtocol,一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。

基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同开发语言等条件的限制。

1.2.2MQTT

MQTT(MessageQueuingTelemetryTransport,消息队列遥测传输)是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分。

MQTT:该协议支持所有平台,几乎可以把所有联网物品和外部连接起来,被用来当做传感器和致动器(比如通过Twitter让房屋联网)的通信协议。

优点:格式简洁、占用带宽小、移动端通信、PUSH、嵌入式系统

1.2.3STOMP

STOMP(StreamingTextOrientatedMessageProtocol)是流文本定向消息协议,是一种为MOM(MessageOrientedMiddleware,面向消息的中间件)设计的简单文本协议。

STOMP:STOMP提供一个可互操作的连接格式,允许客户端与任意STOMP消息代理(Broker)进行交互。
优点:命令模式(非topic\queue模式)

1.2.4XMPP

XMPP(可扩展消息处理现场协议,ExtensibleMessagingandPresenceProtocol)是基于可扩展标记语言(XML)的协议,多用于即时消息(IM)以及在线现场探测。

XMPP:适用于服务器之间的准即时操作。核心是基于XML流传输,这个协议可能最终允许因特网用户向因特网上的其他任何人发送即时消息,即使其操作系统和浏览器不同。
优点:通用公开、兼容性强、可扩展、安全性高,但XML编码格式占用带宽大

2组成

2.1Broker

消息服务器,作为server提供消息核心服务

2.2Producer

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

2.3Consumer

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

2.4Topic

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

2.5Queue

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

2.6Message

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

3开源简介

3.1ActiveMQ

ActiveMQ是Apache出品,最流行的,能力强劲的开源消息总线,并且它是一个完全支持JMS规范的消息中间件。其丰富的API、多种集群构建模式使得他成为业界老牌消息中间件,在中小型企业中应用广泛!
当然现在可能用的相对比较少了,因为ActiveMQ性能和其他的主流MQ相比是比较一般的,早期在传统行业为王的时代它是比较流行的,现如今对于一些高并发、大数据的应用场景随处可见,在MQ的选择上如果再使用ActiveMQ往往就比较力不从心了。

主要特性
服从JMS规范:JMS规范提供了良好的标准和保证,包括:同步或异步的消息分发,一次和仅一次的消息分发,消息接收和订阅等等。遵从JMS规范的好处在于,不论使用什么JMS实现提供者,这些基础特性都是可用的;
连接灵活性:ActiveMQ提供了广泛的连接协议,支持的协议有:HTTP/S,IP多播,SSL,TCP,UDP等等。对众多协议的支持让ActiveMQ拥有了很好的灵活性;
支持的协议种类多:OpenWire、STOMP、REST、XMPP、AMQP;
持久化插件和安全插件:ActiveMQ提供了多种持久化选择。而且,ActiveMQ的安全性也可以完全依据用户需求进行自定义鉴权和授权;
支持的客户端语言种类多:除了Java之外,还有:C/C++,.NET,Perl,PHP,Python,Ruby;
代理集群:多个ActiveMQ代理可以组成一个集群来提供服务;
异常简单的管理:ActiveMQ是以开发者思维被设计的。所以,它并不需要专门的管理员,因为它提供了简单又使用的管理特性。有很多中方法可以监控ActiveMQ不同层面的数据,包括使用在JConsole或者在ActiveMQ的WebConsole中使用JMX。通过处理JMX的告警消息,通过使用命令行脚本,甚至可以通过监控各种类型的日志。

优点
跨平台(JAVA编写与平台无关,ActiveMQ几乎可以运行在任何的JVM上);
可以用JDBC:可以将数据持久化到数据库。虽然使用JDBC会降低ActiveMQ的性能,但是数据库一直都是开发人员最熟悉的存储介质;
支持JMS规范:支持JMS规范提供的统一接口;
支持自动重连和错误重试机制;
有安全机制:支持基于shiro,jaas等多种安全配置机制,可以对Queue/Topic进行认证和授权;
监控完善:拥有完善的监控,包括WebConsole,JMX,Shell命令行,Jolokia的RESTfulAPI;
界面友善:提供的WebConsole可以满足大部分情况,还有很多第三方的组件可以使用,比如hawtio;

缺点
社区活跃度不及RabbitMQ高;
根据其他用户反馈,会出莫名其妙的问题,会丢失消息;
目前重心放到activemq6.0产品Apollo,对5.x的维护较少;
不适合用于上千个队列的应用场景;

使用说明
MQ衡量指标:服务性能、数据存储、集群架构
ActiveMQ它的性能不是特别的好,面对超大规模的并发时,就有可能出现各种各样的小问题,比如阻塞、消息堆积过多、产生一些延迟等等。

从数据存储来看ActiveMQ采用KahaDB这种存储方式作为默认的持久化方案。当然也可以选择使用高性能的Google的LevelDB这种基于内存的,或者说想要保证消息百分百可靠的话也可以选择一些关系型数据库如MySQL

ActiveMQ流行了这么多年,其API包括相关的组件以及集成都是非常的完善的。所以说如果不是特别大的并发场景下,ActiveMQ也是比较不错的选择。其集群架构模式也非常不错。

集群架构模式
ActiveMQ最简单的分为两种集群架构模式,一种是Master-Slave模式,即主备模式(左图)。它利用zookeeper进行两个节点之间的协调,也有可能是更多的节点,其中有一个是主节点,它是对外提供服务的,另外的节点启动但是不对外提供服务。当主节点挂掉时,利用zookeeper进行高可用的切换,把slave节点切换成主节点,继续对外提供服务。

还有一种集群模式是NetWork模式(右图),它其实本质上就是两组主备模式的集成,然后中间用网关进行连接配置,就可以实现分布式的集群了。

在这里插入图片描述
在这里插入图片描述

3.2RabbitMQ

RabbitMQ是使用Erlang语言开发的开源消息队列系统,基于AMQP协议来实现。AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。AMQP协议更多用在企业系统内,对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在其次。

主要特性
可靠性:提供了多种技术可以让你在性能和可靠性之间进行权衡。这些技术包括持久性机制、投递确认、发布者证实和高可用性机制;
灵活的路由:消息在到达队列前是通过交换机进行路由的。RabbitMQ为典型的路由逻辑提供了多种内置交换机类型。如果你有更复杂的路由需求,可以将这些交换机组合起来使用,你甚至可以实现自己的交换机类型,并且当做RabbitMQ的插件来使用;
消息集群:在相同局域网中的多个RabbitMQ服务器可以聚合在一起,作为一个独立的逻辑代理来使用;
队列高可用:队列可以在集群中的机器上进行镜像,以确保在硬件问题下还保证消息安全;
支持多种协议:支持多种消息队列协议;
支持多种语言:用Erlang语言编写,支持只要是你能想到的所有编程语言;
管理界面:RabbitMQ有一个易用的用户界面,使得用户可以监控和管理消息Broker的许多方面;
跟踪机制:如果消息异常,RabbitMQ提供消息跟踪机制,使用者可以找出发生了什么;
插件机制:提供了许多插件,来从多方面进行扩展,也可以编写自己的插件。

优点
由于Erlang语言的特性,消息队列性能较好,支持高并发;
健壮、稳定、易用、跨平台、支持多种语言、文档齐全;
有消息确认机制和持久化机制,可靠性高;
高度可定制的路由;
管理界面较丰富,在互联网公司也有较大规模的应用,社区活跃度高。
缺点
尽管结合Erlang语言本身的并发优势,性能较好,但是不利于做二次开发和维护;
实现了代理架构,意味着消息在发送到客户端之前可以在中央节点上排队。此特性使得RabbitMQ易于使用和部署,但是使得其运行速度较慢,因为中央节点增加了延迟,消息封装后也比较大;需要学习比较复杂的接口和协议,学习和维护成本较高。

使用说明
RabbitMQ它的性能虽然不及kafka,但是要比ActiveMQ高出很多,而且可以做一些性能优化。并其可靠性和安全性非常好,数据可以保证百分百不丢失。RabbitMQ集群可以构建很多组,实现异地双活架构。每一个节点存储方式可以采用内存(ram)或者磁盘(disk),所以是非常灵活的。

集群模式
图中显示的是三个RabbitMQ节点作为一组集群,当然也可以有很多组。节点之间呢采用MirrorQueue(镜像队列)的方式,基于这种方式可以保证数据百分百不丢失。前端可以进行一个负载均衡,例如HA-proxy进行TCP级别的负载,配合keepAlived做一个高可用的配置。前端增加一个虚拟的VIP,通过访问VIP让请求路由到一个负载均衡组件,然后再往下路由到一个RabbitMQ节点。

这就是整个RabbitMQ的集群架构,它能够实现非常完善、非常高可用、并且性能也非常好,而且稳定性超强。它有各种各样的集群恢复的手段,比如节点挂点了、甚至是磁盘损坏了它也能去进行修复。这是RabbitMQ非常好的一个点。

在这里插入图片描述

3.3Kafka

Kafka是LinkedIn开源的分布式发布-订阅消息系统,目前归属于Apache定级项目。Kafka主要特点是基于Pull的模式来处理消息消费,追求高吞吐量,一开始的目的就是用于日志收集和传输。0.8版本开始支持复制,不支持事务,对消息的重复、丢失、错误没有严格要求,适合产生大量数据的互联网服务的数据收集业务。

主要特性
快速持久化:可以在O(1)的系统开销下进行消息持久化;
高吞吐:在一台普通的服务器上既可以达到10W/s的吞吐速率;
完全的分布式系统:Broker、Producer和Consumer都原生自动支持分布式,自动实现负载均衡;
支持同步和异步复制两种高可用机制;
支持数据批量发送和拉取;
零拷贝技术(zero-copy):减少IO操作步骤,提高系统吞吐量;
数据迁移、扩容对用户透明;
无需停机即可扩展机器;
其他特性:丰富的消息拉取模型、高效订阅者水平扩展、实时的消息订阅、亿级的消息堆积能力、定期删除机制;

优点
客户端语言丰富:支持Java、.Net、PHP、Ruby、Python、Go等多种语言;
高性能:单机写入TPS约在100万条/秒,消息大小10个字节;
提供完全分布式架构,并有replica机制,拥有较高的可用性和可靠性,理论上支持消息无限堆积;
支持批量操作;
消费者采用Pull方式获取消息。消息有序,通过控制能够保证所有消息被消费且仅被消费一次;
有优秀的第三方KafkaWeb管理界面Kafka-Manager;
在日志领域比较成熟,被多家公司和多个开源项目使用。

缺点
Kafka单机超过64个队列/分区时,Load时会发生明显的飙高现象。队列越多,负载越高,发送消息响应时间变长;
使用短轮询方式,实时性取决于轮询间隔时间;
消费失败不支持重试;
支持消息顺序,但是一台代理宕机后,就会产生消息乱序;
社区更新较慢。

使用说明
kafka最初设计时就是面向大数据方向的,主要用于日志收集,所以在使用kafka时,要注意业务是否允许出现消息重复、丢失、错误等问题,如果允许那使用kafka是性能最高的。它能够在廉价的服务器上也能支持单机每秒100k条数据以上的吞吐量。

kafka的高性能读写主要是借力于操作系统底层的提供的PageCache功能。而且kafka完全没有进行内存和磁盘的数据同步的烦恼,它仅仅使用内存的存储。只要你有足够的内存就能承载很大的数据。

集群架构模式
kafka的集群模式也依赖于zookeeper,让zookeeper进行节点的协调和管理。每个kafka节点之间可以进行replicate(副本的复制),对于某个节点的数据会依次同步到集群的其他节点上,这样只要部署方案合理,即使某个节点挂掉,其他节点的数据也依然存在。

在这里插入图片描述

3.4RocketMQ

RocketMQ是阿里开源的消息中间件,它是纯Java开发,具有高吞吐量、高可用性、适合大规模分布式系统应用的特点。RocketMQ思路起源于Kafka,但并不是Kafka的一个Copy,它对消息的可靠传输及事务性做了优化,目前在阿里集团被广泛应用于交易、充值、流计算、消息推送、日志流式处理、binglog分发等场景。

主要特性
基于队列模型:具有高性能、高可靠、高实时、分布式等特点;
Producer、Consumer、队列都支持分布式;
Producer向一些队列轮流发送消息,队列集合称为Topic。Consumer如果做广播消费,则一个Consumer实例消费这个Topic对应的所有队列;如果做集群消费,则多个Consumer实例平均消费这个Topic对应的队列集合;
能够保证严格的消息顺序;
提供丰富的消息拉取模式;
高效的订阅者水平扩展能力;
实时的消息订阅机制;
亿级消息堆积能力;
较少的外部依赖。

优点
单机支持1万以上持久化队列;
RocketMQ的所有消息都是持久化的,先写入系统PAGECACHE,然后刷盘,可以保证内存与磁盘都有一份数据,而访问时,直接从内存读取。
模型简单,接口易用(JMS的接口很多场合并不太实用);
性能非常好,可以允许大量堆积消息在Broker中;
支持多种消费模式,包括集群消费、广播消费等;
各个环节分布式扩展设计,支持主从和高可用;
开发度较活跃,版本更新很快。

缺点
支持的客户端语言不多,目前是Java及C++,其中C++还不成熟;
RocketMQ社区关注度及成熟度也不及前两者;
没有Web管理界面,提供了一个CLI(命令行界面)管理工具带来查询、管理和诊断各种问题;
没有在MQ核心里实现JMS等接口;

使用说明
RocketMQ在早期2.X版本也是使用zookeeper做协调,在后续3.X版本中放弃了使用zookeeper,而是自行实现了一套NameServer去做集群之间的管理和协调工作。

RocketMQ的特点在于它能够保障消息的顺序性,提供了丰富的消息拉取和处理模式,支持订阅者进行水平扩展,实时消息订阅的机制,以及它能承载上亿级别的消息堆积能力。

它的集群架构也有很多种,比如Master-Slave模式,双Master模式、双主双从(2M2S)模式,多主多从模式。它的集群架构可选的方案是非常多的。而且RacketMQ刷盘策略也很多,比如说同步刷写、异步复制。它的存储方式借鉴了很多优秀的开源技术,比如zerocopy、linux的ext4文件系统等。

集群模型
左边和右边分别是生产者集群和消费者集群,NameServer就是自行实现的用于替代zookeeper的程序。中间就是两主两从服务集群,可以实现主从的自动切换,数据之间也可以采用replicate机制。

当然这些优秀的机制在ApacheRocketMQ项目里面其实是不提供的,比如还有解决分布式事务使用MQ进行解耦,为什么没有呢?因为阿里的RocketMQ商业版是收费的,需要购买相关的产品才可以使用到这些功能。所以这也是使用RocketMQ的一个痛点。

在这里插入图片描述

3.5ZeroMQ

号称史上最快的消息队列,基于C语言开发。ZeroMQ是一个消息处理队列库,可在多线程、多内核和主机之间弹性伸缩,虽然大多数时候我们习惯将其归入消息队列家族之中,但是其和前面的几款有着本质的区别,ZeroMQ本身就不是一个消息队列服务器,更像是一组底层网络通讯库,对原有的SocketAPI上加上一层封装而已。

3.6其它

目前市面上的消息中间件还有很多,比如腾讯系的PhxQueue、CMQ、CKafka,又比如基于Go语言的NSQ,还有ZeroMQ和Redis。
当然,它们都很优秀,但是本文篇幅限制无法穷其所有,只介绍了常见的几种消息中间件。

4模式分类

4.1点对点

PTP点对点:使用queue作为通信载体

消息生产者生产消息发送到queue中,然后消息消费者从queue中取出并且消费消息。
消息被消费以后,queue中不再存储,所以消息消费者不可能消费到已经被消费的消息。Queue支持存在多个消费者,但是对一个消息而言,只会有一个消费者可以消费。

在这里插入图片描述

4.2发布/订阅

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

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

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

5优势

5.1屏蔽异构平台的细节

发送方、接收方系统之间不需要了解双方,只需认识消息。

5.2异步

消息堆积能力;发送方接收方不需同时在线,发送方接收方不需同时扩容(削峰)。
将耗时的同步操作,通过以发送消息的方式,进行了异步化处理。减少了同步等待的时间。

5.3解耦

防止引入过多的API给系统的稳定性带来风险;调用方使用不当会给被调用方系统造成压力,被调用方处理不当会降低调用方系统的响应能力。
消息队列减少了服务之间的耦合性,不同的服务可以通过消息队列进行通信,而不用关心彼此的实现细节,只要定义好消息的格式就行。

5.4复用

一次发送多次消费。

5.5可靠

一次保证消息的传递。如果发送消息时接收者不可用,消息队列会保留消息,直到成功地传递它。
消息队列一般会把接收到的消息存储到本地硬盘上(当消息被处理完之后,存储信息根据不同的消息队列实现,有可能将其删除),这样即使应用挂掉或者消息队列本身挂掉,消息也能够重新加载。

5.6提供路由

发送者无需与接收者建立连接,双方通过消息队列保证消息能够从发送者路由到接收者,甚至对于本来网络不易互通的两个服务,也可以提供消息路由。

6应用场景

6.1异步处理

一个用户注册流程,包含下述业务:
1.注册处理以及写数据库
2.发送注册成功的手机短信
3.发送注册成功的邮件信息

我们使用老方法的话,则会注册完执行发送短信再执行邮件发送。太low

一般使用的是:在注册成功后,使用两个线程去做发送邮件,发送短信操作。

如果用消息中间件:则将两个线程创建这些事情省了,直接发送消息给消息中间件,然后让邮件服务和短信服务自己去消息中间件里面去取消息,然后取到消息后再自己做对应的业务操作。就是这么方便

6.2应用解耦

a)订单系统—》库存系统(强耦合)
b)消息中间件:订单系统—》消息中间件《----库存系统(解耦)

说明:用户购买一笔订单,订单成交—》调用库存系统—1—》返回给订单系统,此时算一个正常业务。还有不正常的业务,就是用户订单完成后,订单系统并不去滴啊用库存系统-1操作,而是调用消息中间件,写入一个订单信息。又库存系统自己去消息中间件上去获取,然后更新库存,这样能够减少互联网型应用追求的快这一个属性。而库存系统读取订单间库存其实这个操作也是非常快的,所以有消息中间件对解耦来说也是一个不错的方向。

6.3流量削峰

a)用户请求-----》秒杀应用
b)应用的前端加入消息队列
c)用户请求-----》消息队列《----秒杀应用

说明:比如,系统举行秒杀活动,热门商品。流量蜂拥而至100件商品,10万人挤进来怎么办,10万秒杀的操作,放入消息队列。秒杀应用处理消息队列中的10万个请求中的100个,其他的打回,通知失败。流量峰值控制在消息队列处,秒杀应用不会瞬间被怼死.

6.4日志处理

a)错误日志—》消息队列《----日志处理
b)用户行为日志–》消息队列《-----日志的存储或流式处理

6.5消息通讯

消息通讯是指,消息队列一般都内置了高效的通信机制,因此也可以用在纯的消息通讯。比如实现点对点消息队列,或者聊天室等
1点对点通讯:客户端A和客户端B使用同一队列,进行消息通讯。
2聊天室通讯:客户端A,客户端B,客户端N订阅同一主题,进行消息发布和接收。实现类似聊天室效果。

7选型要点

7.1功能维度

7.1.1优先级队列

优先级队列不同于先进先出队列,优先级高的消息具备优先被消费的特权,这样可以为下游提供不同消息级别的保证。

7.1.2延迟队列

当你在网上购物的时候是否会遇到这样的提示:“三十分钟之内未付款,订单自动取消”,这个是延迟队列的一种典型应用场景。

延迟队列存储的是对应的延迟消息,所谓“延迟消息”是指当消息被发送以后,并不想让消费者立刻拿到消息,而是等待特定时间后,消费者才能拿到这个消息进行消费。

7.1.3死信队列

由于某些原因消息无法被正确投递,为了确保消息不会被无故丢弃,一般将其置于一个特殊角色的队列,这个队列称为死信队列。

与此对应的还有一个“回退队列”的概念,试想如果消费者在消费时发生了异常,那么就不会对这一次消费进行确认(Ack),进而发生回滚消息的操作之后消息始终会放在队列的顶部,然后不断被处理和回滚,导致队列陷入死循环。
为了解决这个问题,可以为每个队列设置一个回退队列,它和死信队列都是为异常的处理提供的一种机制保障。实际情况下,回退队列的角色可以由死信队列和重试队列来扮演。

7.1.4重试队列

其实可以看成是一种回退队列,具体指消费端消费消息失败时,为防止消息无故丢失而重新将消息回滚到Broker中。

与回退队列不同的是重试队列一般分成多个重试等级,每个重试等级一般也会设置重新投递延时,重试次数越多投递延时就越大。

7.1.5消费模式

推(push)模式:推模式是指由Broker主动推送消息至消费端,实时性较好,不过需要一定的流制机制来确保服务端推送过来的消息不会压垮消费端;
拉(pull)模式拉模式是指消费端主动向Broker端请求拉取(一般是定时或者定量)消息,实时性较推模式差,但是可以根据自身的处理能力而控制拉取的消息量。

7.1.6广播消费

点对点(P2P,Point-to-Point)模式:对于点对点的模式而言,消息被消费以后,队列中不会再存储,所以消息消费者不可能消费到已经被消费的消息。虽然队列可以支持多个消费者,但是一条消息只会被一个消费者消费。
发布/订阅(Pub/Sub)模式:发布订阅模式定义了如何向一个内容节点发布和订阅消息,这个内容节点称为主题(Topic),主题可以认为是消息传递的中介,消息发布者将消息发布到某个主题,而消息订阅者则从主题中订阅消息。主题使得消息的订阅者与消息的发布者互相保持独立,不需要进行接触即可保证消息的传递,发布/订阅模式在消息的一对多广播时采用。

7.1.7消息回溯

一般消息在消费完成之后就被处理了,之后再也不能消费到该条消息。消息回溯正好相反,是指消息在消费完成之后,还能消费到之前被消费掉的消息。
对于消息而言,经常面临的问题是“消息丢失”,至于是真正由于消息中间件的缺陷丢失还是由于使用方的误用而丢失,一般很难追查。如果消息中间件本身具备消息回溯功能的话,可以通过回溯消费复现“丢失的”消息进而查出问题的源头所在。
消息回溯的作用远不止与此,比如还有索引恢复、本地缓存重建,有些业务补偿方案也可以采用回溯的方式来实现。

7.1.8消息堆积+持久化

流量削峰是消息中间件的一个非常重要的功能,而这个功能其实得益于其消息堆积能力。从某种意义上来讲,如果一个消息中间件不具备消息堆积的能力,那么就不能把它看做是一个合格的消息中间件。
消息堆积分内存式堆积和磁盘式堆积:

RabbitMQ是典型的内存式堆积,但这并非绝对,在某些条件触发后会有换页动作来将内存中的消息换页到磁盘(换页动作会影响吞吐),或者直接使用惰性队列来将消息直接持久化至磁盘中;
Kafka是一种典型的磁盘式堆积,所有的消息都存储在磁盘中。
一般来说,磁盘的容量会比内存的容量要大得多,对于磁盘式的堆积其堆积能力就是整个磁盘的大小。从另外一个角度讲,消息堆积也为消息中间件提供了冗余存储的功能。援引《纽约时报》的案例,其直接将Kafka用作存储系统。

7.1.9消息追踪

对于分布式架构系统中的链路追踪(Trace),大家一定不陌生。对于消息中间件,消息的链路追踪(以下简称消息追踪)同样重要,最通俗来理解,就是要知道消息从哪来,存在哪里以及发往哪里去。基于此功能,我们可以对发送或者消费完的消息进行链路追踪服务,进而可以进行问题的快速定位与排查。

7.1.10消息过滤

消息过滤是指按照既定的过滤规则为下游用户提供指定类别的消息。
就以Kafka而言,完全可以将不同类别的消息发送至不同的Topic中,由此可以实现某种意义的消息过滤,或者Kafka还可以根据分区对同一个Topic中的消息进行分类。
不过,更加严格意义上的消息过滤,应该是对既定的消息采取一定的方式按照一定的过滤规则进行过滤。

同样以Kafka为例,可以通过客户端提供的ConsumerInterceptor接口或者KafkaStream的Filter功能进行消息过滤。

7.1.11多租户

也可以称为多重租赁技术,是一种软件架构技术,主要用来实现多用户的环境下公用相同的系统或程序组件,并且仍可以确保各用户间数据的隔离性
RabbitMQ就能够支持多租户技术,每一个租户表示为一个VHost,其本质上是一个独立的小型RabbitMQ服务器,又有自己独立的队列、交换器及绑定关系等,并且它拥有自己独立的权限。

VHost就像是物理机中的虚拟机一样,它们在各个实例间提供逻辑上的分离,为不同程序安全保密地允许数据,它既能将同一个RabbitMQ中的众多客户区分开,又可以避免队列和交换器等命名冲突。

7.1.12多协议支持

消息是信息的载体,为了让生产者和消费者都能理解所承载的信息(生产者需要知道如何构造消息,消费者需要知道如何解析消息),它们就需要按照一种统一的格式描述消息,这种统一的格式称之为消息协议。
有效的消息一定具有某种格式,而没有格式的消息是没有意义的。
一般消息层面的协议有AMQP、MQTT、STOMP、XMPP等(消息领域中的JMS更多的是一个规范而不是一个协议),支持的协议越多其应用范围就会越广,通用性越强,比如RabbitMQ能够支持MQTT协议就让其在物联网应用中获得一席之地。还有的消息中间件是基于其本身的私有协议运转的,典型的如Kafka。

7.1.13跨语言支持

对很多公司而言,其技术栈体系中会有多种编程语言,如C/C++、JAVA、Go、PHP等,消息中间件本身具备应用解耦的特性,如果能够进一步的支持多客户端语言,那么就可以将此特性的效能扩大。跨语言的支持力度也可以从侧面反映出一个消息中间件的流行程度。

7.1.14流量控制

针对的是发送方和接收方速度不匹配的问题,提供一种速度匹配服务抑制发送速率使接收方应用程序的读取速率与之相适应。通常的流控方法有Stop-and-Wait、滑动窗口以及令牌桶等。

7.1.15消息顺序性

顾名思义,是指保证消息有序。这个功能有个很常见的应用场景就是CDC(ChangeDataChapture),以MySQL为例,如果其传输的Binlog的顺序出错,比如原本是先对一条数据加1,然后再乘以2,发送错序之后就变成了先乘以2后加1,造成数据不一致。

7.1.16安全机制

在Kafka0.9版本之后就开始增加了身份认证和权限控制两种安全机制

身份认证是指客户端与服务端连接进行身份认证,包括客户端与Broker之间、Broker与Broker之间、Broker与ZooKeeper之间的连接认证,目前支持SSL、SASL等认证机制;
权限控制是指对客户端的读写操作进行权限控制,包括对消息或Kafka集群操作权限控制。权限控制是可插拔的,并支持与外部的授权服务进行集成。
对于RabbitMQ而言,其同样提供身份认证(TLS/SSL、SASL)和权限控制(读写操作)的安全机制

7.1.17消息幂等性

确保消息在生产者和消费者之间进行传输,一般有三种传输保障(DeliveryGuarantee)

Atmostonce,至多一次,消息可能丢失,但绝不会重复传输;
Atleastonce,至少一次,消息绝不会丢,但是可能会重复;
Exactlyonce,精确一次,每条消息肯定会被传输一次且仅一次。
对于大多数消息中间件而言,一般只提供Atmostonce和Atleastonce两种传输保障,对于第三种一般很难做到,由此消息幂等性也很难保证。
Kafka自0.11版本开始引入了幂等性和事务,Kafka的幂等性是指单个生产者对于单分区单会话的幂等,而事务可以保证原子性地写入到多个分区,即写入到多个分区的消息要么全部成功,要么全部回滚,这两个功能加起来可以让Kafka具备EOS(ExactlyOnceSemantic)的能力。
不过如果要考虑全局的幂等,还需要与从上下游方面综合考虑,即关联业务层面,幂等处理本身也是业务层面所需要考虑的重要议题。

7.1.18事务性消息

事务本身是一个并不陌生的词汇,事务是由事务开始(BeginTransaction)和事务结束(EndTransaction)之间执行的全体操作组成。
支持事务的消息中间件并不在少数,Kafka和RabbitMQ都支持,不过此两者的事务是指生产者发生消息的事务,要么发送成功,要么发送失败。消息中间件可以作为用来实现分布式事务的一种手段,但其本身并不提供全局分布式事务的功能。

7.2性能

功能维度是消息中间件选型中的一个重要的参考维度,但这并不是唯一的维度,有时候性能比功能还要重要,况且性能和功能很多时候是相悖的,鱼和熊掌不可兼得。

Kafka在开启幂等、事务功能的时候会使其性能降低;RabbitMQ在开启rabbitmq_tracing插件的时候也会极大影响其性能。

性能指什么?
消息中间件的性能一般是指其吞吐量。虽然从功能维度上来说,RabbitMQ的优势要大于Kafka,但是Kafka的吞吐量要比RabbitMQ高出1至2个数量级,一般RabbitMQ的单机QPS在万级别之内,而Kafka的单机QPS可以维持在十万级别,甚至可以达到百万级。
消息中间件的吞吐量始终会受到硬件层面的限制。就以网卡带宽为例,如果单机单网卡的带宽为1Gbps,如果要达到百万级的吞吐,那么消息体大小不得超过(1Gb/8)/100W,即约等于134B,换句话说如果消息体大小超过134B,那么就不可能达到百万级别的吞吐。这种计算方式同样可以适用于内存和磁盘。

性能的指标是什么?
时延作为性能维度的一个重要指标,却往往在消息中间件领域所被忽视,因为一般使用消息中间件的场景对时效性的要求并不是很高,如果要求时效性完全可以采用RPC的方式实现。
消息中间件具备消息堆积的能力,消息堆积越大也就意味着端到端的时延也就越长,与此同时延时队列也是某些消息中间件的一大特色。
那么为什么还要关注消息中间件的时延问题呢?
消息中间件能够解耦系统,对于一个时延较低的消息中间件而言,它可以让上游生产者发送消息之后可以迅速的返回,也可以让消费者更加快速的获取到消息,在没有堆积的情况下,可以让整体上下游的应用之间的级联动作更加高效,虽然不建议在时效性很高的场景下使用消息中间件,但是如果所使用的消息中间件的时延方面比较优秀,那么对于整体系统的性能将会是一个不小的提升。

7.3可靠性+可用性

消息丢失是使用消息中间件时所不得不面对的一个同点,其背后消息可靠性也是衡量消息中间件好坏的一个关键因素。尤其是在金融支付领域,消息可靠性尤为重要

区别:
消息中间件的可靠性是指对消息不丢失的保障程度;
而消息中间件的可用性是指无故障运行的时间百分比,通常用几个9来衡量。

7.4运维管理

在消息中间件的使用过程中难免会出现各式各样的异常情况,有客户端的,也有服务端的,那么怎样及时有效的进行监测及修复?业务线流量有峰值又低谷,尤其是电商领域,那么怎样前进行有效的容量评估,尤其是大促期间?脚踢电源、网线被挖等事件层出不穷,如何有效的做好异地多活?

这些都离不开消息中间件的衍生产品——运维管理。

运维管理也可以进行进一步的细分,比如申请、审核、监控、告警、管理、容灾、部署等。

申请、审核很好理解,在源头对资源进行管控,既可以进行有效校正应用方的使用规范,配合监控也可以做好流量统计与流量评估工作。一般申请、审核与公司内部系统交融性较大,不适合使用开源类的产品。

监控、告警也比较好理解,对消息中间件的使用进行全方位的监控,既可以为系统提供基准数据,也可以在检测到异常的情况配合告警,以便运维、开发人员的迅速介入。除了一般的监控项(比如硬件、GC等)之外,消息中间件还需要关注端到端时延、消息审计、消息堆积等方面:

对于RabbitMQ而言,最正统的监控管理工具莫过于rabbitmq_management插件了,但是社区内还有AppDynamics、Collectd、DataDog、Ganglia、Munin、Nagios、NewRelic、Prometheus、Zenoss等多种优秀的产品。

Kafka在此方面也毫不逊色,比如:KafkaManager、KafkaMonitor、KafkaOffsetMonitor、Burrow、Chaperone、ConfluentControlCenter等产品,尤其是Cruise还可以提供自动化运维的功能。

不管是扩容、降级、版本升级、集群节点部署、还是故障处理都离不开管理工具的应用,一个配套完备的管理工具集可以在遇到变更时做到事半功倍。

故障可大可小,一般是一些应用异常,也可以是机器掉电、网络异常、磁盘损坏等单机故障,这些故障单机房内的多副本足以应付。

如果是机房故障就要涉及异地容灾了,关键点在于如何有效的进行数据复制,Kafka可以参考MirrorMarker、uReplicator等产品,而RabbitMQ可以参考Federation和Shovel。

7.5社区力度及生态发展

对于目前流行的编程语言而言,如Java、Python,如果你在使用过程中遇到了一些异常,基本上可以通过搜索引擎的帮助来得到解决,因为一个产品用的人越多,踩过的坑也就越多,对应的解决方案也就越多。

消息中间件也同样适用,如果你选择了一种“生僻”的消息中间件,可能在某些方面运用的得心应手,但是版本更新缓慢、遇到棘手问题也难以得到社区的支持而越陷越深;相反如果你选择了一种“流行”的消息中间件,其更新力度大,不仅可以迅速的弥补之前的不足,而且也能顺应技术的快速发展来变更一些新的功能,这样可以让你以“站在巨人的肩膀上”。

在运维管理维度我们提及了Kafka和RabbitMQ都有一系列开源的监控管理产品,这些正是得益于其社区及生态的迅猛发展。

7.6对比图

4种常用的消息中间件的对比图:
在这里插入图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值