1.JMS规范介绍

目录

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消息传递域(publish/subscribe 发送/订阅),请看如下介绍:

    点对点消息传递域

      特点:

        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消费消息的事务的事务标识,接收时提供商设置
JMSXRcvTimestampJMS转发消息到消费者的时间,接收时提供商设置
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 种消息体格式,可以使用不同形式发送接收数据,并可以兼容现有的消息格式,具体如下:

消息格式格式介绍
TextMessagejava.lang.String 对象,如 xml 文件内容
MapMessagek/v键值对的集合,key为 String 对象,value 类型可以是 Java 任何基本类型
BytesMessage字节流
StreamMessageJava 中的输入输出流
OpbjectMessageJava 中的可序列话对象
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_ACKNOWLEDGEsession.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

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

扛麻袋的少年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值