AMQP,JMS和MOM
今天在公司听关于JMS的session,再结合之前接触RabbitMQ了解到的知识,产生了一些困惑,这篇博客主要描述下困惑的原因以及理清后的结构。
首先,session中讲到JMS是一套JCP定义的协议,用于描述可供Java使用的消息API,总所周知,JCP定义的JSR只描述API接口及其行为,结合到我之前接触到的RabbitMQ中实现的AMQP协议,我想当然的以为JMS是AMQP协议的Java API封装,有一套标准的实现,基于标准的AMQP协议。但是之后经过同事解释,才明白到JMS的Java实现是由消息中间件的实现者提供,而且每个消息中间件有着不同的JMS Java库实现。毫无疑问,这是巨大的浪费,为了实现同样的功能接口,不同的vendor需要提供截然不同的Java库实现,而且封装的是消息机制这样的软件功能,而非蓝牙,或者NFC之类的硬件功能,匪夷所思。于是我稍微做了些调查,以便明白这种拙劣架构产生的历史原因。
首先看wikipedia上的JMS条目,提到了JMS中包含JMS Provider,是JMS接口针对MOM的实现,而MOM,是Message Oriented Middleware,也就是上面提到的消息中间件。
接下来看下MOM的条目,其中明确提到了MOM缺乏标准的混乱历史,主要的vendor都有自己的MOM实现,有自己的API接口,以及自己的管理工具。而这些MOM的vendor呢,基本都实现了JMS的接口,以便能为自己的MOM提供一套标准的公共接口,而这些JMS的实现其实就是用Java来封装自己的MOM API,因为JMS只定义了API,没定义消息格式!这里其实还存在两种可能,如果大量的MOM先存在,之后再有了JMS,以供这些MOM能有标准的接口,那么JMS的这种点到即止,还情有可原。但是如果JMS在先,因为没有定义消息格式这些原因,而导致了后来这种混乱局面,那么其设计多少是不负责任的,考虑到是JCP指定的JMS,这种情况是很可能发生的。
在JMS之后涌现出的AMQP,就是消息机制的一个标准协议,其清晰的定义了消息格式,以及蕴含其中的传输协议,甚至transaction概念,有了这样的标准协议,那么意味着,只要遵循了协议,无论消息服务器或者客户端由哪个vendor实现,那么都可以实现相互通讯。而且,针对每种语言,只需要一套客户端adapter实现库,而不是像以前一样,MOM因为自己定义了消息协议,就需要在每种语言上都实现自己MOM native API的封装。
在JMS这么坑爹的情况下,还是涌现出了ActiveMQ这样的项目,就定义了自己的协议,实现了MOM,并且提供了多语言的支持库,当然,免不了在非Java语言下再去定义一遍API接口,即便大同小异。不过,即便做到了这一步,ActiveMQ也没有发布一套标准的消息协议,似乎只是倒腾了OpenWire这个给不同语言使用的 porting layer出来。
总结一下,JMS就是单纯的Java API协议,定义了基于Java语言下的程序间进行消息通讯的接口。ActiveMQ,JBoss Messaging这些是消息中间件实现者(MOM),其定义了自己的消息协议,并且提供了JMS兼容的Java库。AMQP是一套标准的消息协议,与实现无关,AMQP兼容的实现间可以进行消息交换。也存在JMS到AMQP的Adapter库,这意味着用同一个库,可以与任意的AMQP服务器通讯,因为基于标准的协议,目前可供选择的有RabbitMQ,StormMQ等。