1消息队列概述
我们现在生活的是一个信息高质量高可用并且持久的一个时代,作为技术开发人员,我们造就的代码程序需要有能力以简单并且高效可靠的方式将信息传送给需要的接受者。更为重要的是我们要优化消息传递的方式,使得场景有变的时候我们不需要重写那些代码。很多时候信息将成为孤岛,如果不把信息发布的生产者推倒重来的话,很难访问到其发布的信息。不过消息队列的出现正好解决这个问题。
消息队列技术将应用程序连接起来了,这些由不同发布者发布的讯息在消息代理服务器里面进行路由,最终被正确的消费者所接收。这种场景就像现在日常网购活动中最关键的一环——送快递。发布者我们可以理解为寄出快递的店家,消费者即是接收快递的买家,而我们的消息代理服务器就是快递公司。快递小哥们都需要拿到包裹,将其送往集散中心。这时候就要按照包裹填写的地址信息进行分批路由到不同的城市去。比如送往南京的我们就只能送往南京,而不会送到北京或者是上海。最终还是由快递小哥送到买家手上。整个过程不需要买家和卖家的直接关联,应用程序之间也是一样。我们通过快递公司或者是消息代理服务器托管即可。
2004年,JPMorgan Chase 和iMatix公司一起研发Advanced Message Queuing Protocal(AMQP)。该协议被设计为一个开放标准,用来解决各种消息队列的需求和时间拓扑问题。由于其开放的原则,任何人都能以AMQP的标准来实施自己的产品设计。也就是说只要大家都遵守这一标准,任何发布者和消费者都能动态相互建立联系,只要消费者感兴趣。今天,RabbitMQ不是唯一的消息代理服务。像ActiveMQ、ZeroMQ和Apache Qpid这些都提供了不同的并且各有特色的解决方案。那我为什么选择RabbitMQ?
(1)和Qpid一样,RabbitMQ也是实现了AMQP协议的消息代理服务,但其他的几种消息队列服务没有这样做。
(2)由于RabbitMQ是基于Erlang语言开发的,所以集群的构建非常地简单。
(3)多种案例表示RabbitMQ更加可靠,更能防止崩溃,是一种求稳的选择。
2 RabbitMQ消息中间件的研究
2.1 RabbitMQ特性
消息队列服务代理机制可以使企业里的负责各部分功能的不同应用相互通讯,只要实现了消息队列代理,便可进行互相调用。消息中间件就是一个独立的应用型组件。使用RabbitMQ,能够将不同功能的软件应用相互连接,实现相互调用,应用程序各功能单元(模块)、用户数据可以在需要的时候进行对话。消息队列服务代理机制将传统数据的发送和接收部分进行解耦,从而达到异步处理和降低耦合度的目的。通过这种方式,可以实现数据代理托管传输、非阻塞托管操作、推送生产待消费信息、发布/订阅、工作队列等功能。RabbitMQ是一个消息的代理托管服务器——一个独立于各个功能系统的中间件。它为应用程序之间提供了一个通用消息队列中转平台,用来发送和接收消息。同时它还能进行逻辑排序,分发策略定制,消息持久化保存等功能,并且在消息被消费之前,都能够安全地持久存在于队列中。其特性如下:
(1)可靠性,RabbitMQ使用一些机制来保证系统服务的可靠性,如持久化、传输确认机制、发布确认、高可用性。
(2)灵活路由策略,在消息进入队列之前,通过转换器(Exchange)来对消息的发布进行路由操作,将消息发布到指定到的队列中。对于典型的路由策略,RabbitMQ也提供了不同的转换器来予以支持。针对于更复杂的路由功能,可以将多个转换器绑定在一起,也可通过自定义插件机制实现自己的需要的转换器。
(3)消息集群(Cluster),多个RabbitMQ服务器可以组成一个联合工作群,形成单个逻辑服务实体。
(4)联合模型(Federation),对于需要比集群允许的更松散和不可靠的连接服务器联合工作群体,RabbitMQ提供联合模式。
(5)队列高可用,队列可以在集群中的机器上进行数据镜像备份,以确保在硬件出现问题的情况下,还能保证消息的安全。
(6)支持多种协议,RabbitMQ支持多种消息队列协议。
(7)支持多种客户端语言,RabbitMQ几乎支持所有的流行编程语言,如Java、Python等。
(8)UI管理界面,RabbitMQ有一个可视化的Web管理界面,作为一个可视化插件,它可以让用户管理消息服务并,对消息队列中的情况有一个清晰地认识。
(9)跟踪机制,如果消息的发布订阅发生异常,RabbitMQ提供对消息的跟踪机制,开发人员可以轻松定位问题的位置与原因。
(10)多种插件支持,RabbitMQ提供了多种针对于用户拓展的插件,可以从多方面进行特定业务需求的定制化。
其丰富的特性提供了人性化的,方便研发人员使用的高效条件。企业可以定制自己的消息代理服务器的特性,以此来适应自身的业务需求。
2.2 RabbitMQ与同类型服务的比较
ZeroMQ旨在解决每秒数亿个消息并发的大规模问题。它是一个基于性能的,基于套接字的消息传递库。ZeroMQ由开放源代码专家社区驱动,而不像RabbitMQ。
在ZeroMQ中,消息在具体类型的套接字中承载。套接字类型定义其语义,路由策略,队列等。不同类型的套接字可以连接在一起,如发布者和订阅者套接字。消息中的模式通过这些套接字得以体现。
ZeroMQ从与传统TCP连接有些不同的连接中导出电源。在传统的情况下,当创建套接字时,服务器必须存活。 然而,在ZeroMQ中,可以自动启动位和片段:可以提前创建套接字,只有当服务器上线时才会开始传递消息。一个ZeroMQ套接字还可以连接多个传入和传出连接,并且在断开连接后,连接将自动更新。
每个RabbitMQ服务器至少包含一个节点,并且在群集配置中更多地包含多个节点。 交换和队列包括用于分区代理数据的虚拟主机。连接到RabbitMQ节点上的虚拟主机(参见图1)。
图1 传统应用通讯图
RabbitMQ交易所可以是临时,自动删除或持久的。交换机支持定向策略、轮播策略,以及交换机的标题和基于主题的路由方案。排队,如交换机,是临时的,自动删除或持久的。
几乎所有的消息协议都有两个功能不同的层:连接和代理。连接层包括与消息系统中节点之间连接相关的所有细节,例如握手和认证过程。代理层或代理模型定义端点之间队列中消息发生了什么。
ActiveMQ和ZemoMQ类似,其特性介于RabbitMQ和ZeroMQ之间,不过Active与Spring框架有集成。因此可以很方便的通过Spring为其提供的模板进行开发。它可以部署于代理模式和P2P模式。
3应用场景
3.1应用需求
现有系统一般由不同服务器上的多个单独的应用程序组成,每个都有自己的数据库,并且业务功能上都有所不同。在第一个应用程序中的用户数据更新后,第二个应用程序必须反映这些更改。他们的数据库都包含一个用户表,但每个都有不同的结构。为了将更改从第一个应用程序传播到第二个应用程序的数据库,Web API已在后一个应用程序中定义,以接收用户数据并将其保存到数据库。图2显示了我们描述的情景的应用架构中的组件位置和数据流。
图2 传统应用通讯图
应用程序位于不同机器上的不同域,数据传递到公共可用但受限制的位置。 当在第一个应用程序中更新用户数据时,更新将通过使用POST查询的Web API发送。API通过连接加密,防火墙访问规则和消息令牌化进行保护,防止窃听和未经授权的条目。
图2还显示了应用程序的紧密耦合¬——它们必须同时在线和脱机,以防止发生数据差异。使用应用程序之间的消息代理,当第一个应用程序更新用户数据时,第二个应用程序可以脱机,并且当第二个应用程序重新联机时,更改将有效地传播。在这种情况下,将消息代理引入系统的好处并不仅限于解耦本身,还包括其简化:通过减少应用程序代码的管理,两个应用程序的维护更加容易。3.2实际应用场景通常,引入消息代理以取代系统中的现有功能的第一步是首先定义代理的业务需求,其次是识别数据端点,即找出系统的数据交换关系的位置。必须采取这些步骤来确定最适合的消息代理和消息代理中正确的操作模式,以匹配手头的任务。这里对于RabbitMQ的选择研究已经做好了,所以下一步是交换常用数据的部分。当解耦更大的系统时,可能需要进行彻底的架构检查,那将会是一项耗时的任务。然而,这里很容易,因为已经知道两个应用程序共享什么数据以及如何运作了。
图3 嵌入消息队列的通讯
如图3所示,应用程序不再具有直接连接,因此可以分开管理。队列发布者和消费者不是应用程序的一部分,因此可以使用更多的性能技术实现。如果用户数据流量增长足以减缓操作速度,则可以添加更多队列消费者来更快地处理消息。
图3还描绘了消息代理解决方案启用的潜在未来添加。为了使RabbitMQ具有弹性,故应使用集群,而不是独立的RabbitMQ节点。生产环境中数据完整性是绝对要求的。Rabbit消息队列还通过RabbitMQ的内置管理插件实现了监控和度量。
3.3基于RabbitMQ的软总线设计
到此已经深入了解了消息队列的适用场景,以及对RabbitMQ进行了深入的分析与研究的前提下。我们了解到消息队列的引入,对现代分布式高并发的复杂应用带来了福音。它能以其独特的方式保证消息的安全性、可靠性。同时也能让系统解耦,降低各模块的依赖程度。
从目前来看,RabbitMQ是一个非常优秀,并且可靠的消息代理服务。即使在处理速度上比不了ZeroMQ。但在其提供的多样,并且人性化的功能面前,人们能更加容易地进行开发。况且RabbitMQ几乎支持所有的编程语言客户端。基于上述RabbitMQ的特点以及其能解决的实际能力,接下来的文章将介绍如何实施一个基于RabbitMQ的消息队列软总线服务。我将在其提供的Java API的原有基础上,结合现在流行的框架技术进行二次封装。突出其多样的发布订阅策略,使系统之间的耦合程度进一步地降低。