MOM系列文章之 - JMS2 spec. 解读

简介:      JMS 2是Java EE 7的一个重要“卖点”(如图所示), 本文的重点也落在了JMS 2规范上,通过近4个小时的阅读(156 Page),结合最近Common MQ的实施经验,谈谈对新规范的一些解读,后续会陆续发表一些相关博文,希望大家能够感兴趣。        浏览一下Architecture章节目录,大家很快就会意识到,JMS 2的一个最重要的设计初衷,

     JMS 2是Java EE 7的一个重要“卖点”(如图所示), 本文的重点也落在了JMS 2规范上,通过近4个小时的阅读(156 Page),结合最近Common MQ的实施经验,谈谈对新规范的一些解读,后续会陆续发表一些相关博文,希望大家能够感兴趣。



       浏览一下Architecture章节目录,大家很快就会意识到,JMS 2的一个最重要的设计初衷,通过减少编码提高生产力;通过更高层次的抽象,简化消息模型。3,4,5,6,7,8,9章节则陆续在消息模型,消息领域,消息发送,消息接收,异常体系,特性工具集等方面进行详细阐述。第10,11,12章则重点阐述了JMS broker层面的一些内在工具API,如何与Java EE应用集成等(包括JTA事务,MDB,Context Injection)。接下来的章节就是Programmer最希望看到的 - 代码实例荟萃。最后一个章节(也是我这篇文章的开篇),则汇集了JMS version 2的change history。

        从这25条Change List,我们可以归纳出JMS 2.0的几个亮点(概括起来,就是Simplify,Clarify,Rectify)

(1)Session创建API的简化,避免了在事务消息下,开发者care消息的AcknowledgeMode。

(2)新增持久消费者创建API,替换JMS1.1里面的Domain-specific的API

(3)剔除同一Topic下允许并发消费者消费限制,带来了更好的可扩展性

(4)延迟投递,这个特性无疑对于本身就具有异步消费语意的消息系统进一个扩展。

(5)消息异步发送,通过回调函数的形式

(6)兼容Java SE 7的try-with-resource语法,简化对像的close操作,通过继承Autocloseable

(7)JMS provider必须设置JMSXDeliveryCount,别小看这个属性,对Session

acknowledge mode,reliable produce,Qos方面都有不小的作用

(8)废除了Message接口中的一些headers设置方法

(9)JMS provider 必须实现PTP,pub/sub两种消息通讯模型

(10) 修正了在使用MapMessage SetBytes方法时name为null的不一致异常表现。

        其它的小改进,比方说:订阅名字的128个字符限制,可选择的共享持久化订阅ClientId,Message新增 getBody方法,JMSExpiratoin的定义更加清晰等大家可以查阅手册。

        通过上面的概述,我们发现,2.0规范仍旧没有在Load balance/Fault-tolerance,Administration,Securiy,Wire Protocol,Message Store等方面给予规范性指导。这些也成为开源MOM在这些领域百花齐放的一个重要原因,比方说ZeroMQ在Wire Protocol层面的努力,AMQ在Message Store方面的不断尝试,Hornet MQ在Load Balance方面则引入了JGroup。可谓"因为规范,所以简单。因为开源,所以精彩“。

         有了上面粗线条的介绍,我们来具体看下规范究竟为我们展示了什么?

         首先,我们来看下JMS Application的组成:

                                               

       这里重点说明一下其中的三个组件:

       Non-JMS Clients ,作为JMS clients的一个重要补充,主要使用消息系统的一些Native API做事,比方说在zeroMQ中,如果使用Java版的client(JZMQ),本地可能会有个.o或者.dll的代码库,client通过通过调用native API 可以获得更好的性能(具体可以参见:https://github.com/zeromq/jzmq)。

       Messages,在JMS规范中,定义了5中类型:BytesMessage,MapMessage,ObjectMessage,StreamMessage,TextMessage.

       Administered Object,在JMS规范中,主要指的是预定义的ConnectionFactory,Destination类(一个用来管理Conenction,一个用来统一message-domain中的queue & topic),在JMS 2的几个核心概念中,也只有它们是支持并发的,这点请大家注意(JMSContext,JMSProducer,JMSConsumer则不然)。

        Ok,有了这些知识,我们来看看JMS 2是如何简化API的,上图看真相:


                                                                                                          JMS 1.x 



                                                                                                               JMS 2.x


       怎么样,很清晰吧,虽然不喜欢特性化的JMS命名,没办法,老接口还得用,命名只能这样将就一下了,难不成,各位亲还有其它更好的命名?

       JMSContext虽然从结构上看,统一了Connection& Session,但是其并未暴露获取它们的API,瞧,封装的多好?(好在哪,请大家思考)不过大家要明白Connection对象代表了一条到JMS broker的物理链接抽象,而Session则代表了单线程的会话(Send or Receive)

       下面,我们再来看另一个设计细节:JMS message的组成:

       Header:

       Properties(Application-specific properties & Standard properties,Provider-specific properties)

       Application-specific properties &Standard properties:


     Provider-specific properties : 如含有JMS_<vendor_name>属性名前缀,主要用在provider-native clients当中。

     Message Selector,再来看下这个存在已久的特性,它支持SQL 92语法,可以通过消息头,消息属性过滤实际投递到消费端消息,通过这个定义,我们似乎觉得Message Filter的概念更为贴近它的使用场景,有么有???

     Message Order,首先来看Order of message receipt,规范上写的挺清楚的,不解释

    JMS defines that messages sent by a session to a destination must be received in the order in which they weresent . This defines a partial ordering

constraint on a session’s input messagestream.

   JMS does not define order of message receipt across destinations or across a destination’s messages sent from multiplesessions. This aspect of a

session’s input message stream order istiming-dependent. It is not under application control.

     再来看Order of message sends,这里面有几个影响因子:Message PriorityDelivery mode。一句话概括一下:不保证,JMS provider自己实现

     在这一点上LinkedIn的Kafka通过Partition等有条件地实现了顺序消息,不过也从一定程度上牺牲了MOM的可扩展性,吞吐量。

     最后一个主题:Duplicate production of message & Duplicate delivery of message,规范里的硬性规定其实很直白: 不能投递已经确认了(acknowledged message)的信息两次(second copy); 不能够生产duplicate message,由于session recovery导致的情况除外。哈哈,剩下的就由JMS provider 去实现吧(AT_MOST_ONCE,DUPLICATEDS_OK,ONCE_AND_ONLY_ONCE,任你选的QOS)。

    恩,差不多了,剩下的API层面的改进,大家就在用的过程中去体会吧。

结束语:

     研究规范,而又不囿于规范。

     后面会陆续写一些文章,和大家分享一下自己在MOM方面的探索,希望你能喜欢~

     最后,保持研究的严谨性,附上参考资料,大家有空可以自己阅读~

附录:

    在工作中基于JMS 2规范开发了一套编程模型,如下:



参考资料:

1. http://www.oracle.com/technetwork/java/javaee/javaee7-whitepaper-1956203.pdf

2. http://jcp.org/aboutJava/communityprocess/final/jsr343/index.html

目录
相关文章
|
6月前
|
消息中间件 缓存
RabbitMQ消息模型之Sample
RabbitMQ消息模型之Sample
37 0
|
6月前
|
消息中间件
SpringCloud Stream集成RabbitMQ
SpringCloud Stream集成RabbitMQ
409 0
|
消息中间件
RabbitMQ.Client.Exceptions.BrokerUnreachableException:“None of the specified endpoints were reachabl
RabbitMQ.Client.Exceptions.BrokerUnreachableException:“None of the specified endpoints were reachabl
363 0
|
2月前
【Azure Service Bus】批量处理Service Bus Topic 中的死信消息(dead-lettered messages)
当然是有的。就是Service Bus Explorer工具,下载ZIP包解压或者安装版均可! 这个版本提供强大的 Service Bus 的管理功能。
|
消息中间件 SQL XML
ActiveMQ系列:详细讲讲JMS(Java Messaging Service)
一条持久性的消息:应该被传送“一次仅仅一次”,这就意味者如果JMS提供者出现故障,该消息并不会丢失,它会在服务器恢复之后再次传递。一条非持久的消息:最多会传送一次,这意味这服务器出现故障,该消息将永远丢失。
217 0
ActiveMQ系列:详细讲讲JMS(Java Messaging Service)
|
SQL 数据库 数据格式