2012-08-23 5 views
10

In esecuzione su JSF 2.0.9, Weblogic 10.3.4. Ora stiamo eseguendo JSF nel nostro ambiente di produzione, ma abbiamo riscontrato alcuni problemi con Session Replication e failover. Usiamo il viewcope per i nostri bean e ho assicurato che siano serializzabili/transitori e che le variabili transitori siano effettivamente apolidi. Tuttavia, il failover della sessione non funziona. Ho fatto test approfonditi e sono riusciti a farlo funzionare impostando i seguenti params in web.xmlFailover sessione JSF e salvataggio parziale stato

<context-param> 
     <param-name>javax.faces.STATE_SAVING_METHOD</param-name> 
     <param-value>client</param-value> 
    </context-param> 


    <context-param> 
     <param-name>javax.faces.PARTIAL_STATE_SAVING</param-name> 
     <param-value>false</param-value> 
    </context-param> 

Se ho impostato STATE_SAVING_METHOD-server ottengo un'eccezione viewexpired in caso di failover. Se ho impostato a client con PARTIAL_STATE_SAVING per true ricevo il seguente errore:

java.lang.IndexOutOfBoundsException: Index: 0, Size: 0 
    at java.util.ArrayList.RangeCheck(ArrayList.java:547) 
    at java.util.ArrayList.get(ArrayList.java:322) 
    at javax.faces.component.AttachedObjectListHolder.restoreState(AttachedObjectListHolder.java:165) 
    at javax.faces.component.UIComponentBase.restoreState(UIComponentBase.java:1433) 
    at com.sun.faces.application.view.StateManagementStrategyImpl$1.visit(StateManagementStrategyImpl.java:265) 
    at com.sun.faces.component.visit.FullVisitContext.invokeVisitCallback(FullVisitContext.java:151) 
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1507) 
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1521) 
    at com.sun.faces.component.visit.VisitUtils.doFullNonIteratingVisit(VisitUtils.java:75) 
    at com.sun.faces.application.view.StateManagementStrategyImpl.restoreView(StateManagementStrategyImpl.java:282) 
    at com.sun.faces.application.StateManagerImpl.restoreView(StateManagerImpl.java:181) 
    at com.sun.faces.application.view.ViewHandlingStrategy.restoreView(ViewHandlingStrategy.java:123) 
    at com.sun.faces.application.view.FaceletViewHandlingStrategy.restoreView(FaceletViewHandlingStrategy.java:448) 
    at com.sun.faces.application.view.MultiViewHandler.restoreView(MultiViewHandler.java:148) 
    at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:187) 
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) 
    at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:111) 
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118) 
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:508) 
    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:301) 
    at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:27) 
    at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:57) 
    at weblogic.servlet.internal.RequestEventsFilter.doFilter(RequestEventsFilter.java:27) 
    at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:57) 
    at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.wrapRun(WebAppServletContext.java:3730) 
    at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3696) 
    at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321) 
    at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:120) 
    at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2273) 
    at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2179) 
    at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1490) 
    at weblogic.work.ExecuteThread.execute(ExecuteThread.java:256) 
    at weblogic.work.ExecuteThread.run(ExecuteThread.java:221) 

Quindi le mie domande sono queste:

  • Is STATE_SAVING_METHOD-client & PARTIAL_STATE_SAVING - false l'unico modo che ho intenzione di far funzionare il failover?
  • Qual è il costo della combinazione client/falsa. Questa memoria/CPU è estesa?
  • Si tratta di un errore e in caso affermativo è risolto in 2.1 o 2.2?

Grazie in anticipo.

risposta

12

Finalmente ho funzionato, ma non senza alcuni bit e bob extra. In primo luogo ho aggiunto quanto segue al web.xml (sì aggressiva sia stato digitato in modo errato):

<context-param> 
     <param-name>com.sun.faces.enableAgressiveSessionDirtying</param-name> 
     <param-value>true</param-value> 
    </context-param> 

Il risparmio client è ora del server e risparmio parziale Stato è falso ancora (vero semplicemente non funziona)

In secondo luogo dopo l'implementazione di HttpSessionAttributeListener ho scoperto che lo com.sun.faces.renderkit.ServerSideStateHelper.LogicalViewMap che contiene lo stato nella sessione è stato aggiunto solo una volta e mai rimosso/aggiunto/sostituito di nuovo. Pertanto, sebbene sia stato aggiornato nella sessione locale, queste modifiche non sono mai state replicate in un secondo jvm. I documenti Weblogic dichiarano che setAttribute deve essere richiamato sugli attributi di sessione affinché la replica funzioni. Per risolvere questo ho creato un ascoltatore fase come segue:

public class ViewPhaseListener implements PhaseListener { 

    public void afterPhase(PhaseEvent phaseEvent) 
    { 

    } 

    public void beforePhase(PhaseEvent phaseEvent) 
    { 
     HttpServletRequest request = ((HttpServletRequest) phaseEvent.getFacesContext().getExternalContext().getRequest()); 
     HttpSession session = request.getSession(); 

     session.setAttribute("com.sun.faces.renderkit.ServerSideStateHelper.LogicalViewMap", session.getAttribute("com.sun.faces.renderkit.ServerSideStateHelper.LogicalViewMap")); 

    } 

    public PhaseId getPhaseId() 
    { 
     return PhaseId.RENDER_RESPONSE; 
      //To change body of implemented methods use File | Settings | File Templates. 
    } 
} 

Questo sostituisce semplicemente l'attributo dopo ogni richiesta e assicura si replica.Come un ulteriore punto che sto limitando i dati memorizzati nelle opinioni con il seguente:

<context-param> 
     <param-name>com.sun.faces.numberOfViewsInSession</param-name> 
     <param-value>3</param-value> 
    </context-param> 

    <context-param> 
     <param-name>com.sun.faces.numberOfLogicalViews</param-name> 
     <param-value>1</param-value> 
    </context-param> 

Spero che questo aiuti chiunque con gli stessi problemi.

0

La replica di sessione deve essere gestita dal servizio di bilanciamento del carico poiché l'applicazione JSF è a conoscenza del contesto nel nodo su cui è distribuita. Pertanto, non dovrebbe essere importante se si imposta STATE_SAVING_METHOD su client o server.

Mi sembra che tu abbia una configurazione di bilanciamento del carico errata. Se stai usando Apache HTTP Server come proxy di consultare il seguente link per maggiori informazioni sul corso di stickyness:

http://httpd.apache.org/docs/2.2/mod/mod_proxy_balancer.html

lo consiglio impostazione ProxySet stickysession = ROUTEID e vedere se questo risolve il problema.

+0

Abbiamo IIS. La replica della sessione viene gestita da weblogic e non dal servizio di bilanciamento del carico. Sticky Sessions è attivo ma non è questo il problema. Il problema è che la sessione fallisce correttamente su una nuova jvm. – andyfinch

+0

Se è stata impostata una sessione persistente sul server weblogic, il server weblogic creerà un cookie con le informazioni sulla sessione utente solo su quel nodo. La mia ipotesi è che questo cookie non viene passato al secondo nodo quando si verifica un failover dal momento che l'istanza weblogic è solo consapevole di se stessa. Ecco perché ho detto che dovresti provare a attivare sessioni appiccicose su Load Balancer perché il bilanciamento del carico è in grado di passare il cookie al secondo nodo. –

+0

Grazie ma non penso di essere stato chiaro nella mia domanda iniziale. La replica della sessione sta accadendo ma non è corretta con le sessioni JSF. Solo una parte della nostra app utilizza JSF nelle sessioni mo e non jsf che si stanno replicando ok. – andyfinch