当前位置: 首页 > 后端技术 > Java

常见的消息中间件大PK

时间:2023-04-01 19:09:56 Java

@[toc]说到消息中间件,估计大家或多或少都能分得清,比如ActiveMQ、RabbitMQ、RocketMQ、Kafka等,还有各种协议如JMS和AMQP。但是,这几种消息中间件各有什么特点,我们在开发中应该选择哪一种呢?宋哥今天就来和小伙伴们一起梳理一下。1、几种协议首先说一下消息中间件中常见的几种协议。1.1JMS1.1.1JMS简介先说JMS。JMS的全称是JavaMessageService,类似于JDBC又不同于JDBC。JMS是JavaEE的消息服务接口。JMS有两个主要版本:1.12.0。两者相比,后者主要是简化了发送和接收消息的代码。考虑到消息中间件是一个非常常用的工具,JavaEE为此制定了专门的规范JMS。但是,与JDBC一样,JMS也是一种规范。它只是一组接口,不包含具体的实现。如果我们要使用JMS,一般都需要相应的实现,就像使用JDBC需要相应的驱动一样。1.1.2JMS模型JMS消息服务支持两种消息模型:点对点或队列模型发布/订阅模型在点对点或队列模型中,生产者向特定队列发布消息,消费者读取消息。来自队列的消息。在这里,生产者知道消费者的队列,直接将消息发送到对应的队列。这是一种点对点的消息模型,可以概括为:只有一个消费者会得到消息。消费者消费消息时生产者不需要处于运行状态,消费者发送消息时也不需要处于运行状态,即消息的生产者和消费者完全解耦.每条成功处理的消息都由消息使用者签名。发布者/订阅者模型支持向特定的消息主题发布消息,消费者可以定义自己感兴趣的主题,这是一种点对面的消息模型。这个模型可以概括为:多个消费者可以消费消息。发布者和订阅者之间存在时间依赖性。发布者需要创建一个订阅,以便客户端可以订阅;订户必须保持在线才能接收消息;当然,如果订阅者创建了持久订阅,那么当订阅者没有连接时,消息生产者发布的消息会在订阅者重新连接时重新发布。1.1.3JMS实现开源的支持JMS的消息中间件包括:KafkaApacheActiveMQJBoss社区的HornetQJoramCoridan的MantaRayOpenJMS一些商业的支持JMS的消息中间件包括:WebLogicServerJMSEMSGigaSpacesiBusIONAJMSIQManager(2005年8月被SunMicrosystems收购)JMS+NirvanaSonicMQWebSphere这里有很多MM由宋阁考古发掘。其实我们日常开发接触比较多的可能是Kafka和ActiveMQ。1.2AMQP1.2.1AMQP简介另一个与消息中间件相关的协议是AMQP。对MessageQueue的需求由来已久。在80年代最早的金融交易中,高盛等公司使用了Teknekron的产品。当时的MessageQueue软件叫做:信息总线(TIB)。TIB被电信和通信公司采用,路透社收购了TeknekronCorporation。后来IBM开发了MQSeries,微软开发了MicrosoftMessageQueue(MSMQ)。这些商业MQ供应商的问题是供应商锁定和高价格。2001年,JavaMessageService试图解决锁定和交互性的问题,但对应用来说却变得更加麻烦。于是在2004年,摩根大通和iMatrix开始开发高级消息队列协议(AMQP)开放标准。2006年,AMQP规范发布。2007年,RabbitTechnologies基于AMQP标准开发的RabbitMQ1.0发布。目前最新版本的RabbitMQ是3.5.7,基于AMQP0-9-1。在AMQP协议中,消息的发送和接收涉及到以下几个概念:Broker:接收和分发消息的应用程序。我们日常使用的RabbitMQ就是一个MessageBroker。Virtualhost:为多租户和安全因素而设计,AMQP的基本组件被划分为一个虚拟组,类似于网络中的命名空间概念。当多个不同的用户使用同一个RabbitMQ提供的服务时,可以划分多个vhost,每个用户在自己的vhost中创建一个exchange/queue等。松哥之前专门写过一篇文章,传送门:【VirtualHost在RabbitMQ理解]()。连接:发布者/消费者和代理之间的TCP连接。断开连接的操作只会在client端进行,Broker不会断开连接,除非出现网络故障或者broker服务出现问题。Channel:如果每次访问RabbitMQ都建立Connection,消息量大时建立TCPConnection的开销会很大,效率会很低。Channel是Connection内部建立的逻辑连接。如果应用支持多线程,通常每个Thread都会创建一个单独的Channel进行通信。AMQP方法包含Channelid帮助client和MessageBroker识别Channel,所以Channel是完全隔离的。Channel作为一个轻量级的Connection,大大降低了操作系统建立TCPConnection的开销。关于Channel,松哥在RabbitMQ管理页面的使用方法一文中也有详细介绍。Exchange:消息到达第一站Broker,根据分发规则,匹配查询表中的routingkey,将消息分发到队列中。常用的类型有:direct(点对点)、topic(发布-订阅)和fanout(广播)。Queue:消息最终发送到这里被Consumer取走,一个Message可以同时复制到多个队列。绑定:Exchange和Queue之间的虚拟连接。Binding可以包含路由键,Binding信息保存在Exchange中的查询表中,作为Message分发的依据。1.2.2AMQP实现下面我们来看一些具体实现了AMQP协议的消息中间件产品。ApacheQpidApacheActiveMQRabbitMQ可能有小伙伴,为什么会有ActiveMQ?其实ActiveMQ不仅支持JMS,还支持AMQP,后面宋大哥会详细讲解。此外,还有大家熟知的阿里出品的RocketMQ。这是一个自定义协议。社区也提供了JMS,但是还不成熟,后面松哥会细说。1.3MQTT做物联网开发的小伙伴应该经常接触到这个协议。MQTT(MessageQueuingTelemetryTransport)是IBM开发的一种即时通讯协议。它似乎是物联网发展中比较重要的协议之一。首先,该协议支持所有平台,几乎可以将所有的联网物品与外界连接起来。它被用作传感器和执行器的通信协议(例如通过Twitter将房屋连接到互联网)。其优点是格式简洁,带宽小,支持移动端通信,支持PUSH,适用于嵌入式系统。1.4XMPPXMPP(ExtensibleMessagingandPresenceProtocol,可扩展消息和状态协议)是一种基于XML的协议,主要用于即时消息(IM)和在线状态检测,适用于服务器之间的准即时操作。它的核心是基于XML流,这种协议最终可能允许互联网用户向互联网上的任何其他人发送即时消息,即使他们的操作系统和浏览器不同。其优点是通用开放性、兼容性强、可扩展性强、安全性高。缺点是XML编码格式占用带宽大。1.5JMSVsAMQP对于我们Java工程师来说,JMS和AMQP协议应该是我们日常接触比较多的。既然JMS和AMQP都是协议,那么两者有什么区别呢?看下图:这张图很清楚,我就不啰嗦了。2.重要产品2.1ActiveMQActiveMQ是Apache下的一个子项目。它使用完全支持JMS1.1和J2EE1.4规范的JMSProvider实现。少量代码即可高效实现高级应用场景,支持可插拔传输协议。例如:in-VM、TCP、SSL、NIO、UDP、多播、JGroups和JXTA传输。ActiveMQ支持C++、Java、.Net、Python、Php、Ruby等常用的多语言客户端,目前的ActiveMQ分为两个版本:ActiveMQClassicActiveMQArtemis这里ActiveMQClassic就是原来的ActiveMQ,ActiveMQArtemis是在RedHat捐赠的HornetQ服务器代码的基础上开发。两者代码完全不同,后者支持JMS2.0,使用基于Netty的异步IO,大大提高了性能。更神奇的是,后者不仅支持JMS协议,还支持AMQP协议、STOMP和MQTT。可以说后者的玩法还是挺多的。所以大家在使用的时候,建议直接选择ActiveMQArtemis。2.2RabbitMQRabbitMQ是AMQP体系下最重要的产品。它是基于Erlang语言开发和实现的。估计很多人都被RabbitMQ的安装折磨过。松哥推荐安装RabbitMQ,直接使用Docker,省心省力(公众号后台回复docker有教程)。RabbitMQ支持AMQP、XMPP、SMTP、STOMP等多种协议,功能强大,适合企业级开发。先看一张RabbitMQ的结构图:关于RabbitMQ,宋大哥最近出了十几篇教程,这里不再赘述。2.3RocketMQRocketMQ是阿里巴巴开源的分布式消息中间件。它最初被命名为Metaq,从3.0版本开始更名为RocketMQ。RocketMQ集成了阿里内部多种MQ产品(Notify、Metaq),只维护核心功能,去除所有其他运行时依赖,保证最精简核心功能。在此基础上,再配合前面提到的阿里其他开源产品,实现不同场景下的MQ架构,目前主要应用于订单交易系统。RocketMQ具有以下特点:保证严格的消息顺序。为消息提供过滤功能。提供丰富的消息拉取方式。高效的用户水平扩展能力。实时消息订阅机制。亿级消息堆叠能力对于Java工程师来说,这也是一种经常使用的MQ。2.4KafkaKafka是Apache下的开源流处理平台,用Scala和Java编写。Kafka是一个高吞吐量的分布式发布-订阅消息系统,可以处理网站中的所有消费者操作(网页浏览、搜索和其他用户操作)流数据。Kafka的目的是通过Hadoop的并行加载机制,统一在线和离线消息处理,通过集群提供实时消息。Kafka具有以下特点:快速持久化:通过磁盘顺序读写和零拷贝机制,可以在O(1)的系统开销下进行消息持久化。高吞吐量:普通服务器可以达到10W/s的吞吐率。高堆积:支持主题下消费者长时间离线,导致大量消息堆积。完全分布式系统:Broker、Producer、Consumer都自动原生支持分布式,更复杂的负载均衡可以通过Zookeeper自动实现。支持并行加载Hadoop数据。在大数据开发中可能会经常接触到Kafka,在Java开发中也会接触到,但是相对来说可能接触的比较少。2.5ZeroMQZeroMQ被称为最快的消息队列系统。专为高吞吐/低延迟场景开发。常用于金融应用,侧重于实时数据通信场景。ZeroMQ不是一个单独的服务,而是一个嵌入式库。它封装了网络通信、消息队列、线程调度等功能,向上层提供了简洁的API。应用程序加载库文件并调用API函数来实现高性能的网络通信。.ZeroMQ的特点:无锁队列模型:对于跨线程交互(client和session)之间的数据交换通道管道,采用无锁队列算法CAS,在管道两端注册异步事件。当向管道写入消息时,会自动触发读写事件。批处理算法:针对批处理消息,进行自适应优化,可以批量接收和发送消息。多核下的线程绑定,无需CPU切换:与传统的多线程并发模式、信号量或临界区不同,ZeroMQ充分利用了多核的优势,每个核绑定运行一个工作线程,避免了冲突多线程之间的CPU切换开销。2.6其他此外,Redis还可以作为消息队列使用。宋大哥之前也发过一篇文章,介绍了Redis作为普通消息队列和延迟消息队列的使用,这里就不啰嗦了。3.对比最后,我们通过一张图来对比一下各个消息中间件。小伙伴们,在公众号后台回复mqpkmq,就可以得到这个Excel表格的链接。好了,废话不多说了。