Spring Web Flow锁定超时异常

16
我们正在Weblogic 10群集环境中使用Spring Web Flow(2.0.9)。在生产环境中,我们经常会遇到LockTimeoutException: Unable to acquire conversation lock after 30 seconds的异常。

我一直在试图弄清楚为什么只有单击或访问站点主页时,有些情况下会发生上述异常。请查找尝试锁定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();
        }
    }
}
2个回答

21

Spring Webflow是一个状态机,可以在不同的状态之间执行转换,这些状态可能有关联的视图。同时执行多个转换是没有意义的,因此SWF使用锁系统来确保每个流程执行(或对话)一次只处理一个HTTP请求。

不要过于纠结于ReentrantLock的概念,它只是防止同一线程等待它已经持有的锁。

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

LockTimeoutException很难进行故障排除,因为根本问题不是抛出异常的线程。 LockTimeoutException之所以发生是因为另一个早期请求的处理时间超过了30秒,因此最好找出早期请求为什么需要如此长时间。

故障排除的想法:

  • 实现一个FlowExecutionListener,测量每个请求花费的时间,并记录带有flowId、stateId和转换事件的长时间请求,这将允许您专注于长时间运行的请求。
  • 避免LockTimeoutException的一种好方法是,在单击按钮/链接后使用JavaScript禁用提交按钮和链接。显然,这并不能解决初始超过30秒的请求问题。

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

最后,你提到:

我一直在试图弄清楚为什么只有单击一个按钮或访问站点主页时,上述异常何时出现。

我建议您尝试使用浏览器的开发者工具窗口打开,观察“Network”选项卡,可能会有一个正在后台运行的AJAX请求正在持有锁。


1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接