2012-03-02 18 views
12

Estamos utilizando Spring Web Flow (2.0.9) en el entorno de Werthic 10 clustured. Y en producción estamos recibiendo un montón de LockTimeoutException: no se puede adquirir el bloqueo de conversación después de 30 segundos.Spring Web Flow LockTimeoutException

He intentado averiguar por qué la excepción anterior se produce en algunos casos cuando solo hay un clic o estamos accediendo a la página de inicio del sitio.

Encuentra el código que está intentando bloquear FlowController en SWF. Lo que no puedo entender es que el bloqueo está en el servlet al que se está accediendo o en otra cosa.

Por favor, ayúdeme a entender en una aplicación web cuando se produce este bloqueo, ¿qué recurso está realmente bloqueado en SWF?

Para comprender el concepto de ReentrantLock, consulte el siguiente enlace.

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

Gracias de antemano.

Excepción Seguimiento de la pila

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) 

bloqueo Implementación en 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(); 
     } 
    } 
} 

Respuesta

18

Spring Webflow funciona como una máquina de estado, al ejecutar transiciones entre diferentes estados que pueden tener vistas asociadas. No tiene sentido tener múltiples transiciones de ejecución simultáneas, por lo que SWF usa un sistema de bloqueo para asegurarse de que cada ejecución de flujo (o conversación) solo maneje una solicitud HTTP a la vez.

No se obsesione demasiado con el concepto de ReentrantLock, solo evita que el mismo hilo espere en una cerradura que ya tiene.

En respuesta a su pregunta, la ejecución del flujo (la instancia de conversación específica) está bloqueada por Spring Webflow mientras dure el tratamiento de la solicitud. El servidor aún manejará las solicitudes de otros usuarios, o incluso las solicitudes del mismo usuario a una ejecución de flujo diferente.

LockTimeoutException es difícil de solucionar porque el problema de raíz no es el hilo que lanza la excepción. La excepción LockTimeoutException ocurre porque otra solicitud anterior tarda más de 30 segundos, por lo que sería una buena idea averiguar por qué la solicitud anterior tomó tanto tiempo.

ideas de solución de problemas:

  • implementar un FlowExecutionListener que mide el tiempo que cada solicitud se ha realizado, y registrar las solicitudes de largo junto con el evento flowid, IdentificadorEstado y la transición, esto le permitirá afinar en las solicitudes de larga duración .
  • Una buena forma de evitar la LockTimeoutException es deshabilitar los botones de envío & usando Javascript una vez que se ha hecho clic en un botón/enlace.Obviamente, esto no resuelve el problema de la solicitud inicial de 30 segundos.

Puede aumentar el tiempo de espera de LockTimeoutException, pero eso no resuelve el problema real y conduce a una peor experiencia del usuario. Las solicitudes de 30 segundos son el problema.

Por último, usted ha mencionado:

He estado tratando de averiguar por qué no por encima de excepción se presenta en algunos casos cuando sólo hay un solo clic o que está accediendo a la página principal del sitio en sí .

Sugiero que intente volver a crear el problema con la ventana de herramientas del desarrollador del navegador abierta, mirando la pestaña 'Red', tal vez hay una solicitud AJAX ejecutándose en el fondo que mantiene el bloqueo.

Cuestiones relacionadas