消息驱动的
EJB
消息驱动
EJB
的生命周期和空闲缓冲池
图
7-1 MDB
生命周期
MDB
和空闲缓冲池
WebLogic Server
维护有一个空闲缓冲池,其中驻留了当前未向请求提供服务的
MDB
实例。为获得最佳的响应时间和吞吐量,可以将
WebLogic Server
配置为在启动时填充缓冲池,方法是在
Bean
的
initial-beans-in-free-pool
元素(位于
weblogic-ejb-jar.xml
中)中指定所需的量。默认情况下,
initial-beans-in-free-pool
的值为
0
。
管理员可以在需要时通过管理控制台来初始化空闲缓冲池。有关信息,请参阅
“
管理控制台联机帮助
”
中的
初始化EJB的空闲BEan缓存和缓存池。
空闲缓冲池中的
MDB
实例数受
weblogic-ejb-jar.xml
中
的
max-beans-in-free-pool
元素的值和可用内存的限制。
max-beans-in-free-pool
元素的值由下列规则(按优先顺序列出)确定:
1.
如果定义了自定义
ExecuteThreadPool
,
MDB
线程的数目将等于
ExecuteThreadCount
的值。
2.
如果定义的自定义
WorkManager
具有
max-threads-constraint
,则
MDB
线程的数目将等于
max-threads-constraint
的值。
3.
如果禁用了
autotune
选项,则
MDB
线程的数目将等于以下值:
(
ExecuteThreadCount
/2) + 1
4.
MDB
线程的数目等于
16
(此为默认值)。
注意:
|
由于向后兼容的原因,使用
WebLogic Server 8.1
版本中可用的执行队列样式线程管理成为可能。在该上下文中,线程缓冲池大小对空闲缓冲池中
MDB
实例最大数量的影响各不相同,这取决于
MDB
使用默认的执行队列,还是配置为使用其他执行队列。
|
可以将
WebLogic Server
配置为删除在缓冲池中保持未使用状态达到一定时间的消息驱动
Bean
,该时间由 pool
元素中的
idle-timeout-seconds
元素指定。如果
Bean
在
idle-timeout-seconds
中指定的时间量内在缓冲池中一直处于未使用状态,则将其从缓冲池中删除,直到缓冲池中的
Bean
数达到
initial-beans-in-free-pool
中指定的数字;缓冲池中的
Bean
数永远不会低于
initial-beans-in-free-pool
中指定的数字。
MDB
处理来自
JMS
目标的消息。在收到消息后,
EJB
容器将调用
MDB
的
onMessage()
方法,该方法中包含
EJB
执行的业务逻辑。在调用
MDB
的
onMessage()
方法时:
§
如果空闲缓冲池中有可用的
Bean
实例,
WebLogic Server
将使用该实例。这样可提供最佳响应时间,因为请求可以立即得到处理,而无需等待新实例的创建。
§
如果空闲缓冲池中没有
Bean
实例,
WebLogic Server
将初始化一个实例,其方式是调用:
·
MDB
的构造方法
·
MDB
的
ejbCreate()
方法
·
MDB
的
setMessageDrivenContext()
方法,用于将该实例与某个容器上下文相关联。该
Bean
将可以使用该上下文中的元素,如使用消息驱动 Bean 上下文
中所述。
§
如果一个
MDB
的所有实例都处于活动状态,并且数目已达到
max-beans-in-free-pool
的值,则
JMS
onMessage()
请求将被阻塞,直至某一活动的
MDB
完成方法调用为止。应用程序将一直等待,直至事务超时或缓冲池中已有的
Bean
实例变为可用。
在
MDB
实例的
onMessage()
方法返回后,请求即完成了,且该实例将会置于空闲缓冲池中以便重用,假定这样做不会导致超过
max-beans-in-free-pool
的值。
MDB
和并发处理
无论是主题还是队列,
MDB
都支持并发处理。有关主题和队列的详细信息,请参阅
MDB和消息传递模型。
在
weblogic-ejb-jar.xml
中 max-beans-in-free-pool
元素的默认设置为
1,000
,可以提供最大的并存性。更改此设置的唯一原因将是限制并行使用者的数目。
部署到服务器实例的每个
MDB
都将创建单个
JMS
连接。
在基于队列的
JMS
应用程序(点对点模型)中,每个
MDB
实例都有其自己的会话。
在基于主题的
JMS
应用程序(发布
/
订阅模型)中,一个
MDB
的所有本地实例都共享一个
JMS
会话。一条给定的消息会被分发给多个
MDB
,每个订阅的
MDB
都将收到一个副本。如果部署了多个
MDB
来监听同一主题,则每个
MDB
都会收到每条消息的副本。每条消息都将由监听该主题的每个
MDB
的一个实例进行处理。
MDB
和消息传递模型
WebLogic Server MDB
可用于点对点(队列)或发布
/
订阅(主题)消息传递模型。有关这些模型的详细信息,请参阅
“WebLogic JMS
编程
”
中的
了解 WebLogic JMS
。
下列部分描述点对点和发布
/
订阅消息传递应用程序之间的主要区别。
点对点(队列)模型:每个监听器处理一条消息
在点对点模型中,来自
JMS
队列的每条消息将由一个
MDB
监听器选取并留在队列中,直至得到处理。如果该
MDB
停用,该消息将保留在队列中,等待该
MDB
重新激活。
例如
:某部门必须更新其后端存货系统,以反映一天中所销售的商品数。每条指出存货减少的消息必须进行处理,且只能处理一次。对于这些消息,不必在它们生成时便立即对其进行处理,也不必遵循任何特定的处理顺序,但必须使每条消息都得到处理。
图 7-2
说明了点对点的应用程序。每条消息都由
MDB_A
的单个实例进行处理。消息
“M1”
由
MDB_A(1)
处理,
“M2”
由
MDB_A(2)
处理,
“M3”
由
MDB_A(3)
处理。
图
7-2
点对点模型
发布
/
订阅(主题)模型
在发布
/
订阅模型中,
JMS
主题会将所有消息都发布到所有已订阅的监听器。如果
MDB
监听器关闭,则该
MDB
将无法收到该消息,除非该主题是一个持久订阅主题。
示例
:某金融新闻服务向订阅者广播股票价格和金融故事,例如新闻专线服务。每条消息将分发给每个订阅者。
图 7-3
展示了一个发布
/
订阅应用程序。与点对点应用程序相反,发布
/
订阅模型中的一条消息将由每个订阅
MDB
的一个实例处理。消息
“M1”
由
MDB_A
的实例和
MDB_B
的实例处理。与此类似,
“M2”
由每个订阅
MDB
的一个实例处理。
图
7-3
发布
/
订阅模型
“
恰好一次
”
处理
对于每条消息,
MDB
缓冲池至少会处理一次。这意味着,一条消息可能被处理多次:
§
在
onMessage()
方法执行期间或完成之后,在确认或提交消息之前,如果有应用程序发生故障或事务发生回滚,或者承载服务器实例发生故障,则该消息将会重新传递并再次被处理。
§
在出现故障的情况下,也会重新传递非持久性消息,但以下情况除外:消息的承载
JMS
服务器关闭或崩溃,此时该消息将被破坏。
为了确保一条消息只进行一次处理,请使用容器管理的事务,以便故障可以使事务性
MDB
工作回滚并强制重新传递消息。
基于
JCA
的
MDB
J2EE 1.4
规范定义的接口允许
MDB
接收由符合
JCA 1.5
的适配器发送的消息。另外,
J2EE 1.4
规范要求基于
JCA
的
MDB
支持端点开发、消息传递和端点取消部署。该版本的
WebLogic Server
可满足规范中定义的这些要求。
MDB
部署选项
本部分描述部署
MDB
的各种方法以及
MDB
监听的
JMS
目标。
目标和
MDB
:共存和非共存
可以将
MDB
部署到它要监听的
JMS
目标所在的服务器实例上,也可以将其部署到单独的服务器实例上。这两种方法分别称为
“
共存
”
或
“
非共存
”
。
共存目标
/MDB
使
MDB
与它监听的目标共存可以让消息通信在本地进行,从而避免了在网络上进行往返。如果使用
WebLogic Server JMS
并希望将消息处理延迟和网络流量降至最低,共存是最好的选择。
如果使用的第三方
JMS
提供程序(例如
MQ Series
)无法在
WebLogic Server
上运行,则不能使
MDB
和
JMS
目标共存。
图 7-4
和
图 7-5
说明了以下体系结构:
MDB
应用程序部署到的服务器实例承载了与之关联的
JMS
目标。这些体系结构的不同之处在于:第一个具有分布式目标,而第二个则没有。在使用分布式目标的应用程序中,
MDB
被部署到承载有分布式目标集成员的每个服务器实例上。有关分布式目标的详细信息,请参阅
JMS 分布式目标
。如
图 7-4
所示,消息
“M1”
将传递给部署了分布式目标和
MDB_A
的每个服务器实例上的
MDB_A
实例。
图
7-4
共存目标
/MDB
,分布式目标
图
7-5
共存目标
/MDB
,非分布式目标
非共存目标
/MDB
图
7-6
非共存应用程序,非分布式目标
如果满足下列条件,则适于在
MDB
监听的
JMS
目标所在的服务器实例之外的单独实例上运行
MDB
:
§
应用程序使用第
3
方
JMS
提供程序,例如
MQ Series
。
§
需要将应用程序代码
(MDB)
与
JMS
体系结构隔离。通过将
JMS
目标和
MDB
置于不同的服务器实例上,可以防止
JMS
体系结构的运行因应用程序问题(例如
MDB
占用了虚拟机的所有内存)而中断。
§
MDB
应用程序的
CPU
占用率很高。在单独的计算机上,应用程序可以使用
100%
的
CPU
而不会影响
JMS
体系结构的运行。
§
配置中的一台计算机比其他计算机具有更高的处理功能、磁盘空间和内存。
此外,还可以将
JMS
目标与
MDB
部署到以下位置:非群集服务器、同一群集中的服务器或不同群集中的服务器。
JMS
分布式目标
如果
MDB
应用程序在
WebLogic Server
群集中运行,则可以将多个物理目标(队列或主题)配置为一个分布式目标,这样会使消息生成器和使用者认为这些目标是一个目标。
如果配置了分布式目标,
WebLogic JMS
将在该分布式目标的可用成员之间分布消息传递负载。如果分布式目标中的某个成员因服务器故障而不可用,则会将消息通信重定向到该目标集中的其他可用的物理目标。
如果将
MDB
及其关联的分布式目标部署到同一群集中,
WebLogic Server
将自动列举分布式目标成员并确保有
MDB
在侦听每个成员。
MDB
将以同构方式部署到每个群集服务器实例。消息将在多台服务器实例上的物理目标之间进行分布且进行并行处理。即使某一服务器实例关闭,群集中的其他节点也可以继续处理消息。如果满足下列条件,则适于选择此体系结构:
§
应用程序具有很高的可用性要求。
§
用户希望以同构方式部署应用程序,以便每台服务器都运行相同的应用程序集。
§
应用程序要处理大量的消息或需要进行大规模并行处理。
§
群集中的计算机具有相同或相似的处理功能、磁盘空间和内存。
MDB
编程和配置:主要步骤
本部分提供有关如何实现
MDB
的步骤说明。
注意:
|
必需的
JMS
配置
以下部分中的步骤假定已创建了以下
JMS
组件:
§
JMS
连接工厂
–
支持
XA
的连接工厂,如果您的
MDB
是事务性的。
默认的
WebLogic MDB
连接工厂支持
XA
。有关默认连接工厂的信息,请参阅
“
配置和管理
WebLogic JMS”
中的
使用默认连接工厂
。有关创建自定义
WebLogic JMS
连接工厂的说明,请参阅
“
管理控制台联机帮助
”
中的
在系统模块中创建连接工厂
。
其他
JMS
提供程序的默认行为和配置方法各有不同。如果使用非
BEA JMS
提供程序,请参阅供应商文档以了解详细信息。
§
JMS
目标
有关配置
WebLogic JMS
目标的说明,请参阅
“
管理控制台联机帮助
”
。
注意:
|
如果
JMS
提供程序是远程
WebLogic Server JMS
提供程序或外部
JMS
提供程序,并且使用了
是否使用包装
中推荐的包装方法,则除了配置非本地
JMS
组件外,还必须在
JNDI
树中配置外部连接工厂和外部
JMS
目标。
|
创建
MDB
类和配置部署元素
要实现消息驱动
Bean
,请按照下列步骤操作:
1.
创建一个用于实现
javax.ejb.MessageDrivenBean
和
javax.jms.MessageListener
接口的源文件(消息驱动
Bean
类)。
MDB
类必须定义以下方法:
·
一个
ejbCreate()
方法,容器使用此方法创建空闲缓冲池中消息驱动
Bean
的实例。
·
一个
onMessage()
方法,
EJB
容器在收到消息时将调用该方法。此方法包含处理消息的业务逻辑。
·
一个
setMessageDrivenContext{}
方法,用于向
Bean
实例提供有关其环境信息(某些部署描述符值);
MDB
还使用上下文访问容器服务。请参阅
使用消息驱动 Bean 上下文
。
·
一个
ejbRemove()
方法,用于从空闲缓冲池中删除消息驱动
Bean
。
2.
在
ejb-jar.xml
中声明
MDB
,如以下代码段所示:
<ejb-jar> <enterprise-beans> <message-driven> <ejb-name>,,,</ejb-name> <ejb-class>...</ejb-class> <transaction-type>Container</transaction-type> <acknowledge-mode>auto_acknowledge</acknowledge-mode> <message-driven-destination> <destination-type>javax.jms.Topic</destination-type> <subscription-durability>Durable</subscription-durability> </message-driven-destination> </message-driven> </enterprise-beans> <assembly-descriptor> <container-transaction> <method> <ejb-name>...</ejb-name> <method-name>onMessage()</method-name> </method> <trans-attribute>Required</trans-attribute> </container-transaction> </assembly-descriptor> </ejb-jar>
要配置的关键行为包括:
3.
在
weblogic-ejb-jar.xml
的
message-driven-descriptor
元素中为
MDB
配置
WebLogic
特有的行为。例如:
<weblogic-ejb-jar> <weblogic-enterprise-bean> <ejb-name>exampleMessageDrivenA</ejb-name> <message-driven-descriptor> <pool>...</pool> <timer-descriptor>...</timer-descriptor> <destination-jndi-name>...</destination-jndi-name> <initial-context-factory>...</initial-context-factory> <provider-url>...</provider-url> <connection-factory-jndi-name>...</connection-factory-jndi-name> <jms-polling-interval-seconds>...</jms-polling-interval-seconds> <jms-client-id>...</jms-client-id> <generate-unique-jms-client-id>...</generate-unique-jms-client-id> <durable-subscription-deletion>...</durable-subscription-deletion> <max-messages-in-transaction>...</max-messages-in-transaction> <init-suspend-seconds>...</init-suspend-seconds> <max-suspend-seconds>...</max-suspend-seconds> </message-driven-descriptor> </weblogic-enterprise-bean> </weblogic-ejb-jar>
要配置的关键元素是那些指定如何访问目标的元素。有关说明,请参阅
配置目标的 MDB
。
4.
在
weblogic-application.xml
中将
start-mdbs-with-application
设置为
false
。这可确保在完全启动
WebLogic Server
之前,
MDB
不启动消息处理。有关详细信息,请参阅
延迟消息处理直至引导完成
。
如果
WebLogic Server
在部署期间找不到
MDB
的
JMS
目标,则部署将成功,但
WebLogic Server
将显示一条消息,指出未找到目标。随后,
MDB Bean
会尝试定期连接到它的
JMS
队列直至成功。有关详细信息,请参阅
群集 MDB 的迁移和恢复
。
MDB
编程和配置:详细信息
注意:
|
§
配置目标类型
§
配置持久主题订阅
§
配置消息处理行为
将
EJB
配置为使用逻辑消息目标
在此版本的
WebLogic Server
中,可以在
EJB
的部署描述符中声明逻辑消息目标,并将该逻辑消息目标映射到实际消息目标(
JMS
队列、
JMS
主题或
MDB
)。在声明逻辑消息目标后,便可以创建链接到该逻辑消息目标的消息目标引用。
EJB
将使用逻辑消息目标名执行
JNDI
查询并访问实际消息目标。即可针对单个
MDB
定义逻辑
JMS
消息目标,也可以针对整个应用程序定义。
为单个
MDB
配置逻辑
JMS
消息目标
在此版本的
WebLogic Server
中,可以为单个
MDB
配置逻辑
JMS
消息目标。
要将
MDB
配置为使用逻辑消息目标来链接到实际消息目标,请执行下列操作:
2.
在
ejb-jar.xml
的下列元素中声明消息目标引用:
·
message-destination-ref
·
message-destination-ref-name
-
在企业
Bean
代码中用作消息目标(相对于
java:comp/env
)的环境名称。例如,
<message-destination-ref>jms/StockQueue</message-destination-ref>
。
·
message-destination-type
-
被引用目标的预期类型。例如
<message-destination-type>javax.jms.Queue</message-destination-type>
。
·
message-destination-usage -
指定消息是在目标使用的还是为目标生成的,或是用于这两者。例如
<message-destination-usage>Produces<message-destination-usage>
。
·
message-destination-link
-
将消息目标引用链接到实际消息目标。此值必须与
weblogic-ejb-jar.xml
中的
message-destination-name
所定义的目标匹配。
有关这些元素或
ejb-jar.xml
的其他信息,请参阅
Sun
文档。
配置应用程序作用域的逻辑
JMS
消息目标
在此版本的
WebLogic Server
中,可以配置应用程序的资源。为整个应用程序配置的资源称为应用程序作用域的资源。本部分描述
EJB
应用程序的应用程序作用域的逻辑
JMS
目标。有关应用程序作用域的资源(例如
JMS
和
JDBC
)的其他信息,请参阅
WebLogic JMS 编程
和
WebLogic JDBC 编程
。
EJB
的应用程序作用域的资源(例如逻辑
JMS
消息目标)适用于应用程序中的所有
MDB
。通过将特定
MDB
配置为使用逻辑消息目标来链接到实际消息目标(如
为单个 MDB 配置逻辑 JMS 消息目标
中所述),可以替换相应
MBD
的应用程序作用域的
JMS
。
要为
EJB
配置应用程序作用域的
JMS
,请执行下列操作:
2.
在
ejb-jar.xml
的下列元素中声明消息目标引用:
§
message-driven
·
message-destination-type
-
被引用目标的预期类型。例如
<message-destination-type>javax.jms.Queue</message-destination-type>
。
·
message-destination-usage
-
指定消息是在目标使用的还是为目标生成的,或者是用于这两者。例如
<message-destination-usage>Produces<message-destination-usage>
。
·
message-destination-link
-
将消息目标引用链接到实际消息目标。例如
<message-destination-link>ExpenseProcessingQueue<message-destination-link>
。此值必须与
weblogic-ejb-jar.xml
中的
message-destination-name
所定义的目标匹配。
§
message-destination
·
message-destination-name –
消息目标的名称。例如
<message-destination-name>ExpenseProcessingQueue<message-destination-name>
。此值必须与
weblogic-ejb-jar.xml
中的
message-destination-name
所定义的目标匹配。
有关这些元素或
ejb-jar.xml
的其他信息,请参阅
Sun
文档。
配置目标类型
在
ejb-jar.xml
的
message-driven-destination
元素的
destination-type
元素中配置
MDB
监听的目标类型。
要指定主题,请将
destination-type
设置为
javax.jms.Topic
。如果该目标是一个主题,请将
subscription-durability
指定为
Durable
或
NonDurable
。
要指定队列,请将
destination-type
设置为
javax.jms.Queue
。
配置
MDB
的事务管理策略
MDB
可以管理其自己的事务,也可以将事务委托给容器管理。
要配置容器级事务管理,请执行下列操作:
§
在
ejb-jar.xml
文件中,将
message-driven
元素中的
transaction-type
元素设置为
Container
。
§
在
ejb-jar.xml
文件中,将
container-transaction
元素中的
trans-attribute
元素设置为
Required
。
注意:
|
如果将
transaction-type
设置为
Container
并且未设置
trans-attribute
,则会应用
transaction-attribute
的默认值(对于
MDB
是
NotSupported
)。
WebLogic Server
允许部署
MDB
并记录相容性错误。但是,如果此配置出现错误,
MDB
将不会以事务方式运行
–
如果在事务期间发生故障,将不会回滚在发生故障之前所执行的更新。
|
§
要更改事务的超时时段,请在
weblogic-ejb-jar.xml
的
transaction-descriptor
元素中设置
trans-timeout-seconds
。如果事务超时,就将其回滚,并且重新传递消息。默认情况下,事务在
30
秒后超时。如果应用程序具有长期运行的事务,则可以适当地增加超时时间。
要配置
Bean
级事务管理,请执行下列操作:
§
在
ejb-jar.xml
文件中,将
message-driven
元素中的
transaction-type
元素设置为
Bean
。
配置
JMS
资源中断期间的消息传递挂起
在此版本的
WebLogic Server
中,可以配置在
EJB
容器检测到
JMS
资源停机时
MDB
的行为。
您可以:
§
将
MDB
配置为在
EJB
容器检测到
JMS
资源停机时挂起
JMS
连接,从而停止接收其他消息。如果选择此配置选项:则可以指定:
·
MDB
在首次恢复接收消息之前应等待的秒数。
·
MDB
在恢复接收消息之前等待的最大秒数。
§
将
MDB
配置为在
EJB
容器检测到
JMS
资源中断时不挂起
JMS
连接。
当挂起
JMS
连接时,将挂起与该连接关联的所有
JMS
会话的消息传递。默认情况下,当
EJB
容器检测到
JMS
资源中断时,它将挂起
MDB
的
JMS
连接,挂起时间为六十秒。
配置挂起
JMS
连接的秒数
要配置
MDB
的
JMS
连接在资源中断期间挂起的秒数,请执行下列操作:
1.
在
weblogic-ejb-jar.xml
中更改
init-suspend-seconds
元素的值。默认值为
60
,这会导致
MDB
的
JMS
连接在
EJB
容器检测到
JMS
资源中断时挂起六十秒。如果
JMS
资源在经过
init-suspend-seconds
中指定的秒数后仍不可用,
JMS
连接将会再次挂起,挂起时间为
init-suspend-seconds
中指定的秒数,直至经过
max-suspend-seconds
(请参阅下面的步骤
2
)中指定的秒数为止。
2.
更改
weblogic-ejb-jar.xml
中
max-suspend-seconds
元素的值。默认值为
60
,这会导致
MDB
的
JMS
连接在
EJB
容器检测到
JMS
资源停机时仅挂起一次,时间为六十秒。这是因为
init-suspend-seconds
(请参阅上面的步骤
1
)的默认值等于
max-suspend-seconds
的默认值。在经过
max-suspend-seconds
中指定的秒数后,
MDB
的
JMS
连接将会还原。
禁止对
JMS
连接的挂起
如果不希望
MDB
的
JMS
连接在
EJB
容器检测到资源中断时挂起,请将
max-suspend-seconds
的值设置为
0
。当
max-suspend-seconds
的值为
0
时,
init-suspend-seconds
的值将被忽略。
手工挂起和恢复消息传递
配置目标的
MDB
WebLogic Server MDB
支持
Weblogic JMS
目标和外部(非
BEA
)
JMS
提供程序目标。
本地目标是指与
MDB
运行在同一计算机或同一群集中的目标。远程目标是指与
MDB
在不同计算机和不同群集中运行的目标。一个目标是本地目标还是远程目标,取决于它和
MDB
是否共享同一
JNDI
上下文。
要使
MDB
及其关联的
JMS
目标相互视对方为本地目标,二者必须运行在同一计算机或同一
WebLogic Server
群集中。对于位于同一
WebLogic Server
群集中服务器实例上的
MDB
和
JMS
目标,即使它们位于不同的计算机上,也将相互视对方为本地目标,因为
WebLogic Server
群集中的每个服务器实例都使用同一群集范围的
JNDI
树的副本。
在非
BEA JMS
提供程序下运行的目标称为
“
外部
”
目标。外部
JMS
提供程序拥有其自己的
JNDI
提供程序,并且外部
JMS
对象与
WebLogic Server MDB
不共享同一上下文,除非使用包装将外部
JMS
对象配置为出现在
MDB
的
JNDI
上下文中。有关此方法的信息,请参阅
是否使用包装
。
目标的性质(本地或远程以及
WebLogic JMS
或非
BEA
)控制可用的配置方式,并在某种程度上规定如何在
MDB
的
weblogic-ejb-jar.xml
的
message-destination-descriptor
中配置这些关键元素:
§
initial-context-factory
§
provider-url
§
destination-jndi-name
§
connection-factory-jndi-name
对于外部和远程目标,最简单的配置策略便是使用
WebLogic Server JMS
包装。使用包装可以在第三方
JNDI
提供程序或其他
WebLogic Server
群集或域中的
JMS
对象与本地
WebLogic JNDI
树中的对象之间创建
“
符号链接
”
。
有关何时适于使用包装的详细信息,以及有关在
weblogic-ejb-jar.xml
中配置
message-driven-descriptor
的规则,请参阅下列部分:
§
是否使用包装
是否使用包装
使用包装意味着将与远程
JMS
对象(非
BEA
或
WebLogic JMS
)对应的外部连接工厂和外部目标配置为本地
JNDI
树中的条目。
§
如果使用了外部
JMS
提供程序或远程
WebLogic JMS
提供程序,则建议使用包装。有关
JMS
包装类的详细信息,请参阅
“WebLogic JMS
编程
”
中的
对远程或外部 JMS 提供程序的简化访问
。
§
如果为连接工厂或目标使用了包装,则必须为这两种对象都使用包装。
是否使用包装类将决定如何配置
initial-context-factory
和
destination-jndi-name
,如下所述。
如何设置
provider-url
§
如果
JMS
提供程序对于
MDB
是本地的(按定义为
WebLogic JMS
),请不要指定
provider-url
。
§
如果
JMS
提供程序位于远程(无论是
WebLogic JMS
还是外部提供程序),并且:
·
如果未使用包装,则应指定
provider-url
。
·
如果使用了包装,则请勿指定
provider-url
。
URL
将会隐式编码在包装中。
如何设置
initial-context-factory
§
如果
JMS
提供程序为
WebLogic JMS
,则无论它位于本地还是远程,都不要指定
initial-context-factory
。
§
如果
JMS
提供程序位于外部,并且
·
如果未使用包装,则应指定
JMS
提供程序使用的初始上下文工厂。
·
如果使用了包装,则请勿指定
initial-context-factory
。
如何设置
destination-jndi-name
§
如果
JMS
提供程序位于本地,请指定在本地
JNDI
树中绑定的目标名称。
§
如果
JMS
提供程序位于外部,并且:
·
如果未使用包装,则应指定在外部提供程序的
JNDI
树中绑定的目标名称。
·
如果使用了包装,则应指定在本地
JNDI
树中设置的与远程或外部目标对应的外部目标名。
如何设置
connection-factory-jndi-name
§
如果
JMS
提供程序位于本地,则请勿指定
connection-factory-jndi-name
,除非
MDB
将使用已配置的自定义连接工厂。
当默认的
WebLogic Server
连接工厂不能满足应用程序的要求时,将使用自定义连接工厂。例如,可以配置自定义连接工厂,以便为
MessagesMaximum
特性指定所需的特定值。有关配置连接工厂的过程,请参阅
“
管理控制台联机帮助
”
中的
配置连接工厂
。
注意:
|
如果为
MDB
配置了自定义
JMS
连接工厂,应确保将
Acknowledge Policy
特性设置为
Previous
并启用
UserTransactionsEnabled
特性。
|
§
如果
JMS
提供程序位于远程或外部,并且:
·
如果未使用包装,则应指定
JMS
提供程序使用的连接工厂的名称(在远程
JNDI
树中绑定)。
·
如果使用了包装,则应指定在本地
JNDI
树中设置的与远程或外部
JMS
提供程序的连接工厂对应的外部连接工厂。
公用目标方案:图示和关键元素设置
本部分中的示意图说明了公用目标配置。对于远程和外部目标,将分为使用包装和不使用包装两种方案。
图
7-7 A.
目标位于本地
WebLogic JMS
服务器上
图
7-8 B
目标位于远程
WebLogic JMS
服务器上
–
不使用包装
图
7-9 C
目标位于外部
JMS
服务器上
–
不使用包装
图
7-10 D
目标位于远程
WebLogic Server
或外部
JMS
服务器上
–
使用包装
表
7-1
公用配置方案
|
目标位置
|
是否配置了包装?
|
destination-jndi-name
|
initial- context- factory
|
provider- url
|
connection- factory-jndi- name
|
A
|
本地
WebLogic JMS
服务器
|
不适用于本地
WebLogic JMS
服务器
|
在本地
JNDI
树中绑定的本地目标名称
|
请勿指定
|
请勿指定
|
仅当使用自定义连接工厂时指定
|
B
|
远程
WebLogic JMS
服务器
|
未配置包装
|
在远程
JNDI
树中绑定的远程目标名称
|
请勿指定
|
远程
WebLogic JMS
服务器的
URL
或群集地址
|
仅当在远程提供程序上使用自定义连接工厂时指定
|
C
|
外部
JMS
提供程序
|
未配置包装
|
在远程
JNDI
树中绑定的远程目标名称
|
在远程
JNDI
树中绑定的远程初始上下文工厂名称
|
用于访问外部
JMS
提供程序的
URL
|
外部连接工厂的
JNDI
名
|
D
|
远程
WebLogic JMS
服务器
或
外部
JMS
服务器
|
是。已配置包装
|
映射到远程或外部目标的外部目标的名称(在本地
JNDI
树中绑定)
|
请勿指定
|
请勿指定
|
映射到远程或外部连接工厂的外部连接工厂的名称(在本地
JNDI
树中绑定)
|
配置持久主题订阅
持久订阅允许
MDB
接收在未连接
MDB
时传递给主题的消息。
配置非群集服务器的持久主题订阅
要为部署到非群集服务器实例的
MDB
配置持久主题订阅,请按照下列说明操作。
1.
将
ejb-jar.xml
中的
destination-type
配子为
javax.jms.Topic
。
2.
在
ejb-jar.xml
的
message-driven-destination
元素中:
·
将
destination-type
设置为
javax.jms.Topic
·
将
subscription-durability
设置为
Durable
.
3.
根据需要配置
MDB
的
ClientId
:
如果设置连接工厂,但是不向其分配
ClientID
,或者如果使用默认的连接工厂,
MDB
就将
weblogic-ejb-jar.xml
中的
jms-client-id
的值用作其客户端
ID
。如果未指定
jms-client-id
,默认值为
MDB
的
ejb-name
。
配置群集的持久主题订阅
在群集中,
JMS
持久订阅由
MDB
的下列元素的组合进行唯一标识:
§
连接
ID –
连接工厂的
ClientId
,它在一个群集中是唯一的。
§
订阅
ID - MDB
的
jms-client-id
。订阅
ID
在其主题上必须是唯一的,因此具有持久主题订阅的
MDB
不能在一个群集中的多个服务器实例上运行。当
MDB
的第一个实例在群集的服务器实例上启动后,可以在另一台群集服务器上成功部署
EJB
的另一个实例,但当
MDB
启动时,将检测到冲突,并且该
MDB
实例将无法完全连接到
JMS
。
要允许持久订阅者
MDB
在一个群集中的多个服务器实例上运行,以便每个
MDB
实例都接收到每个主题消息的副本,应使用唯一的
jms-client-ID
来部署每个
MDB
实例,而如果未指定
jms-client-ID
,则应使用
ejb-name
。
持久订阅者不能直接订阅
WebLogic Server
分布式目标主题,而必须改为订阅目标主题物理成员的
JNDI
名。有两种方式可完成此任务:
§
使用唯一的
JNDI
名配置每个分布式目标主题物理目标,并使用匹配的
destination-jndi-name
配置每个持久订阅者
MDB
缓冲池,或者
§
使用同一
JNDI
名配置每个物理目标,并且:
·
确保每个服务器实例只有一个物理目标。
配置持久主题订阅的自动删除
在此版本的
WebLogic Server
中,可以将
MDB
配置为在从服务器取消部署或删除
MDB
时自动删除持久主题订阅。要将
MDB
配置为自动删除持久主题订阅,请将
durable-subscription-deletion
设置为
True
;默认情况下,
durable-subscription-deletion
设置为
False
。
配置消息处理行为
下列主题提供与消息传递有关的行为准则:
§
确保消息接收顺序
确保消息接收顺序
确保
MDB
的业务逻辑允许对消息进行异步处理。不要假定
MDB
会按照客户端发出消息的顺序来接收消息。要确保接收顺序与客户端发送消息的顺序匹配,必须执行下列操作:
要确保在进行事务回滚和恢复时对消息排序,请对自定义的连接工厂进行配置:将
MessagesMaximum
设置为
1
,同时确保未配置重新传递延迟。有关详细信息,请参阅
“WebLogic JMS
编程
”
中的
消息的有序重新传递
。
有关详细信息,请参阅
Sun
有关
Interface MessageListener
(
javax.jms.MessageListener.onMessage()
)
的文档,网址为
http://java.sun.com/j2ee/sdk_1.2.1/techdocs/api/javax/jms/MessageListener.html/
。
防止和处理重复消息
JMS
生成器需要
MDB
对收到的消息进行确认。如果
MDB
收到消息但未能发送确认信息,
JMS
生成器将重新发送相同的消息。
MDB
的设计应允许出现重复消息的可能。在某些情况下,出现重复消息是不适当的。例如,如果
MDB
的
onMessage()
方法包含借记银行帐户的代码,则接收和处理该消息两次将导致对该帐户借记两次。另外,重新发送消息将占用更多的处理资源。
防止传递重复消息的最佳方式是使用容器管理的事务。在容器管理的事务中,消息接收和确认都在事务中进行;二者相互依存,决不单独发生。但是,与使用
Bean
管理的事务相比,虽然它可以提供更高的可靠性,但会降低性能,因为容器管理的事务会占用更多的
CPU
和磁盘空间。
如果
MDB
管理其自己的事务,则
onMessage()
代码必须处理重复消息,因为接收和确认操作都在事务之外执行。在某些应用程序中,可以接收并处理重复消息。而在其他情况下(例如上述帐户情况),如果事务是由
Bean
管理的,则
Bean
代码必须防止处理重复消息。例如,
MDB
可以跟踪数据库中已使用的消息。
图
7-11
服务器在
onMessage()
完成和容器传递确认之间崩溃
重新传递和异常处理
如果发生意外错误时
MDB
正在使用某一消息,该
MDB
便可能引发系统异常,进而导致
JMS
重新发送、延迟,然后重新发送或放弃,具体取决于
JMS
的配置方式。
要强制为事务
MDB
重新传递消息,请使用
Bean
上下文来调用
setRollbackOnly()
。
要强制为任何
MDB
(事务或非事务)重新传递消息,可以引发由
RuntimeException
派生的异常或由
MDB
引发的错误。这会导致销毁并重新创建
MDB
实例,从而导致性能降低。
基于
MDB
的
onMessage()
方法正在执行的任务类型来配置重新传递延迟。在某些情况下,重新传递应当是即时的,例如在向新闻专线服务发布突发新闻的应用程序中。在其他情况下,例如,如果
MDB
因数据库关闭而引发异常,则不会立即执行重新传递,而是等到数据库恢复后再执行这一操作。
注意:
|
对于完全排序的
MDB
,请勿设置重新传递延迟。
|
使用消息驱动
Bean
上下文
WebLogic Server
调用
setMessageDrivenContext()
来将
MDB
实例与容器上下文关联。它不是客户端上下文;客户端上下文不与
JMS
消息一起传递。
要从
MDB
实例内部访问容器上文的属性,请使用
MessageDrivenContext
接口中的下列方法:
§
getCallerPrincipal())
-
它从
EJBContext
接口继承,不应由
MDB
实例调用。
§
isCallerInRole()
-
它从
EJBContext
接口继承,不应由
MDB
实例调用。
§
setRollbackOnly()
-
只能由使用容器管理的事务的
EJB
使用。
§
getRollbackOnly()
-
只能由使用容器管理的事务的
EJB
使用。
§
getUserTransaction()
-
只能由使用
Bean
管理的事务的
EJB
使用。
注意:
|
虽然
getEJBHome()
也继承为
MessageDrivenContext
接口的一部分,但消息驱动
Bean
不具有
Home
接口。从
MDB
实例内部调用
getEJBHome()
会导致
IllegalStateException
。
|
延迟消息处理直至引导完成
默认情况下,
MDB
会在部署后立即开始处理消息,即使在其目标
WebLogic Server
实例未完成引导时也是如此。这会导致
MDB
应用程序在启动过程中访问未初始化的服务或应用程序,进而导致程序失败。要避免此问题,请将
weblogic-application.xml
中的
start-mdbs-with-application
设置为
false
。
将
start-mdbs-with-application
设置为
false
会强制
MDB
延迟启动,直至服务器实例在服务器引导过程即将完成时打开其监听端口为止。
配置消息驱动
Bean
的安全标识
当消息驱动
Bean (MDB)
收到来自
JMS
队列或主题的消息时,
EJB
容器将使用凭据映射提供程序和凭据映射,来获取在建立
JMS
连接时要使用的安全标识(用户名和密码)。在启动
MDB
时,仅进行一次凭据映射。
连接到
EJB
容器后,
JMS
提供程序就会使用已建立的安全标识来检索所有消息。
要配置
MDB
的安全标识,请执行下列操作:
1.
创建
MDB
的
WebLogic
用户。请参阅
“
确保
WebLogic
资源安全
”
中的
用户、组和安全角色
。向该用户指定非
BEA JMS
提供程序在建立
JMS
连接时需要使用的用户名和密码。
2.
在
ejb-jar.xml
部署描述符中,定义
MDB
的
run-as
标识:
<security-identity> <run-as> <role-name>admin</role-name> </run-as>
</security-identity>
3.
在
weblogic-ejb-jar.xml
部署描述符中,将
run-as
标识映射到上一步骤中定义的用户,如下所示:
<security-role-assignment> <role-name>admin</role-name> <principal-name>username</principal-name> </security-role-assignment>
其中,
username
是步骤
1
中所创建用户的用户名。
注意:
|
如果
JMS
提供程序是
WebLogic JMS
,则不必配置凭据映射器。
|
将
MDB
与跨域安全一起使用
MBD
并不要求您配置跨域安全。但在实现
MDB
时,您应该考虑下列准则:
§
如果
MDB
必须处理事务消息,则必须为所有的参与域配置跨域安全或安全互操作模式。
在跨域安全配置和安全互操作模式方面,使进程使用的所有域保持对称。由于这两个设置都在域级别进行设置,所以域可能处于混合模式,即既为域设置了跨域安全,又为域设置了安全互操作模式。有关详细信息,请参阅
“WebLogic JTA
编程
”
中的
为域间事务配置域
。
§
不需要为处理非事务消息的
MDB
配置跨域安全。但是,如果在一个域上配置了跨域安全,而且任何域中
MDB
监听的分布式目标的成员发生了变化,您将需要为进程与其通信的所有域配置跨域安全。
一个最佳实践是在跨域安全配置方面,使进程使用的所有域保持对称。这就是说,所有的域都使用跨越安全(或在适当的例外列表中),或不为任何域配置跨域安全。请参阅
“
确保
WebLogic Server
安全
”
中的
配置 WebLogic 域的安全
。
群集
MDB
的迁移和恢复
WebLogic Server
支持对群集
MDB
应用程序进行迁移和恢复。在发生故障的情况下,可以将
JMS
目标和
MDB
重新联机。对应用程序进行设计,以便在有服务器实例发生故障时,该应用程序可自动将
JMS
目标及其关联的
MDB
从群集中的故障服务器迁移到可用服务器实例上。
注意:
|
MDB
只能在群集服务器中使用可迁移服务。可迁移服务不能跨越多个群集。
|
当
MDB
应用程序迁移到其他服务器上后,它将重新连接到迁移后的
JMS
目标并再次开始接收来自
JMS
目标的消息。
MDB
不具有可迁移目标,而是会自动在部署过程中检测
JMS
服务器迁移目标,并将该目标用作它的可迁移目标。必须确保在部署
JMS
服务器的所有位置都部署了
MDB
。有两种方式可实现此目的:
§
以同构方式将
MDB
部署到群集中。
§
将
MDB
的目标与服务器实例所在域的
config.xml
文件中的
JMS
可迁移目标列表相匹配。
MDB
目标服务器名必须与
JMS
可迁移目标列表匹配,否则
MDB
迁移将失败。有关配置可迁移目标的详细信息,请参阅
“
使用
WebLogic Server
群集
”
中的
定义群集中的可迁移目标服务器
。
在
图 7-12
中,受管服务器
1
、
2
和
3
位于同一群集中。受管服务器
2
和受管服务器
3
被配置为受管服务器
1
的可迁移目标。如果受管服务器
1
发生故障,
JMS
目标和
MDB
将迁移到下一个可用的受管服务器。如果目标列表上的某个受管服务器不可用,该目标和
MDB
将迁移到目标列表上的下一个可用受管服务器。例如,如果受管服务器
2
在受管服务器
1
发生故障时不可用,
JMS
目标和
MDB
应用程序将迁移到受管服务器
3
。
图
7-12 JMS
目标的迁移
MDB
的事务批处理
在
MDB
中,业务逻辑(包括数据库事务)是在
onMessage()
方法内执行的。在
EJB
应用程序中,多个
MDB
可以执行多个
onMessage()
调用。如果每个
onMessage()
调用都执行一项数据库事务,则会造成大量开销,因为每个调用都需要有其自己的数据库连接。
WebLogic Server
提供了一种机制,可以使多个
onMessage()
调用归组为一个事务。通过减少处理事情所需的数据库工作量,此机制可以提高
EJB
应用程序的性能。
注意:
|
事务批处理并非对所有
MDB
应用程序都有效。例如,如果应用程序中的某个
MDB
对数据库执行多次调用,则可能发生数据库死锁。使用事务批处理功能将导致
MDB
为每个事务锁定更多的行,进而可能导致数据库死锁。
|
配置
MDB
事务批处理
可以通过定义
max-messages-in-transaction
元素启用
MDB
事务批处理。此元素是
weblogic-ejb-jar.xml
部署描述符中的
message-driven-descriptor
元素的一部分。
max-messages-in-transaction
定义
WebLogic Server
用于处理
onMessage()
事务的批处理大小。但是,增加批处理大小会增加滞后时间。开始时应使用较小的值,例如
5
。如果应用程序性能允许,可以增大此值。
在使用
MDB
批处理时,每个事务将处理更多的消息。由于每个事务中要执行更多的工作,因此可能导致更多的事务发生超时。通过在
weblogic-ejb-jar.xml
中增大
trans-timeout-seconds
特性的值可延长事务超时时间。
MDB
事务批处理的工作原理
MDB
事务批处理不需要对应用程序代码进行任何更改。就应用程序而言,仍将逐条一理各条消息。不存在应用程序级消息列表。
在内部,
WebLogic Server
将创建一个队列来管理各项事务。每条消息都将进行排队,直至队列中的消息数等于
max-messages-in-transaction
定义的批处理大小。但是,如果没有将排队的文本消息,则将提交队列中的当前消息进行处理。
如果单个
onMessage()
调用失败,则会回滚整个批处理。如果失败是由事务超时(由
weblogic-ejb-jar.xml
中的
trans-timeout-seconds
特性定义)引起的,
MDB
容器将临时减小批处理的大小并尝试以较小的批处理来处理事务。
如果失败是由其他原因造成的,则
MDB
会将失败批处理中的每条消息作为单个事务重新处理。这样可避免单个
onMessage()
调用永久挂起整个批处理的情况。
概要:
MDB
的部署元素
本部分列出影响
MDB
行为的关键部署元素:
表
7-2 MDB
在
weblogic-ejb-jar.xml
中的部署元素
| ||
元素
|
描述
|
默认
|
weblogic.jms. MessageDriven BeanConnection Factory
| ||
N/A
| ||
| ||
60
| ||
0
| ||
weblogic.jndi. WLInitialContext Factory
| ||
ejb-name
| ||
EJB
容器将每
10
秒进行一次重新连接尝试。
| ||
1000
| ||
60
| ||
t3://localhost:7001
| ||
将
ejb-jar.xml
文件中的应用程序角色映射到
WebLogic Server
中可用安全委托人的名称。
|
| |
| ||
30
秒
|
表
7-3 MDB
在
weblogic-application.xml
中的元素
| ||
元素
|
描述
|
默认
|
start-mdbs-with-application
|
控制
MDB
开始处理消息的时间。当使用默认设置
True
时,
MDB
会在部署后立即开始处理消息,即使在
WebLogic Server
未完成引导时也是如此。这会导致
MDB
应用程序在引导过程中访问未初始化的服务或应用程序,进而导致程序失败。
将值设置为
False
可延迟消息处理,直至
WebLogic Server
打开其监听端口。
|
true
|
表
7-4 MDB
的关键
J2EE
部署元素
| ||||
元素
|
描述
|
允许的值
| ||
acknowledge-mode
|
对于使用
Bean
管理的事务界定的消息驱动
Bean
,指定其
onMessage
方法的
JMS
消息确认语义。
|
§
AUTO_ACKNOWLEDGE
§
DUPS_OK_ACKNOWLEDGE
| ||
destination-type
|
指定
JMS
目标的类型
-
应该由目标实现的
Java
接口。
|
§
javax.jms.Queue
§
javax.jms.Topic
| ||
subscription-durability
|
指定希望
JMS
主题订阅是持久订阅还是非持久订阅。
|
§
Durable
§
NonDurable
| ||
transaction-type
|
指定企业
Bean
的事务管理类型。
|
§
Bean
§
Container
| ||
trans-attribute
|
指定在向企业
Bean
的业务方法委托方法调用时,容器必须如何管理事务边界。
|
§
NotSupported
§
Supports
§
必需
§
RequiresNew
§
Mandatory
§
Never
|