WebLogic JMS 概述
企业消息传递系统使得应用程序能够通过消息的交换与其他系统之间进行通信。消息是包含协调不同应用程序之间通信所需信息的请求、报告和/或事 件。消息提供了提取级别,使您能够从应用程序代码中分离出有关目标系统的详细信息。Java 消息服务 (JMS) 是用于访问企业消息传递系统的标准 API。尤其是 JMS:
使得共享消息传递系统的 Java 应用程序能够交换消息
通过提供用于创建、发送和接收消息的标准接口简化了应用程序开发
如图中所说明,WebLogic JMS 接受来自生成器应用程序的消息,然后将其传递给使用者应用程序。
WebLogic JMS 是企业级消息传递系统,紧密集成于 WebLogic Server 平台之中。它完全支持 JMS Specification,还提供了很多超出标准JMS API的WebLogic JMS扩展。
WebLogic JMS体系架构
主要组件:
JMS 服务器,承载定义的模块组和 WebLogic Server 实例上驻留的任何关联的持久性存储。
JMS 模块,由符合 weblogic-jmsmd.xsd Schema 的 XML 文档定义,其中包含配置资源(例如队列、主题和连接工厂)。
客户端 JMS 应用程序,它们生成消息以传递给目标,或使用来自目标的消息。
JNDI(Java 命名和目录接口),提供资源查找工具。
WebLogic 持久性存储(文件存储或可通过 JDBC 访问),用于存储持久性消息数据。
消息传递模型
JMS 支持两种消息传递模型:点对点(point-to-point,简称 PTP)和发布/订阅(publish/subscribe,简称pub/sub)。这两种消息传递模型非常相似,只有以下区别:
PTP 消息传递模型支持一条消息仅传递给一个接收方。
Pub/sub 消息传递模型支持一条消息传递给多个接收方。
每种模型都通过扩展公用基类的类来实现。例如,PTP 类 javax.jms.Queue 和 pub/sub 类 javax.jms.Topic 都扩展 javax.jms.Destination 类。
点对点消息传递
通过点对点 (PTP) 的消息传递模型,一个应用程序可以向另一个应用程序发送消息。PTP消息传递应用程序使用命名队列接发消息。队列发送方(生成器)向特定队列发送消息。队列接收方(使用者)从特定队列接收消息。
下图说明 PTP 消息传递。
一个队列可以关联多个队列发送方和接收方,但一条消息仅传递给一个队列接收方。
如果多个队列接收方正在监听队列上的消息,WebLogic JMS 将根据“先来者优先”的原则确定由哪个队列接收方接收下一条消息。如果没有队列接收方在监听队列,消息将保留在队列中,直至队列接收方连接队列为止。
发布/订阅消息传递
通过发布/订阅 (pub/sub) 消息传递模型,应用程序能够将一条消息发送到多个应用程序。Pub/sub 消息传递应用程序可通过订阅主题来发送和接收消息。主题发布者(生成器)可向特定主题发送消息。主题订阅者(使用者)从特定主题获取消息。
下图说明 pub/sub 消息传递。
如果多个队列接收方正在监听队列上的消息,WebLogic JMS 将根据“先来者优先”的原则确定由哪个队列接收方接收下一条消息。如果没有队列接收方在监听队列,消息将保留在队列中,直至队列接收方连接队列为止。
发布/订阅消息传递
通过发布/订阅 (pub/sub) 消息传递模型,应用程序能够将一条消息发送到多个应用程序。Pub/sub 消息传递应用程序可通过订阅主题来发送和接收消息。主题发布者(生成器)可向特定主题发送消息。主题订阅者(使用者)从特定主题获取消息。
下图说明 pub/sub 消息传递。
与PTP消息传递模型不同,pub/sub消息传递模型允许多个主题订阅者接收同一条消息。JMS 一直保留消息,直至所有主题订阅者都收到消息为止。
Pub/Sub消息传递支持持久订阅者,您可以为主题订阅者分配名称,然后将该名称与某个用户或应用程序关联起来。
消息持久性
根据 JMS 规范的“Message Delivery Mode”部分,消息可以指定为持久性消息或非持久性消息:
可以保证持久性消息传递“一次且仅一次”。消息不会因 JMS 提供程序失败而丢失,也不会传递两次。除非消息已经安全写入文件或数据库,否则视为消息未传送。WebLogic JMS 向 WebLogic 持久性存储(基于磁盘的文件或可通过JDBC访问的数据库)写入持久性消息,可选择在配置过程中由每个JMS服务器确定存储位置。
不存储非持久性消息。除非JMS提供程序失败(这可能引起消息丢失),否则仅保证它们传递“最多一次”,不会传递两次。如果连接关闭或恢复,则将重新传递所有未经确认的非持久性消息。非持久性消息一旦经过确认,则不会重新传递。
JMS API
要创建 JMS 应用程序,请使用 javax.jms API。通过该 API,您可以创建连接JMS、发送和接收消息所需要的类对象。所创建的 JMS 类接口将用作子类,以便提供队列特定或主题特定的版本的公用父类。
下表列出常见的JMS 类。
Pub/Sub消息传递支持持久订阅者,您可以为主题订阅者分配名称,然后将该名称与某个用户或应用程序关联起来。
消息持久性
根据 JMS 规范的“Message Delivery Mode”部分,消息可以指定为持久性消息或非持久性消息:
可以保证持久性消息传递“一次且仅一次”。消息不会因 JMS 提供程序失败而丢失,也不会传递两次。除非消息已经安全写入文件或数据库,否则视为消息未传送。WebLogic JMS 向 WebLogic 持久性存储(基于磁盘的文件或可通过JDBC访问的数据库)写入持久性消息,可选择在配置过程中由每个JMS服务器确定存储位置。
不存储非持久性消息。除非JMS提供程序失败(这可能引起消息丢失),否则仅保证它们传递“最多一次”,不会传递两次。如果连接关闭或恢复,则将重新传递所有未经确认的非持久性消息。非持久性消息一旦经过确认,则不会重新传递。
JMS API
要创建 JMS 应用程序,请使用 javax.jms API。通过该 API,您可以创建连接JMS、发送和接收消息所需要的类对象。所创建的 JMS 类接口将用作子类,以便提供队列特定或主题特定的版本的公用父类。
下表列出常见的JMS 类。
JMS类 | 描述 |
ConnectionFactory
|
|
Connection
|
|
Session
|
|
Destination
|
|
MessageProducer 和 MessageConsumer
|
|
Message
|
|
ServerSessionPoolFactory 1
|
|
ServerSessionPool 2
|
|
ServerSession 3
|
|
ConnectionConsumer 4
|
|
1支持用于并发地处理多个消息的可选 JMS 接口。
2支持用于并发地处理多个消息的可选 JMS 接口。
3支持用于并发地处理多个消息的可选 JMS 接口。
4支持用于并发地处理多个消息的可选 JMS 接口。
ConnectionFactory
ConnectionFactory封装 配置信息,支持JMS应用程序创建Connection。连接工厂支持并发使用,可以使多个线程同时访问该对象。可以使用WebLogic JMS提供的预配置默认连接工厂,或配置一个和多个连接工厂,从而使用适合您应用程序的预定义特性创建连接。
WebLogic JMS 定义了两个默认连接工厂,可以使用以下 JNDI 名查找这些连接工厂:
weblogic.jms.ConnectionFactory
weblogic.jms.XAConnectionFactory
两者之间的主要差别在于:用于支持 JTA 事务的“已启用 XA 连接工厂”特性的默认值不同,如下表所示。
默认连接工厂. . . | “已启用 XA 连接工厂”设置是. . . |
weblogic.jms.ConnectionFactory
|
|
weblogic.jms.XAConnectionFactory
|
|
对于使用JTA用户事务的JMS应用程序,XA 工厂是必需的,但是对于事务处理会话,则不是必需的。
如果默认工厂设置不适合您的应用程序,您只需要配置一个用户定义的连接工厂。
使用默认连接工厂时的另外一点区别是,您无法控制可能部署连接工厂的WebLogic Server实例的目标。但可以基于每台服务器禁用默认连接工厂。
要在特定独立服务器上、群集中的特定服务器上或者在整个群集上部署连接工厂,必须配置新的连接工厂并指定适当的目标,如配置和部署连接工厂中所说明。
注意:为了实现向后兼容,WebLogic JMS 仍支持两种不赞成使用的默认连接工厂。这两种连接工厂的 JNDI 名是:javax.jms.QueueConnectionFactory 和 javax.jms.TopicConnectionFactory。
系统管理员可以定义和配置一个或多个连接工厂以创建具有预定义特性的连接,WebLogic Server 会在启动时将它们添加到 JNDI 空间中。然后应用程序使用 WebLogic JNDI 检索连接工厂。任何用户定义的连接工厂都必须具有唯一的名称。
系统管理员可以以群集为目标或以群集中的一个或多个服务器实例为目标,在群集范围内建立从群集中任意服务器乃至 JMS 目标的透明访问。这样,每一个连接工厂都可以部署到多个 WebLogic Server 实例。
ConnectionFactory 类不定义任何方法;但其子类会定义适用于各个消息传递模型的方法。连接工厂支持并发使用,可以使多个线程同时访问该对象。
下表描述 ConnectionFactory 子类。
子类. . . | 消息传递模型. . . | 用于创建. . . |
QueueConnectionFactory
|
|
QueueConnection
|
TopicConnectionFactory
|
|
TopicConnection
|
Connection
Connection 代表应用程序和消息传递系统之间的开放式通信通道,用于创建生成消息或使用消息的Session。连接创建用于管理应用程序和JMS之间的消息传递活动的服务器端和客户端对象。连接还可以提供用户身份验证。
Connection 由通过 JNDI 查找获得的 ConnectionFactory 创建。
由于与用户身份验证和建立通信关联的资源 开销比较大,因此多数应用程序为所有消息传递建立一个连接。在 WebLogic Server 中,JMS 流量通过客户端与服务器的连接上的其他 WebLogic 服务进行多路传输。无需再为 JMS 创建其他 TCP/IP 连接。Servlet 和其他服务器端对象可能还包含 JMS 连接。
连接支持并发使用,可以使多个线程同时访问该对象。
注意:对于本版本,可以使用 JMS v1.1 规范的连接对象,或选择使用子类。
子类. . . | 消息传递模型. . . | 用于创建. . . |
QueueConnection
|
|
QueueSessions ,包括由 QueueConnectionFactory 创建的、与 JMS PTP 提供程序之间的连接。
|
TopicConnection
|
|
TopicSessions ,包括由 TopicConnectionFactory 创建的、与 JMS pub/sub 提供程序之间的连接。
|
Session
Session 对象定义生成及使用消息的顺序,并可创建多个消息生成器和消息使用者。同样的线程可以用于生成和使用消息。如果应用程序希望使用单独的线程生成和使用消息,应用程序应针对每个功能创建独立的会话。
Session 由 Connection 创建。
非事务处理会话
在非事务处理会话中,创建会话的应用程序会在下表中定义的五个确认模式中任选其一。
确认模式 | 描述 | ||
AUTO_ACKNOWLEDGE
|
Session 对象即确认消息接收。
|
||
CLIENT_ACKNOWLEDGE
|
Session 对象依赖于应用程序对已收到的消息调用确认方法。一旦调用该方法,会话将确认所有自上次确认后收到的消息。
|
||
DUPS_OK_ACKNOWLEDGE
|
Session 对象即确认消息接收,允许重复确认。
|
||
NO_ACKNOWLEDGE
|
NO_ACKNOWLEDGE 会话的消息将立即从服务器中删除。此模式下接收的消息不可恢复,因此,消息可能会丢失,也可能在第一次传递消息失败后传递重复消息。
|
||
MULTICAST_NO_ACKNOWLEDGE
|
MULTICAST_NO_ACKNOWLEDGE 会话的消息与 NO_ACKNOWLEDGE 模式具有相同特征,如前所述。
|
事务处理会话
在事务处理会话中,在任意给定时刻,只有一个事务处于活动状态。事务期间发送或接收的任意数量的消息将视为原子单元。
创建事务处理会话时,将忽略确认模式。应用程序提交事务时,应用程序在事务期间接收的所有消息将由消息传递系统进行确认,应用程序发送的消息也将被接收以进行传递。如果应用程序发生事务回滚,则应用程序在该事务期间接收的消息不会经过确认,其发送的消息也将被放弃。
JMS 可以通过其他 Java 服务参与分布式事务,例如 EJB 会使用 Java 事务 API (JTA)。事务处理会话不支持此功能,因为事务仅限于访问与该会话关联的消息。
Destination
Destination 对象可以是队列或主题,它封装特定提供程序的地址语法。JMS 规范中没有定义标准地址语法,因为各个提供程序之间的语法有所不同。与连接工厂类似,管理员定义和配置目标,然后WebLogic Server会在启动期间将目标添加到 JNDI 空间中。应用程序还可以创建临时目标,临时目标的生存期仅限于其创建时所位于的 JMS 连接的持续时间。
注意:管理员还可以配置分布式目标,即一组目标(队列或主题),但可以视作单个逻辑目标供客户端访问。
在客户端,Queue和Topic对象是服务器上的对象的句柄。它们的方法仅返回它们的名称。要访问它们以进行消息传递,需要创建与其连接的消息生成器和使用者。
目标支持并发使用,可以使多个线程同时访问该对象。JMS Queues和Topics扩展 javax.jms.Destination。
注意:对于本版本,可以使用 JMS v1.1 规范的目标对象,或选择使用子类。
下表描述 Destination 子类。
子类 | 消息传递模型 | 管理下列消息 |
Queue
|
|
|
TemporaryQueue
|
|
|
Topic
|
|
|
TemporaryTopic
|
|
|
注意:应用程序可以选择在队列会话中创建 QueueBrowser 对象以浏览该队列。在创建队列浏览器时,此对象将为队列中的消息生成快照。应用程序可以查看队列中的消息,但并不等于消息是可读的,也不能从队列中删除消息。
分布式目标
分布式目标资源是可作为单个逻辑目标供客户端进行访问的一组目标(队列或主题),例如,分布 式主题有其各自的 JNDI 名称。通常,集合成员分布在群集中的多个服务器内,而且每个成员都分属于不同的JMS服务器。使用分布式目标的应用程序比使用独立目标的应用程序具有更高 的可用性,因为WebLogic JMS为群集中分布式目标的成员提供了负载平衡和故障转移。
MessageProducer和MessageConsumer
MessageProducer 向队列或主题发送消息。MessageConsumer从队列或主题接收消息。消息生成器和使用者相互独立运行。无论是否已经创建消息使用者或使用者是否在等待消息,消息生成器都会生成和发送消息,反之亦然。
Session创建MessageProducers和MessageConsumers,它们将连接到队列和主题上。将创建消息发送方和接收方对象,并用作MessageProducer 和 MessageConsumer 类的子类。
下表描述 MessageProducer 和 MessageConsumer 子类。
子类 | 消息传递模型 | 管理下列消息 |
QueueSender
|
|
|
QueueReceiver
|
|
JMS 点对点提供程序。
|
TopicPublisher
|
|
|
TopicSubscriber
|
|
JMS pub/sub 提供程序发送消息。
|
如图点对点 (PTP) 消息传递所示,PTP 模型允许多个会话接收来自同一个队列的消息。但是,消息只能传递给一个队列接收方。存在多个队列接收方时,WebLogic JMS 将根据“先来者优先”的原则定义下一个接收消息的队列接收方。
如图发布/订阅 (Pub/Sub) 消息传递所示,pub/sub 模型允许向多个主题订阅者传递消息。主题订阅者可以为持久订阅者或非持久订阅者,如设置持久订阅中所述。
应用程序可以使用同一个 JMS 连接发布并订阅单个主题。因为主题消息将传递至所有订阅者,所以应用程序会接收到其自身发布的消息。为防止客户端接收它们自己发布的消息,JMS 应用程序可以在主题订阅者上设置 noLocal 特性
Message
Message 封装应用程序之间交换的信息。这些信息包括三个组件:消息头字段、消息属性字段、消息正文
消息头字段
每个JMS消息包含一个默认包含的标准头字段集,可供消息使用者使用。某些字段可由消息生成器设置。
下表描述消息头中的各个字段,显示每个字段应该定义的值。
字段 | 描述 | 定义者 |
JMSCorrelationID
|
JMSMessageID (此表稍后描述)、应用程序特定的字符串或一个 byte[] 数组。JMSCorrelationID 用于关联消息,在 send() 之前,应用程序将直接在消息上设置此字段。
JMSCorrelationID 字段存储您选择的任意字符串,将一系列消息通过应用程序确定的某些值链接起来。
|
|
JMSDeliveryMode
|
PERSISTENT 或 NON_PERSISTENT 消息传递。此字段设置在生成器上,或设置为应用程序在 send() 之前发送的参数。
send() 操作已成功。对于持久性消息,可以保证传递至少一次。
producer.send() 调用所覆盖,直接在消息上设置此值没有任何作用。通过向 producer.send() 传递的消息,或当使用者接收到消息时,可以查询生成器设置的值。
|
send() 方法
|
JMSDeliveryTime
|
send() 之前将设置此字段,它依赖于生成器上设置的 timeToDeliver 。
|
send() 方法
|
JMSDestination
|
send() 之前发送的参数。
producer.send() 调用覆盖,直接在消息上设置此值没有任何作用。通过向 producer.send() 传递的消息,或当使用者接收到消息时,可以查询生成器设置的值。收到消息时,它的目标值必须等于发送它时为它分配的值。
|
send() 方法
|
JMSExpiration
|
send() 之前将设置此字段。此字段依赖于生成器上设置的 timeToLive ,或用作应用程序向 send() 发送的参数。
JMSExpiration 的计算值。如果应用程序指定生存时间为 0,则将 JMSExpiration 设置为 0,这表明消息永不过期。
|
send() 方法
|
JMSMessageID
|
send() 在内部设置。
JMSMessageID 均以“ID: ”前缀开始。
producer.send() 调用覆盖,直接在消息上设置此值没有任何作用。通过向 producer.send() 传递的消息,或当使用者接收到消息时,可以查询生成器设置的值。收到消息时,消息中包含提供程序分配的值。
|
send() 方法
|
JMSPriority
|
send() 之前发送的参数。
|
send() 方法
|
JMSRedelivered
|
|
|
JMSReplyTo
|
send() 之前直接在消息上设置此字段。
JMSCorrelationID 头字段,以协调请求/响应消息。
JMSReplyTo 字段并不能保证响应;它只是使接收应用程序能够响应而已。
|
|
JMSTimestamp
|
|
|
JMSType
|
send() 之前直接在消息上设置。
JMSType 字段保存消息类型 ID,该 ID 可以提供对存储的类型定义的访问。
|
|
消息属性字段
消息的属性字段包含发送应用程序所添加的头字段。这些属性是标准Java 名/值对。属性名称必须符合 javax.jms.Message Javadoc 中定义的消息选择器语法规范。以下值有效:boolean、byte、double、float、int、long、short 和 String。
WebLogic Server 支持使用下列 JMS (JMSX) 定义属性,如 JMS 1.1.规范所定义:
类型 | 描述 |
尽管消息属性字段可以用于各种应用程序特定的用途,但 JMS 提供这些属性主要是为了在消息选择器中使用。您可以决定如何在您的环境中使用 JMS 属性。您可以选择在某些消息中包含这些属性,而在其他消息中忽略这些属性,这取决于您的处理条件。
消息正文
消息正文包含从生成器传递给使用者的内容。
下表描述 JMS 定义的消息类型。所有消息类型扩展 javax.jms.Message,其中包括消息头和属性,但不包括消息正文。
类型 | 描述 |
ServerSessionPoolFactory
注意:会话缓冲池和连接使用者配置对象在此版本 WebLogic Server 中已不赞成使用。它们不是 J2EE 规范的必需部分,不支持 JTA 用户事务,并且已基本被消息驱动 Bean (MDB) 替代,MDB 更简单、易于管理且功能更强大。
服务器会话缓冲池 WebLogic 特定的 JMS 功能,使您能够并发处理消息。可以使用服务器会话缓冲池工厂创建服务器端 ServerSessionPool
WebLogic JMS 定义一个 ServerSessionPoolFactory 对象,默认为:weblogic.jms.extensions.ServerSessionPoolFactory:<name>,其中 <name> 指定会话缓冲池创建至的 JMS 服务器的名称。WebLogic Server 在启动期间向 JNDI 空间中添加默认服务器会话缓冲池工厂,然后应用程序使用 WebLogic JNDI 检索服务器会话缓冲池工厂。
ServerSessionPool
ServerSessionPool 应用程序服务器对象提供服务器会话缓冲池,连接使用者可以在其中进行检索,以便并发地处理消息。
ServerSessionPool 由通过 JNDI 查找获得的 ServerSessionPoolFactory 对象创建。
ServerSession
通过提供创建、发送和接收消息的上下文,ServerSession 应用程序对象,使您能够将线程与 JMS 会话关联起来。
ServerSession 由 ServerSessionPool 对象创建。
ConnectionConsumer
ConnectionConsumer 对象使用服务器会话处理接收的消息。如果消息流量很大,连接使用者可以加载具有多个消息的每个服务器会话,以使线程上下文切换最小化。
ConnectionConsumer 由 Connection 对象创建。
注意:连接使用者监听器与服务器运行在同一台 JVM 上。
参考至:http://edocs.weblogicfans.net/wls/docs92/jms/fund.html
本文原创,转载请注明出处、作者
如有错误,欢迎指正
邮箱:czmcj@163.com
本文原创,转载请注明出处、作者
如有错误,欢迎指正
邮箱:czmcj@163.com
作者:czmmiao 文章出处:http://czmmiao.iteye.com/blog/1625494