2012-03-02 82 views
12

我们在WebLogic 10 clustured环境中使用Spring Web Flow的(2.0.9)。并在生产中,我们得到了很多LockTimeoutException的:无法在30秒后获得的谈话锁。Spring Web Flow的LockTimeoutException

我一直在试图弄清楚为什么上面的异常出现在某些情况下,只有一次点击或我们正在访问网站本身的主页。

请找正试图在SWF锁定了流量控制器的代码。我无法弄清楚的是锁正在被访问的servlet或其他东西?

请帮助理解在Web应用程序中何时发生哪些资源实际上锁定在SWF中?

要了解ReentrantLock的概念,请参阅下面的链接。

What is the Re-entrant lock and concept in general?

在此先感谢。

异常堆栈跟踪

org.springframework.webflow.conversation.impl.LockTimeoutException: Unable to acquire conversation lock after 30 seconds 
    at org.springframework.webflow.conversation.impl.JdkConcurrentConversationLock.lock(JdkConcurrentConversationLock.java:44) 
    at org.springframework.webflow.conversation.impl.ContainedConversation.lock(ContainedConversation.java:69) 
    at org.springframework.webflow.execution.repository.support.ConversationBackedFlowExecutionLock.lock(ConversationBackedFlowExecutionLock.java:51) 
    at org.springframework.webflow.executor.FlowExecutorImpl.resumeExecution(FlowExecutorImpl.java:166) 
    at org.springframework.webflow.mvc.servlet.FlowHandlerAdapter.handle(FlowHandlerAdapter.java:183) 
    at org.springframework.webflow.mvc.servlet.FlowController.handleRequest(FlowController.java:174) 
    at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48) 
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:875) 
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:807) 
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571) 
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:511) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:727) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:820) 
    at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227) 
    at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125) 
    at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:292) 
    at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:26) 
    at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56) 
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:96) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76) 
    at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56) 

在SWF

package org.springframework.webflow.conversation.impl; 

import java.io.Serializable; 
import java.util.concurrent.locks.ReentrantLock; 

/** 
* A conversation lock that relies on a {@link ReentrantLock} within Java 5's <code>util.concurrent.locks</code> 
* package. 
* 
* @author Keith Donald 
*/ 
class JdkConcurrentConversationLock implements ConversationLock, Serializable { 

    /** 
    * The lock. 
    */ 
    private ReentrantLock lock = new ReentrantLock(); 

    public void lock() { 
     // ensure non-reentrant behaviour 
     if (!lock.isHeldByCurrentThread()) { 
      lock.lock(); 
     } 
    } 

    public void unlock() { 
     // ensure non-reentrant behaviour 
     if (lock.isHeldByCurrentThread()) { 
      lock.unlock(); 
     } 
    } 
} 

回答

18

春Webflow的工作作为一个状态机,这可能有相关的意见不同状态之间的转换执行。它没有意义有多个并发执行的过渡,因此SWF使用锁定系统,以确保每个流执行(或会话)只处理一次一个HTTP请求。

不要太在意ReentrantLock的概念,它只会阻止同一个线程等待它已经拥有的锁。

在回答你的问题时,它只是流程执行(特定对话实例),在请求处理期间被Spring Webflow锁定。服务器仍然会处理来自其他用户的请求,甚至处理来自同一用户的不同流程执行的请求。

LockTimeoutException对于排除故障很棘手,因为根问题不是抛出异常的线程。出现该LockTimeoutException因为另一个较早请求超过30秒花费更长的时间,所以这将是找出为什么早期的要求花了这么长时间是个好主意。

故障诊断思路:

  • 实现一个FlowExecutionListener衡量每个请求花费的时间和日志随着流ID,STATEID和转换事件,这将让你磨练长时间运行的请求长的请求。
  • 避免LockTimeoutException本身的一个好方法是禁用提交按钮&链接使用JavaScript一旦按钮/链接被点击。显然这并不能解决最初的30秒+请求的问题。

您可能会增加LockTimeoutException的超时时间,但这并不能解决实际问题并导致更糟糕的用户体验。 30秒的请求是问题。

最后,你提到:

我一直在试图找出为什么上面的异常进来 某些情况下,当只有一个单一的点击,否则我们访问的网站本身的 主页。

我建议您尝试重新创建问题,浏览器的开发工具窗口打开,看着'网络'选项卡,也许有一个AJAX请求在持有​​锁的背景中运行。