1.JMS规范介绍

  • Post author:
  • Post category:其他



目录


1.什么是JMS规范


2.什么是MOM


3.MOM的特点


4.JMS和MOM的关联


5.JMS的体系结构


6.JMS常见基本概念


7.JMS 的事务性会话和非事务性会话


8.JMS消息的可靠性机制


1.什么是JMS规范

Java 消息服务(Java Message Service)是 java 平台中关于面向消息中间件的 API,用于在两个应用程序之间,或者分布式系统中发送消息,进行异步通信。

JMS 是一个与


具体平台无关的 API


,绝大多数 MOM


??


(Message Oriented Middleware)(面向消息中间件)提供商都对 JMS 提供了支持。接下来讲解的ActiveMQ 就是其中一个实现。

JMS可以理解为是,Java平台为MQ产商提供的一套标准。你可以类比JDBC来理解即可,JDBC就是Java为Oracle、MySQL、SqlServer等数据库产商指定的标准。

2.什么是MOM

MOM(Message Oriented Middleware)是面向消息的中间件,可以变向理解为:


消息传递和消息排队模型


。使用消息传送提供者来协调消息传送操作。MOM 需要提供 API 和管理工具。客户端使用api调用,把消息发送到由提供者管理的目的地。在发送消息之后,客户端会继续执行其他工作,并且在接收方收到这个消息确认之前,提供者一直保留该消息 (摘自:

百度百科

)

MOM通过提供


消息传递





消息排队


模型,它可在分布环境下扩展进程间的通信,并支持多基于 MOM 的系统通讯协议、语言、应用程序、硬件和软件平台。时下流行的MOM中间件产品有IBM的MQSeries、 BEA的MessageQ等。

3.MOM的特点

1.消息异步接受,发送者不需要等待消息接受者的响应;

2.消息可靠接受,确保消息在中间件中的可靠保存。只有接受方收到后,消息才可以被删除。

4.JMS和MOM的关联



在JMS规范出现之前,由于当时需求的出现,很多产商都开发了自己独有的消息中间件。如果我在一个系统中引入了多个消息中间件,但是由于他们都是各自一套,没有一个统一的规范,从而在当时暴露除了许多问题,比如:多个消息中间件之间的数据传递问题等

在这种情况下,2001年6月JMS规范也就诞生了。JMS是一个在 Java标准化组织(JCP)内开发的标准,是Java平台上有关面向消息中间件(MOM)的技术规范。







JMS规范最初的开发目的,是为了将Java应用程序能够访问现有的MOM系统,是为了已有的MOM系统而制定的。但是在引入规范之后,它便被许多现有的MOM供应商所采用的。

5.JMS的体系结构

6.JMS常见基本概念



1.消息传递域





JMS规范中定义了两种消息传递域:

①点对点(point-to-point)消息传递域

②PUB/SUB消息传递域(


pub


lish/


sub


scribe 发送/订阅),请看如下介绍:


点对点消息传递域




特点:



1.每个消息只能有一个消费者;

2.消息的生产者和消费者之间没有时间上的相关性。无论消费者在生产者发送消息时是否处于运行状态,都可以提取消息。


PUB/SUB消息传递域


特点:



1.每个消息可以有多个消费者;

2.生产者和消费者之间有时间上的相关性。订阅一个主题的消费者


只能消费自它订阅之后发布的消息


,订阅之前发布的消息他是收不到的,类似于微信入群操作;

3.


JMS规范允许客户创建持久订阅


,这在一定程度上降低了时间上的相关性要求。持久订阅允许消费者消费在它(消费者)未激活启动之前发送的消息。


2


.消息结构组成





JMS消息由以下三部分组成:

消息头、属性和消息体



消息头

消息头包含消息的


识别信息





路由信息


,消息头包含的一些属性如下:

属性名

属性名称

属性介绍

JMSDestination
消息发送的目的地 主要是指Queue和Topic

JMSDeliveryMode
传送模式 有两种:


持久模式





非持久模式


。一条持久性的消息,如果在JMS提供者出现故障,JMS消息不会丢失,它会在服务器恢复之后继续传递。一条非持久性的消息最多会传递一次,这就意味着服务器出现故障,该消息永久丢失。

JMSExpiration
消息过期时间 等于Destination的send方法中的timeToLive值加上发送时刻的GMT时间值。如果timeToLive值等于零,则JMSExpiration被设置为零,表示该消息永不过期。如果发送后,在消息过期时间之后消息还没有被发送到目的地,则该消息被清除。

JMSPriority
消息优先级 从0-9十级,0-4是普通消息,5-9是加急消息。JMS不要求JMS provider严格按照这十个优先级发送消息,但必须保证加急消息要优先于普通消息到达目的地。默认是4级。

JMSMessageId
消息ID 唯一识别每个消息的标志

JMSTimestamp
消息发送->接收的时间差 一个JMS provider在调用send()自动设置的

JMSCorrelationId
用来连接到另外一个消息

JMSReplyTo
提供本消息回复消息的目的地

JMSType
消息类别的识别符

JMSRedelivered
如果一个客户端端收到了设置了JMSRedelivered属性的消息,则表示客户端可能在早些时候曾经收到过该消息,但并没有被签收(acknowledge)。如果该消息重新发送,JMSRedelivered = true 反之 JMSRedelivered = false



属性

包含以下三种类型的属性:


1.应用程序设置或添加的属性

Message.setStringProperty(key,value)


在发送端,定义消息属性

message.setStringProperty("xxx","xxx");


在接收端,接受数据:

try {
    Enumeration enumeration = message.getPropertyNames(); 
    while (enumeration.hasMoreElements()) { 
        String name = enumeration.nextElement().toString(); 
        System.out.println("name:" + name + ":" + message.getStringProperty(name)); 
    }
} catch (JMSException e) {
    e.printStackTrace();
}


2.JMS定义的属性


JMS定义的属性如下:


属性名

属性介绍

JMSXUserID
发送消息的用户标识。发送时提供商设置

JMSXAppID
发送消息的应用标识。发送时提供商设置

JMSXDeliveryCount
转发消息重试次数。第一次是1,第二次是2,……,发送时提供商设置

JMSXGroupID
消息所在消息组的标识,客户端设置

JMSXGroupSeq
组内消息的序号,第一个是1,第二个是2,……,客户端设置

JMSXProducerTXID
产生消息的事务的事务标识,发送时提供商设置

JMSXConsumerTXID
消费消息的事务的事务标识,接收时提供商设置

JMSXRcvTimestamp
JMS转发消息到消费者的时间,接收时提供商设置

JMSXState
假定存在一个消息仓库,它储存了每个消息的单独拷贝,且这些消息从原始消息发送开始,每个拷贝的状态有:1(等待)、2(准备)、3(到期)或4(保留)。由于状态与生产者和消费者无关,所以它不是由它们来提供,它只和在仓库中查找消息相关,因此JMS消息没有提供相关的API,所以由提供商设置

使用”JMSX”作为属性的前缀,通过如下代码,可以返回所有支持的JMSX的属性名称

try {
    Enumeration names = connection.getMetaData().getJMSXPropertyNames();
    while(names.hasMoreElements()){
        String name = (String)names.nextElement();
        System.out.println(name);
    }
    
} catch (JMSException e) {
    e.printStackTrace();
}


3.JMS提供商(Provider)特定的属性



消息体





消息体就是我们需要传递的消息内容,JMS API 定义了 5 种消息体格式,可以使用不同形式发送接收数据,并可以兼容现有的消息格式,具体如下:


消息格式

格式介绍

TextMessage
java.lang.String 对象,如 xml 文件内容

MapMessage
k/v键值对的集合,key为 String 对象,value 类型可以是 Java 任何基本类型

BytesMessage
字节流

StreamMessage
Java 中的输入输出流

OpbjectMessage
Java 中的可序列话对象
Message(这个在5种之外) 没有消息体,只有消息头和属性

至此,JMS基本概念介绍完了,可能看着会有点懵圈,这些只是内部的一些属性特质,你只需要简单了解一下即可。

7.JMS 的事务性会话和非事务性会话

JMS规范中,Session接口提供了commit 和 rollback 两种方法,分别用于事务的提交和回滚。



事务提交:


意味着生产的所有消息被发送,消费的所有消息被确认;



事务回滚:


意味着生产的所有消息被销毁,消费的所有消息被恢复并重新提交,除非它们已经过期。

事务性的会话,总是牵涉在事务处理中,commit 或 rollback 方法一单被调用,则意味着一个事务的结束,另一个事务的开始。关闭事务性会话,将会回滚其中的事务。


● 如何设置当前的会话是事务性还是非事务性

通过在创建 session 的时候,使用 true 或者 false 来决定当前的会话是 事务性 还是 非事务性 操作,设置如下:

//此处,通过true或者false来确定操作时 事务性 or 非事务性(第二个参数,下面会讲)
connection.createSession(Boolean.TRUE,Session.AUTO_ACKNOWLEDGE);


● 事务性会话

在事务状态下进行发送操作,消息并未真正投递到中间件,而


只有进行 session.commit 操作之后,消息才会被真正的发送到中间件。


然后才是消费者进行消费处理。


如果是调用 session.rollback 操作,则说明当前事务期间内所发送的消息都会被取消掉

事务性会话中,消息的确认是自动进行,也就是通过session.commit()操作之后,消息便会被自动确认。

还要注意一点就是:事务性会话中,


必须保证 发送端 和 消费端 都是事务性会话。


● 非事务性会话

在非事务性会话中,消息何时被确认取决于创建会话时的


应答模式


(acknowledgement mode)。该应答模式有如下三个可选项:


Session.AUTO_ACKNOWLEDGE

当客户成功的从 receive 方法返回的时候,或者从 MessageListener.onMessage 方法成功返回的时候,会话自动确认客户收到消息


Session.CLIENT_ACKNOWLEDGE

当客户通过调用消息的 acknowledge 方法,来确认客户真正收到消息。该模式下,确认是在会话层上进行的。确认一个被消费的消息,将自动确认所有已被会话消费的消息。比如:有个for循环,如果一个消费者消费了10个消息,但是在 i==8 的时候,调用了 message.acknowledge()方法进行确认,看着是他只确认了第8个消息。但是,你会发现0~8个消息都会被确认。


Session.DUPS_ACKNOWLEDGE

消息延迟确认。指定消息提供者,在消息接收者没有确认发送时,重新发送消息。这种模式不在乎接收者收到重复的消息。


事务 | 确认机制

Producer(生产者)

Customer(消费端)

TRUE

&&


AUTO_ACKNOWLEDGE

session.commit() session.commit()

FALSE

&&


AUTO_ACKNOWLEDGE

不需要commit() 不需要commit()

FALSE

&&


CLIENT_ACKNOWLEDGE

发送端不需要设置 消费端设置,需要手动签收(message.acknowledge()手动签收)

FALSE

&&


DUPS_OK_ACKNOWLEDGE

延迟确认

8.JMS消息的可靠性机制

JMS机制消息的可靠性,主要有两种方式:①消息确认机制   ②消息的持久化存储机制



消息确认机制

理论上来说,我们需要保证消息中间件上的消息,只有被消费者确认过以后,才会被签收。相当于我们寄一个快递出去,收件人没有收到快递,就认为这个包裹还是属于待签收状态,这样才能保证包裹能够安全送达到收件人的手里。消息中间件和寄快递的道理也是一样样的。

消息的消费,通常包含以下3个阶段:①客户接收消息   ②客户处理消息   ③消息被确认。

消息去人机制,在本文

『7.JMS 的事务性会话和非事务性会话』

中有介绍到,你可以向上查看。



消息持久化存储机制

消息的持久化存储,也就是消息发送到Broker上以后,如果Broker出现故障宕机了,那么存储在Broker上的消息不应该丢失。可以通过如下代码来设置


消息发送端


的持久化和非持久化特性,如下分情况介绍:

MessageProducer producer = session.createProducer(destination);
//DeliveryMode.NON_PERSISTENT--持久化
//DeliveryMode.NON_PERSISTENT--非持久化
producer.setDeliveryMode(DeliveryMode.PERSISTENT);


①非持久消息

对于非持久的消息,JMS消息发送端 不会将它存储到文件/数据库等稳定的存储介质中。也就是说

非持久化消息只是存储在内存中

,如果 JMS消息发送端 宕机了,那么内存中的非持久化消息也会丢失。


②持久化消息

对于持久化消息,消息提供者会使用


存储-转发机制


,先将消息存储到稳定的介质中,等效洗发送成功后,再做删除操作。如果 JMS消息发送端 挂掉了,那么这些为发送的消息也并不会丢失。等 JMS消息发送端 恢复正常后,会再次重新去读取这些消息,并传送给对应的消息消费者。

END



版权声明:本文为lzb348110175原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。