Spring Web Flow LockTimeoutException

Kun*_*Jha 15 spring-webflow weblogic-10.x reentrantlock

我们在Weblogic 10 clustured环境中使用Spring Web Flow(2.0.9).在生产中我们得到了很多LockTimeoutException:30秒后无法获得对话锁定.

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

请在SWF中找到试图锁定FlowController的代码.我无法弄清楚的是锁定在正在访问的servlet上还是其他什么东西?

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

要了解ReentrantLock的概念,请参阅以下链接.

什么是可重入锁定和概念?

提前致谢.

异常堆栈跟踪

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)
Run Code Online (Sandbox Code Playgroud)

在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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Bar*_*man 20

Spring Webflow作为状态机运行,执行可能具有关联视图的不同状态之间的转换.具有多个并发执行转换是没有意义的,因此SWF使用锁定系统来确保每个流执行(或会话)一次只处理一个HTTP请求.

不要过于依赖ReentrantLock的概念,它只是阻止同一个线程等待它已经拥有的锁.

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

LockTimeoutException很难排除故障,因为根问题不是抛出异常的线程.发生LockTimeoutException是因为另一个早期请求花费的时间超过30秒,因此最好找出早期请求花了这么长时间的原因.

疑难解答:

  • 实现一个FlowExecutionListener来测量每个请求所需的时间,并记录长请求以及flowId,stateId和transition事件,这将允许您了解长时间运行的请求.
  • 避免LockTimeoutException本身的一个好方法是在单击按钮/链接后使用javascript禁用提交按钮和链接.显然这并没有解决最初的30秒+请求的问题.

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

最后,你提到:

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

我建议您尝试在浏览器的开发人员工具窗口打开的情况下重新创建问题,观看"网络"选项卡,也许在后台运行一个持有锁的AJAX请求.