我们在Weblogic 10集群环境中使用Spring Web Flow(2.0.9)。在生产中,我们得到了很多LockTimeoutException:30秒后无法获取会话锁定。

我一直试图弄清楚为什么在某些情况下,仅单击一次或我们正在访问网站本身的主页时,就会出现上述例外情况。

请在SWF中找到试图锁定FlowController的代码。我不知道锁定是在正在访问的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();
        }
    }
}

最佳答案

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

不要太迷恋ReentrantLock的概念,它只是防止同一线程在已经持有的锁上等待。

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

LockTimeoutException很难解决,因为根本原因不是线程抛出异常。发生LockTimeoutException的原因是另一个先前的请求花费的时间超过30秒,因此,找出为什么先前的请求花费如此长时间的原因是一个好主意。

故障排除思路:


实现一个FlowExecutionListener,它测量每个请求花费的时间,并记录长请求以及flowId,stateId和transition事件,这将使您能够磨合长时间运行的请求。
避免LockTimeoutException本身的一种好方法是,一旦单击按钮/链接,则使用javascript禁用提交按钮和链接。显然,这不能解决最初的30秒以上请求的问题。


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

最后,您提到:


我一直在试图找出为什么出现以上异常
在某些情况下,仅需单击一下或我们正在访问
网站本身的首页。


我建议您在浏览器的开发人员工具窗口打开的情况下,尝试重新创建问题,注意“网络”标签,也许是在后台运行着一个AJAX请求,该请求持有该锁。

关于spring-webflow - Spring Web Flow LockTimeoutException,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9533786/

10-11 04:30