dev2dev 首页 > 资源中心 > 技术文章
使用WebLogic Portal、Tangosol Coherence和WSRP在联邦门户中共享数据
Web Services for Remote Portlets (WSRP)协议被设计用来支持驻留在任意门户服务器或服务器集群上的门户的联邦,开发人员利用WSRP来聚合来自驻留在远程其他门户上的各种portlet的内容和用户界面(UI)。但是,WSRP本身并没有解决实现可伸缩、可靠、高性能的联邦门户来创建、访问在分布式portlet中共享的数据并对其生命周期进行管理的挑战。幸运的是,BEA WebLogic提供了对WSRP规范的扩展,它与Tangosol Coherence结合起来,就可以允许WSRP生产者和消费者以一种可伸缩、可靠和高性能的方式来创建、查看、修改共享的限定作用域的数据并控制对它的并发访问。
例子
为了赢得业务,银行已经将贷款申请过程(包括贷款批准)转移到网络上。考虑一个使用WebLogic Portal构建的银行应用程序,它包含了一份带自动批准处理的在线贷款申请书。该应用程序架构需要一种集群式的网关门户应用程序,它可以让终端用户直接访问,但是它还聚合了多个部署在分散的WebLogic Portal集群中的portlet,这些终端用户不能直接访问。这些portlet包括:收集申请人基本信息(比如姓名、地址、社会保险号码(SSN)和收入)的portlet;执行申请人姓名和SSN验证的portlet;执行信用检查的portlet;对完成的申请执行风险分析的portlet。
网关门户通过利用WSRP动态地装配来自远程portlet的内容与UI,来调整贷款申请的过程。根据定义,网关应用程序是WSRP消费者,而远程portlet应用程序则是WSRP生产者。在贷款申请过程中,有时消费者会将生产者一起呈现,有时也可以单独呈现。该过程由WSRP消费者发起,它创建LoanApplication类的实例,该对象的作用域为终端用户的HTTP会话。随后各种生产者将访问并修改该LoanApplication对象中所包含的信息:
- 在处理过程中,一些生产者需要对LoanApplication对象作只读访问,而另一些却需要作互斥的写访问。
- 因为LoanApplication对象可能非常大,所以每个生产者必须能够以接近内存访问的速度进行访问。
- 当填充LoanApplication对象时,数据不会因为任何一个WebLogic Portal JVM过早终止而丢失,这一点极为重要。
当一个已批准的贷款申请完成后,消费者网关会将来自LoanApplication对象的信息写入中心数据库,例如,以XML文档的形式。
图1描述了该应用程序的逻辑架构:

图1. 应用程序的逻辑架构(单击图像查看大图)
图字:
Application that collects name,address,SSN and income information:收集姓名、地址、SSN以及收入信息的应用程序
Portal:门户
Portlet Application:Portlet应用程序
Applicationthat performs user verification:执行用户验证的应用程序
Applicationthat performs credit check:执行信用检查的应用程序
Risk analysis applicationthat determines if the application is approved,declined or requires more information:确定申请是否被批准、拒绝或需要其他信息的风险分析应用程序
Large XML document representing the LoanApplication object shared and maintained by all federated applications:表示由所有联邦应用程序所共享和维护的LoanApplication对象的非常大的XML文档
问题
对于访问共享数据的生产者应用程序而言,必须使得在每一次WSRP请求期间,在消费者和生产者之间能够传递信息。然而当前的WSRP规范没有提供通过WSRP请求进行任意数据传递的机制。因此WSRP对于在消费者和生产者之间传递共享数据而言并不是一种合适的机制。
即使WSRP对于数据交换有规定,它也不会是在消费者及其生产者之间反复转移大量数据的最优机制,因为毫无疑问底层SOAP传输效率是非常低的。SOAP最适合在两个端点之间传递比较少的文本数据。此外,将LoanApplication对象序列化和将XML文档反序列化也将非常耗费时间和资源,而且生成的XML文档也可能相当大。
解决方案
WebLogic Portal包含了一个WSRPCustom Data Transfer扩展,允许开发人员在消费者和生产者之间传递数据。为了支持自定义数据传输,一个门户开发人员创建了一个JspBacking实现,向相关生命周期方法中的当前HTTP请求添加自定义的请求状态,并将自定义的JspBacking实现与消费者代理portlet绑定。
在生产者portlet中,portlet可以从HTTP请求获取任何必需的自定义请求状态,并向HTTP请求添加任何自定义响应状态。
在消费者的自定义JspBacking实现中,从HTTP请求获取任何自定义的响应状态也是可能的。
Custom Data Transfer机制将自定义状态转换成文本形式,并在WSRP请求和响应期间将其添加至WSRP SOAP XML文档,因此它最适合传输少量数据。然而在本例中,共享信息未必是LoanApplication数据本身——它可以是一个用于从外部数据存储区(比如中心数据库)提取文档的关键字或cookie。当然,这要求在将对象写入数据存储区时将其转换成一种数据存储友好的格式,然后在从数据存储区读取时将其再转换成Java对象。
基本实现
图2中的顺序图展示了实现此解决方案的基本方法的相关步骤:

图2. 基本实现(单击图像查看大图)
图字:
Consumer:消费者
Producer:生产者
DB:数据库
Createa new HttpSession:创建新的HttpSession
Createa new LoanApplication:创建新的LoanApplication
Add LoanApplication to theHttpSession:将LoanApplication添加到HttpSession
Convert a LoanApplication to XML:将LoanApplication转换为XML
Store LoanApplication XML by session ID:通过会话ID存储LoanApplication XML
Add session ID to WSRP request:将会话ID添加到WSRP请求
WSRP request:WSRP请求
Extract HTTP session ID:提取HTTP会话ID
Read LoanApplication XML by session ID:通过会话ID读取LoanApplication XML
Create LoanApplication from XML:从XML创建LoanApplication
Modify LoanApplication:修改LoanApplication
Convert LoanApplication to XML:将LoanApplication转换为XML
Store LoanApplication XML by session ID:通过会话ID存储LoanApplication XML
Add modified flag to WSRP response:将修改后的标记添加到WSRP响应
WSRP response:WSRP响应
Extract modified flag from WSRP response:从WSRP响应提取修改后的标记
Read LoanApplication XML by session ID:通过会话ID读取LoanApplication XML
Create LoanApplication from XML:从XML创建LoanApplication
Add LoanApplication to theHttpSession:将LoanApplication添加到HttpSession
使用这种方法,LoanApplication对象可以使用以下策略在消费者和生产者之间进行共享:
- 当开始一个新的用户HTTP会话时,消费者应用程序创建一个初始LoanApplication对象,并将其保存至用户的会话中。应用程序还将对象写入中心数据库的表格中,以会话标识符作为关键字保存“处理中的”贷款申请记录。
- 因为数据的作用域被限定在用户HTTP会话中,LoanApplication对象必须实现HttpSessionBindingListener接口,一旦从会话中解除绑定就从数据库中移除自身。或者,通过周期性地扫描“处理中的”贷款申请表也可以从数据库中删除过期记录。
- 在WSRP请求期间,自定义的JspBacking实现利用WebLogic Portal Custom Data Transfer机制向WSRP请求加入用户HTTP会话标识符。
- 当生产者需要访问共享的LoanApplication对象时,它可以从WSRP请求中提取HTTP会话标识符,并从中心数据库检索该对象。
- 如果生产者需要互斥地访问LoanApplication对象,它可以在处理该对象时通过中心数据库获得一个互斥的写锁定。
- 如果生产者修改LoanApplication对象,它必须将其写回数据库,并向WSRP响应添加自定义响应状态,表示该对象已被生产者修改。
- 在结束WSRP请求时,消费者将检查表示LoanApplication对象已被更新的自定义响应状态,如果找到,用当前存储在数据库中的对象来替换先前的版本,并在用户HTTP会话中保存更新后的对象。
缺点
乍一看,提出的解决方案可以满足贷款申请的需求。然而,它有许多缺点,这使它不能成为一个最佳方案。
最明显的问题是,该解决方案过度地使用了中心数据库来保存一些在理论上经常改变的数据。每一次WSRP请求都需要高达三次的数据库访问:在WSRP请求期间生产者的一次读和一次写,在结束请求时消费者的一次读。这不仅限制了应用程序处理贷款申请数据的性能和可伸缩性,而且对于应用程序整体也有负面影响,尤其当应用程序大量使用数据库时更是如此。这将造成应用程序性能和可伸缩性的降低,还会增加成本。
除了过多的数据库访问之外,上面提出的方案在进行LoanApplication对象与数据库友好格式(比如XML)之间的转换时对CPU的占用量很大。这将消耗重要的CPU资源,还可能对性能产生负面影响。因此,这种方法可能必须购买额外的软件许可和/或硬件。
最后,为了避免在每一次HTTP请求开始时进行额外的数据库读取,LoanApplication对象本身会被写入用户HTTP会话。在集群环境中,这将需要在结束任何对LoanApplication对象作出修改的HTTP请求时将该对象序列化至备份服务器。这将造成过多的网络交互以及额外的序列化与反序列化开销,尤其是在对象相当大的时候。
最佳解决方案
图3中的顺序图展示了对原方法的一些修改,使其有了明显的改善。

图3. 利用Coherence得出的最佳解决方案(单击图像查看大图)
图字:
Createa new HttpSession:创建新的HttpSession
Createa new LoanApplication:创建新的LoanApplication
Add LoanApplication handle to theHttpSession:将LoanApplication句柄添加到HttpSession
Put LoanApplication into NamedCache:将LoanApplication放入NamedCache
Add HTTP session ID to WSRP request:将HTTP会话ID添加到WSRP请求
WSRP request:WSRP请求
Extract HTTP session ID:提取HTTP会话ID
Get LoanApplication from NamedCache:从NamedCache获取LoanApplication
Modify LoanApplication:修改LoanApplication
Put LoanApplication into NamedCache:将LoanApplication放入NamedCache
WSRP response:WSRP响应
Get LoanApplication:获取LoanApplication
Get LoanApplication from NamedCache:从NamedCache获取LoanApplication
通过使用Tangosol Coherence分布式缓存而不是中心数据库来保存共享的贷款申请数据,上面提出的解决方案可以获得极大改进:
- 当开始一个新的用户HTTP会话时,消费者应用程序创建一个初始LoanApplication对象,并以会话标识符作为关键字将其保存至集群化的Coherence NamedCache中。
LoanApplication application = new LoanApplication();
NamedCache cache = CacheFactory.getCache("loan-application");
cache.put(session.getId(), application);
- 因为数据的作用域被限定在用户HTTP会话中,应用程序创建一个实现HttpSessionBindingListener接口的类。一旦从会话中解除绑定,该对象将从保存它的NamedCache中移除对应的LoanApplication对象。注意,保存在会话中的对象不是LoanApplication对象本身,而是一个用作LoanApplication的代表(或句柄)的对象。正因为如此,该对象可以非常小,可以高效地进行序列化与反序列化。
public class LoanApplicationHandle
implements HttpSessionBindingListener, Serializable
{
public void valueBound(HttpSessionBindingEvent event)
{
}
public void valueUnbound(HttpSessionBindingEvent event)
{
String sId = event.getSession().getId();
CacheFactory.getCache("loan-application").remove(sId);
}
}
- 然后消费者向HTTP会话添加LoanApplicationHandle类的实例:
session.setAttribute("loan-application-handle", new LoanApplicationHandle());
- 在WSRP请求期间,自定义的JspBacking实现使用WebLogic Portal Custom Data Transfer机制向WSRP请求添加用户HTTP会话标识符。这使得信息量很小,底层的SOAP传输可以高效实现。
public boolean preRender(HttpServletRequest req, HttpServletResponse res)
{
HttpSession session = req.getSession(true);
SimpleStateHolder state = new SimpleStateHolder();
state.addParameter("session-id", session.getId());
req.setAttribute(MarkupRequestState.KEY, state);
return super.preRender(req, res);
}
- 当生产者需要访问共享的LoanApplication对象时,它可以从WSRP请求中提取HTTP会话标识符,并使用它直接从NamedCache检索LoanApplication:
SimpleStateHolder state = (SimpleStateHolder)
req.getAttribute(MarkupRequestState.KEY);
String sId = (String) state.getParameter("session-id");
NamedCache cache = CacheFactory.getCache("loan-application");
LoanApplication application = (LoanApplication) cache.get(sId);
- 当消费者需要访问共享的LoanApplication对象时,它可以使用HTTP会话标识符来直接从NamedCache检索LoanApplication:
String sId = session.getId();
NamedCache cache = CacheFactory.getCache("loan-application");
LoanApplication application = (LoanApplication) cache.get(sId);
- 如果生产者或者消费者需要对LoanApplication对象进行互斥访问,它可以通过保存它的NamedCache中的一个lock()方法获得对该对象的集群范围的锁定。
NamedCache cache = CacheFactory.getCache("loan-application");
cache.lock(sId, -1);
try
{
LoanApplication application = (LoanApplication) cache.get(sId);
// Perform logic that requires exclusive access to the
// LoanApplication
}
finally
{
cache.unlock(sId);
}
下载
该例子演示了如何将BEA WebLogic Portal的Custom Data Transfer WSRP扩展与Tangosol Coherenc结合起来,对WSRP消费者和生产者共享的、限定作用域的数据进行创建、查看、修改和并发访问管理。这个包内含源代码、配置文件和预建类库。你可以在档案文件根目录下的README.txt文件中查看安装说明。
下载例子:coherence-wsrp.zip
结束语
BEA对WSRP规范的扩展使得应用程序可以向WSRP请求和响应引入附加的状态。这与共享数据存储区结合起来,使得数据能够与用户界面和内容进行联邦。使用Coherence作为共享数据存储区将使应用程序可以以一种可伸缩、可靠、高性能的方式访问联邦数据。在本文的例子中,Coherence的使用完全消除了所有为获取共享的贷款申请数据而对中心数据库进行的访问。并且在将LoanApplication对象存入Coherence NamedCache之前,应用程序不再需要在该对象与中间格式之间进行转换。此外,可能开销极大的对LoanApplication对象的HTTP复制也完全可以避免了。最后,该方案还消除了许多易于出错的任务,比如确保对数据库中贷款申请表的互斥访问,以及清除任何来自数据库的孤立贷款申请。
参考资料
原文出处:Sharing Data among Federated Portals: Using WebLogic Portal, Tangosol Coherence and WSRPhttp://dev2dev.bea.com/pub/a/2005/11/federated-portal-cache.html
| 作者简介 |
|
Jason Howes是Tangosol公司的专职软件工程师,该公司提供内存缓存和数据管理软件解决方案。 |
作者其它文章
|