门户中的资源挂起线程应急解决方案
业务任务
您的门户出现用户请求在资源中挂起情况的频率是多高?我希望这种情况不经常发生。然而,如果出现了这种情况,而且资源不断挂起用户请求,则门户会面临耗尽所有已配置的并发用户请求并最终崩溃的致命风险。这将是一场灾难。我碰到过几次这样的情况,并决定保护我的门户不再受类似情况的影响。
我们需要让门户包含几个具有登录控件(通过用于每个Portlet的备份文件提供)的Portlet。对于每个请求,创建一个备份文件,备份文件在用户请求方面是线程安全的。在登录控件中,备份文件的init()方法(或preRender()方法)调用独立的安全服务(资源)API以获得资源访问授权。对于业务处理,Portlet也通过其他API调用将用户请求委托到业务层。一切都运行正常,直到一个对资源的调用未返回到Portlet,即,由于某种原因,它在某处挂起了。以下是一个具体示例。
我们假定WebLogic Portal使用EJB作为业务层和/或安全服务中的资源。此EJB操作其他资源,并通过使用JMS发送消息的方式报告处理状态。此EJB与其他应用程序一起部署在集群中。门户部署在另一个物理机器上。如果共同部署的一个应用程序引发了内存错误,则整个集群(包括EJB)都会挂起,即它不返回请求也不抛出异常。事实上,讨论如此显著的失效是没有必要的:从门户的角度来说,“挂起”模式仅是门户的动态并发生命周期中的一种返回得过慢、延迟过久以至于不能接受的响应。例如,延迟可能由于服务器过载或数据库出现问题引起,但这是不相干的——备份文件中的线程运行时间超出了正常门户工作的允许范围,达到了门户中的“最大并发用户数”。此门户完全停止接受用户请求——这就成了问题。
解决方案设计
我首先想到的是,在Portlet用于访问其资源的RMI客户端(即EJB客户端)上设置超时(远程-客户端-超时)。然而,关于使用RMI超时的WebLogic指导原则列出了关于此类超时的几条限制,其中包括“在调用中不涉及JMS资源。”这就是说,不能对EJB资源使用超时。我提及这种情况只是为了说明存在门户可能未被保护以不受挂起的资源线程影响的情况。即使没有关于超时的限制,如果请求挂起的速度快于超时释放相关线程的速度,问题就依然存在。
我想介绍一种针对此问题的可能解决方案。此解决方案在下面的条件下有效:门户具有一些独立于可能会挂起的资源的内容或功能。就是说,门户可以运行部分功能。
此解决方案包括3个组件:监控、决策规则和规则实施方法。此解决方案的原理很简单:门户监控运行中的资源调用,从而监控被调用的资源线程,对运行过久的资源线程的数量进行计数(riskCounterValue),然后应用决策规则,如“如果riskCounterValue达到或超出预定义的阈值(riskThreshold),则所有传入的对此资源的调用均被拒绝,直到riskCounterValue小于riskThreshold。”使用此规则可以限制可能“挂起”的资源线程数量,而且可能使用简化功能处理用户请求。例如,如果门户包含4个Portlet,用于一个Portlet的某些资源线程被认为“存在挂起的风险”,则门户可以跳过存在风险的Portlet而仅对用户显示3个Portlet。
规则实施方法的实现非常重要。如果此规则在每个调用的范围内执行,我们可以预见性能会降低,但是可以轻松地控制可能“挂起”的资源线程。如果此规则在调用以外执行,我们可以保持性能,但是对此类控制的调整是需要技巧的。我们将详细讨论后一种情况。图1的图描述了这种情况。
如图所示,在第一步中,门户初始化一个Helper对象,而此Helper对象则初始化一个CallRegistry对象。后者可作为java.util.HashMap实现,并用于注册所有对资源API的调用。然后Helper启动一个watchdog线程。例如,如果使用Struts,则此线程就在模型中启动。watchdog线程定期检查CallRegistry中的记录,对运行时间过长的调用数量进行计数,并将其设置为Helper中的riskCounterValue变量。
假定我们大概知道API调用的正常执行时间。该值(最长持续时间)可以用于所有的API,或者每个API可以具有其单独的执行时间。因此,当调用一个API方法时,我们可以计算此API在正常情况下预期完成的时间,例如:
java.lang.System.currentTimeMillis()
long apiExecutionTime = ...;// property
long timeToComplete =
java.lang.System.currentTimeMillis() + apiExecutionTim
当调用Helper的方法时,它将一条新记录添加进CallRegistry。此记录包括一个惟一的调用ID(用作java.util.HashMap中的键)和用于API的预期完成时间(timeToComplete)(用作java.util.HashMap中的值)。如果此方法成功完成,它会从CallRegistry移除其记录。
让我们来看一下用户请求是如何处理的。接到用户请求后,Portlet的备份文件将其委托给Helper API方法(后者调用资源API)。首先,此Helper API方法检查其是否可以执行。如果接到请求的时候尚未达到riskThreshold,则此Helper API方法继续运行。否则,它会抛出一个异常,门户会继续下一项功能或下一个API调用。
仅在运行时间过长的资源线程数量(riskCounterValue)小于riskThreshold的情况下才可以赋予执行的权限。通过配置属性设置riskThreshold。例如,如果将并发用户请求最大值配置为25,则riskThreshold可以设置为10。这就是说,门户处理并发用户请求的能力仅存在一半风险,它在资源线程开始挂起的情况下仍然可以运行。
请注意我们不对运行时间过长的API调用进行任何操作。它们中的一些最终可以成功完成,Helper API方法会将其记录从CallRegistry移除,即下一次计数可能会低于riskThreshold,下一次针对资源的用户请求可能不会被拒绝(通过抛出异常的方式)。
门户无法知道网络中是否存在意外延迟或者资源线程是否确实挂起。因此,推荐在几个顺序控制周期中达到或超出riskThreshold时给操作团队发送一个通知(例如,通过电子邮件)。收到的通知允许操作团队迅速分析日志,及时找到并解决运行时间过长的调用的原因。
分析和调整
对“挂起”的资源线程的控制具有很大的动态性,要对其进行调整并不是一件简单的事。其效果是基于对以下3个参数的权衡:
- 用户请求之间的平均时间(TUR)与watchdog线程控制周期(风险控制周期)之间的时间(TRC)的比率:R = TUR / TRC
- 用于特定资源的风险阀值(riskThreshold)
- 资源API调用的预期执行时间
对控件的研究和测试得出的结论是,参数调整取决于特定的门户实现,但具有共同的趋势。图2中的图表展示了用于调整的准则。在测试中,比率被设为R = 95%,TUR为95[ms],TRC被设为100[ms]。通常,可靠的比率是90%或更高。
此图表显示“挂起”的API调用数(在控件中计数)是如何取决于调用执行时间的。图表中的点代表风险控制周期之间挂起的用户请求的最大数量,即在针对给定调用执行时间而进行的一系列测试中的riskCounterValue最大值。请记住,在实施决策规则时,一些用户请求被拒绝,而“挂起”的资源线程数量不会增加。
图2中的水平红线标记门户中所允许的最大并发用户数量。控件的目的是将最大riskCounterValue严格保持在红线以下。图表中的点越接近红线,就越可能达到或超出riskThreshold。
我们可以看到,控制的行为不明显。对于某些调用执行时间值(从3250ms到1500ms),控件生成用户请求,“挂起”的资源线程数量接近并超出门户允许的并发用户最大值。在此间隔期间,控制在给定条件下是无效的。同时,控制在从100ms到1000ms和从3500ms到4000ms的2个间隔中是有效的:具有特定riskThreshold的决策规则可靠地保护门户不受“挂起”的API调用的影响,并保留足够的并发请求线程以服务其他用户请求。
此图表还显示较小的riskThreshold可提供较好的保护。但是,如果将一个资源的riskThreshold设置得过低,资源可能仅仅由于网络延迟的轻微波动就在大多数用户会话中不可用。这是另一个主题了:平衡和调整。
结束语
这套关于“挂起”的资源调用的运行时控制的推荐解决方案允许门户隔离有问题的资源,并使用余下的资源继续运行,从而最大程度地减小对性能的影响。此解决方案的效果取决于以下几个调整参数:请求频率和风险控制周期频率的比率、风险阀值的值和预期的调用执行时间。
这种情况下的调整不是一件容易的事——它需要密集的测试。此外,本文中给出的数字是特定于我的测试门户的,即使您发现了相关性,在您的门户上进行的测试中使用的应该是其他值。另一方面,如果某种程度的性能降低是可以接受的,则推荐在每个API调用的范围内执行风险控制周期,以显著简化解决方案参数的调整。
参考资料
- WebLogic RMI特性和指导原则:关于使用RMI超时的指导原则http://e-docs.bea.com/wls/docs81/rmi/rmi_api.html
- Nyberg, G.、Patrick, R.、Bauerschmidt, P.、McDaniel, J.以及Mukherjee, R.所著的“Mastering BEA WebLogic Server: Best Practices for Building and Deploying J2EE Applications”,Wiley E-Book,2004年3月出版。ISBN: 0-471-48090-8。
原文出处:
http://wldj.sys-con.com/read/185309.htm
作者简介 |
|
Michael Poulin 是一位技术架构师,现供职于华尔街一家大型公司。他是Sun认证的Java技术架构师。过去数年来,他专攻分布式计算、应用程序安全性和SOA。 |