2012-03-02 14 views
12

Stiamo utilizzando Spring Web Flow (2.0.9) nell'ambiente di Weblogic 10 clustured. E in produzione stiamo ottenendo un sacco di LockTimeoutException: Impossibile acquisire il blocco della conversazione dopo 30 secondi.Spring Web Flow LockTimeoutException

Ho cercato di capire perché l'eccezione di cui sopra si verifica in alcuni casi quando c'è un solo clic o si accede alla home page del sito stesso.

Si prega di trovare il codice che sta cercando di bloccare FlowController in SWF. Quello che non riesco a capire è che il blocco è sul servlet a cui si accede o qualcos'altro?

Si prega di aiutare a capire in un'applicazione Web quando si verifica questo blocco quale risorsa è effettivamente bloccata in SWF?

Per comprendere il concetto di ReentrantLock, fare riferimento al collegamento seguente.

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

Grazie in anticipo.

Eccezione dello stack

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) 

Blocco Implementazione in 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(); 
     } 
    } 
} 

risposta

18

Spring Webflow opera come macchina di stato, eseguendo transizioni tra diversi stati che potrebbero avere viste associate. Non ha senso avere più transizioni in esecuzione simultanea, quindi SWF utilizza un sistema di blocco per assicurarsi che l'esecuzione (o la conversazione) di ogni flusso gestisca una sola richiesta HTTP alla volta .

Non restare troppo attaccato al concetto di ReentrantLock, impedisce solo lo stesso thread in attesa su un blocco che già detiene.

In risposta alla domanda, è solo l'esecuzione del flusso (l'istanza di conversazione specifica) bloccata da Spring Webflow per la durata della gestione della richiesta. Il server gestirà comunque richieste di altri utenti o anche richieste dello stesso utente a un'esecuzione di flusso diversa.

LockTimeoutException è difficile da risolvere perché il problema di root non è il thread che genera l'eccezione. L'eccezione LockTimeoutException si verifica perché un'altra richiesta precedente richiede più di 30 secondi, quindi sarebbe una buona idea scoprire perché la richiesta precedente ha richiesto così tanto tempo.

idee risoluzione dei problemi:

  • implementare un FlowExecutionListener che misura quanto tempo ogni richiesta prende, e registrare le richieste a lungo insieme con l'evento flowId, stateId e di transizione, questo vi permetterà di perfezionare in richieste di lunga durata .
  • Un buon modo per evitare la stessa LockTimeoutException consiste nel disabilitare i pulsanti di invio dei collegamenti & utilizzando javascript dopo aver fatto clic su un pulsante/collegamento.Ovviamente questo non risolve il problema della richiesta iniziale di 30 secondi +.

È possibile aumentare il timeout per LockTimeoutException, ma ciò non risolve il problema effettivo e porta a un'esperienza utente peggiore. Richieste di 30 secondi sono il problema

Infine, lei ha citato:

Ho cercato di capire il motivo per cui non sopra eccezione viene in alcuni casi, quando v'è un solo clic o ci si accede al home page del sito stesso .

Suggerisco di provare a ricreare il problema con la finestra degli strumenti di sviluppo del browser aperta, guardando la scheda 'Rete', forse c'è una richiesta AJAX in esecuzione in background che sta tenendo il blocco.