WebLogic JMS的强大功能组合:UOW+SAF+分布式Queue
来源:互联网 发布:淘宝上买徕卡 编辑:程序博客网 时间:2024/05/17 01:57
Weblogic 服务器提供了非常强大的JMS消息中间件平台,其性能优越,远超同类JMS产品比IBM 的MQ也快很多。并且,Weblogic JMS提供了非常强大的消息传递功能使得基于该平台的Java 消息解决方案非常的完整。本文,旨在阐述WebLogic JMS 服务器的一些比较重要的特性,以及如何配合在一起使用。
- 本文所要介绍的WebLogic JMS特性有:
DQ (Distributed Queue):分布式Queue。通过配置DQ可以提供消息队列的集群式部署,提高一个队列的Capacity以及提供HA支持。对于客户端透明。
SAF 存储转发:可以在两个WebLogic服务器(相同版本)之间,从一段发送JMS消息到另一端,并保证发送能到达终端的Destination。如果,两台服务器之间的网络连接暂不可用,则会将消息保存至发送方的本地存储中。用户可以设定多种转发策略和Qos设定。
UOW(Unit-Of-Work):WLS可以将多条消息标签为一个工作单元(UOW),只有当该UOW中所有的消息都被发送到队列中后,Consumer端才能获取该工作单元的所有消息。并且,所有属于该UOW的消息,保证只有一个Consumer能进行处理。
- 客户用例
在某家工厂构建的一个门店和总部数据中心系统之间的一个异步信息同步的解决方案中,采用了UOW+SAF+DQ的方式来传送大文件的切片,并在终端还原文件。由于文件被切片传送,因此,根据JMS 队列传输的原理,默认配置的JMS DQ会将文件切片分散接收在集群的各个节点的QUEUE上,并且每个节点上配置的消息驱动EJB(MDB)也不能保证只有一个实例能获取文件的全部切片,这样的默认行为令还原大文件切片变为一个需要在多个MDB之间协调完成的事务,处理过程复杂,效率也不高。并且通过SAF来克服在VPN网络环境中可能的各类异常,保证消息传递的质量。
针对该用户的这种需求,提出的解决方案是使用UOW来将一个文件的切片打包为一个工作单元的方式来传送。
方案示意图如下:
上图中的UOW1、UOW2、UOW3表示的是代表一个大文件切片的一组/一个工作单元消息(多条)。大文件会先经过JAVA程序进行切片,然后通过JMS API和UOW的API来发送到一个本地的WebLogic服务器的队列上。本地队列被配置为通过SAF转发到远程的一个DQ中。远程的DQ接收到消息后,会根据UOW的ID来将一组消息(统一UOW ID的消息)作为一个整体,分配到集群中的某一个实例。在该集群中部署一个MDB EJB。该EJB的实例会收到属于一个文件的所有切片,然后进行还原处理。由于使用了UOW,可以保证每个文件的所有切片,有且只有一个MDB实例可以进行处理。
- 配置过程简述
- 首先安装远端WebLogic服务器并配置好集群。
- 分别创建三个JMS Server在三个集群节点上。
- 创建一个JMS Module,并在JMS Module中定义一个子部署target到cluster上。
- 创建一个Distributed Queue, target到定义好的子部署上,记得在高级配置区域中选择工作单元 (UOW) 消息处理策略为:单个消息传递。 该配置启动UOW支持。
- 安装本地WebLogic服务器
- 创建SAF存储转发代理。
- 创建SAF导入目的地,并在SAF远程上下文定义中,配置远程集群的URL,例如:t3://172.16.100.1:7003,172.16.100.1:7004,172.16.100.1:7005。
- 配置子部署并将SAF导入目的地target到子部署上。
详细部署请参考WLS相关文档。
- 示例代码
UOW 发送:
import
java.util.UUID;
import
java.io.BufferedReader;
import
java.io.IOException;
import
java.io.InputStreamReader;
import
java.util.Hashtable;
import
javax.jms.*;
import
javax.naming.Context;
import
javax.naming.InitialContext;
import
javax.naming.NamingException;
import
weblogic.jms.extensions.WLMessageProducer;
/** This example shows how to establish a connection
* and send messages to the JMS queue. The classes in this
* package operate on the same JMS queue. Run the classes together to
* witness messages being sent and received, and to browse the queue
* for messages. The class is used to send messages to the queue.
*/
public
class
QueueSendUOW
{
// Defines the JNDI context factory.
public
final
static
String JNDI_FACTORY=
"weblogic.jndi.WLInitialContextFactory"
;
// Defines the JMS context factory.
public
final
static
String JMS_FACTORY=
"dizzyworldConnectionFactory"
;
// Defines the queue.
public
final
static
String QUEUE=
"dizzyworldDistributedQueue"
;
private
QueueConnectionFactory qconFactory;
private
QueueConnection qcon;
private
QueueSession qsession;
private
QueueSender qsender;
private
Queue queue;
private
TextMessage msg;
/**
* Creates all the necessary objects for sending
* messages to a JMS queue.
*
* @param ctx JNDI initial context
* @param queueName name of queue
* @exception NamingException if operation cannot be performed
* @exception JMSException if JMS fails to initialize due to internal error
*/
public
void
init(Context ctx, String queueName)
throws
NamingException, JMSException
{
qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY);
qcon = qconFactory.createQueueConnection();
qsession = qcon.createQueueSession(
true
, Session.AUTO_ACKNOWLEDGE);
queue = (Queue) ctx.lookup(queueName);
qsender = qsession.createSender(queue);
msg = qsession.createTextMessage();
qcon.start();
}
/**
* Sends a message to a JMS queue.
*
* @param message message to be sent
* @exception JMSException if JMS fails to send message due to internal error
*/
public
void
send(String message, String strUOW,
int
SeqNo,
boolean
isLast)
throws
JMSException {
msg.setText(message);
msg.setStringProperty(
"JMS_BEA_UnitOfWork"
, strUOW);
msg.setIntProperty(
"JMS_BEA_UnitOfWorkSequenceNumber"
, SeqNo);
msg.setBooleanProperty(
"JMS_BEA_IsUnitOfWorkEnd"
, isLast);
qsender.send(msg, DeliveryMode.NON_PERSISTENT,
7
,
0
);
}
/**
* Closes JMS objects.
* @exception JMSException if JMS fails to close objects due to internal error
*/
public
void
close()
throws
JMSException {
qsession.commit();
qsender.close();
qsession.close();
qcon.close();
}
/** main() method.
*
* @param args WebLogic Server URL
* @exception Exception if operation fails
*/
public
static
void
main(String[] args)
throws
Exception {
if
(args.length !=
1
) {
System.out.println(
"Usage: java QueueSendUOW WebLogicURL"
);
return
;
}
InitialContext ic = getInitialContext(args[
0
]);
QueueSendUOW qs =
new
QueueSendUOW();
qs.init(ic, QUEUE);
readAndSend(qs);
qs.close();
}
private
static
void
readAndSend(QueueSendUOW qs)
throws
IOException, JMSException
{
BufferedReader msgStream =
new
BufferedReader(
new
InputStreamReader(System.in));
String line=
null
;
UUID UOW =
null
;
boolean
quitNow =
false
;
int
seqNumber =
1
;
UOW = UUID.randomUUID();
while
(! quitNow) {
System.out.print(
"Enter message (\"quit\" to quit): \n"
);
line = msgStream.readLine();
if
(line !=
null
&& line.trim().length() !=
0
) {
quitNow = line.equalsIgnoreCase(
"quit"
);
if
( ! quitNow ) {
qs.send( line, String.valueOf(UOW), seqNumber,
false
);
}
else
{
qs.send( line, String.valueOf(UOW), seqNumber,
true
);
}
System.out.println(
"JMS Message Sent: "
+ line +
"\n"
);
seqNumber +=
1
;
}
}
}
private
static
InitialContext getInitialContext(String url)
throws
NamingException
{
Hashtable<String,String> env =
new
Hashtable<String,String>();
env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
env.put(Context.PROVIDER_URL, url);
return
new
InitialContext(env);
}
}
MDB 接收:
package
mdb;
import
java.util.ArrayList;
import
javax.ejb.MessageDriven;
import
javax.ejb.MessageDrivenContext;
import
javax.jms.JMSException;
import
javax.jms.Message;
import
javax.jms.MessageListener;
import
javax.jms.ObjectMessage;
import
javax.jms.TextMessage;
@MessageDriven
(mappedName =
"dizzyworldDistributedQueue"
)
public
class
MessageDrivenEJBBean
implements
MessageListener {
private
static
final
boolean
VERBOSE =
true
;
private
int
count =
0
;
private
MessageDrivenContext m_context;
private
int
m_tradeLimit;
public
void
onMessage(Message msg) {
try
{
System.out.println(count++);
System.out.println(msg.getClass());
if
(msg
instanceof
ObjectMessage) {
ArrayList msgList =
(ArrayList)(((ObjectMessage)msg).getObject());
int
numMsgs = msgList.size();
log(
"Received ["
+ numMsgs +
"] Messages"
);
log(
"UOW id: "
+
(((TextMessage)msgList.get(
0
)).getStringProperty(
"JMS_BEA_UnitOfWork"
)));
for
(
int
i =
0
; i < numMsgs; i++) {
log(
"Message["
+ i +
"] "
+
((TextMessage)msgList.get(i)).getText());
}
System.out.println();
}
}
catch
(JMSException jmse) {
// TODO: Add catch code
jmse.printStackTrace();
}
}
private
void
log(String s) {
if
(VERBOSE)
System.out.println(s);
}
}
5. 测试
设定相关类路径并启动发送客户端,示例:java – cp %CLASSPATH% QueueSendUOW t3://172.16.100.102:7001
启动后输入一条或多条消息,输入’quit’完成一个UOW。
将MDB部署到集群中,在WLS的输出信息中,检查消息接收。
- WebLogic JMS的强大功能组合:UOW+SAF+分布式Queue
- WebLogic JMS的强大功能组合:UOW+SAF+分布式Queue
- Weblogic JMS MDB分布式部署
- 使用weblogic jms定时发送的功能列子
- weblogic JMS的建立
- springboot集成weblogic的jms
- SAF
- saf
- SAF
- Jms Topic和Queue的比较
- WAS 中配置JMS Queue的注意事项
- JMS入门(三)--Queue的使用
- JMS Topic 和queue 的区别
- JMS入门(三)--Queue的使用
- JMS入门(三)--Queue的使用
- JMS入门(三)--Queue的使用
- JMS入门(三)--Queue的使用
- weblogic上配置jms服务的方法
- 我自己重写 Ext.form.TwinTriggerField ,文本框点击后面按钮,弹出 Window 页面,选择值
- HTML5手机游戏将迎美好未来
- 通共类注意事项
- android apk安装原理分析
- oracle: OCA-047-题解与实验(8)--CUBE和ROLLUP的用法
- WebLogic JMS的强大功能组合:UOW+SAF+分布式Queue
- SNS平台与第三方APP的JS通信实现
- extjs4做的grid,带分页,搜索
- dd examples
- Java 与 JSON 入门
- ATM
- 一个设计师的心声[分享篇别人写的文章,感觉确实挺...]
- android installd分析
- awk工具