Hello, I wonder, is anybody using RAP on a session-replicated cluster?
For the last few days I was trying to get my RAP based project to play nicely in a clustered environment. However, after fixing all the application-related issues, I still see strange behaviour, most likely caused by RAP. The environment is rather tricky: 2x Tomcat application servers + Apache+mod_jk round-robin load balancer The load-balancer is alternating between the two Tomcat instances for every request, which means high requirements regarding session replication consistency. Unfourtunately the environment is as-is, later the application has to run in an environment behaving like this one. RAP is configured with OperationMode.SESSION_FAILOVER and <distributable/> and in principle, session replication seems to work. Tomcat was configured with SimpleTcpCluster and channelSendOptions="6" (synchrounous session replication with ACK - according to the tomcat users mailing list the strictest setting Tomcat has.). However even with the simple example below, I get strange behaviour and issues: https://youtu.be/p5u2z-NjIs0 Sometimes request/response pairs are sent for 30s. And for a larger real-world app I also get sometimes: - HTTP-500 and HTTP-412 - ConcurrentModificationException during Session Serialization (Collection is modified concurrently while being serialized) - Various other exceptions listed below. - ClientListener is not Serializeable I had a look at RAP's source, but I am a bit lost: * ClientListener not implementing Serializeable was easy to fix and seems to work. * I guess the ConcurrentModificationException during seerialization is tough and it seems I am not the only one expoeriencing this: https://www.eclipse.org/forums/index.php/t/532053/ I wrote my own servlet filter (running before/after RWTClusterSupport) serializing all session attributes to disk, *removing* the attributes, and re-loading them again at the next request and ran into issues of UISessionImpl.attributes beeing empty. I saw UISessionImpl.get/setAttribute is synchronized, is this supposed to be accessed by multiple threads? If so, synchronization has no effect on the app servers synchronization during session replication - it will simply snapshot some inconsistent state). * What could cause the client to immediatly re-execute a new request after receiving a response? Maybe this could be a starting point to debug the request/response storms I am experiencing. Thank you in advance and best regards, Clemens public class BasicEntryPoint extends AbstractEntryPoint { protected void createContents(Composite parent) { Tree tree; ScrolledComposite scroll = new ScrolledComposite(parent, SWT.V_SCROLL); tree = new Tree(scroll, SWT.BORDER); scroll.setContent(tree); scroll.setExpandHorizontal(true); scroll.setExpandVertical(true); tree.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent se) { if(tree.getSelectionCount() > 0) { TreeItem item = tree.getSelection()[0]; item.setText(item.getText() + "_"); }} }); for(int i=0; i < 10; i++) { TreeItem item = new TreeItem(tree, SWT.NONE); item.setText("MainItem " + i); for(int m=0; m < 10; m++) { TreeItem childItem = new TreeItem(item, SWT.NONE); childItem.setText("Child: "+m); } } } } Tomcat cluster configuration: <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="6"> <Manager className="org.apache.catalina.ha.session.DeltaManager" expireSessionsOnShutdown="false" notifyListenersOnReplication="true"/> <Channel className="org.apache.catalina.tribes.group.GroupChannel"> <Membership className="org.apache.catalina.tribes.membership.McastService" address="228.0.0.4" port="45564" frequency="500" dropTime="3000"/> <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="192.168.56.102" port="4000" autoBind="100" selectorTimeout="5000" maxThreads="6"/> <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter"> <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/> </Sender> <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/> <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/> </Channel> <Valve className="org.apache.catalina.ha.tcp.ReplicationValve" filter=""/> <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/> <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer" tempDir="/tmp/war-temp/" deployDir="/tmp/war-deploy/" watchDir="/tmp/war-listen/" watchEnabled="false"/> <!-- <ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/> --> <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/> </Cluster> - java.lang.NullPointerException at org.eclipse.rap.rwt.SingletonUtil.getUniqueInstance(SingletonUtil.java:74) at org.eclipse.rap.rwt.internal.lifecycle.RequestCounter.getInstance(RequestCounter.java:25) at org.eclipse.rap.rwt.internal.service.LifeCycleServiceHandler.isRequestCounterValid(LifeCycleServiceHandler.java:133) at org.eclipse.rap.rwt.internal.service.LifeCycleServiceHandler.processUIRequest(LifeCycleServiceHandler.java:94) at org.eclipse.rap.rwt.internal.service.LifeCycleServiceHandler.synchronizedService(LifeCycleServiceHandler.java:75) at org.eclipse.rap.rwt.internal.service.LifeCycleServiceHandler.service(LifeCycleServiceHandler.java:66) at org.eclipse.rap.rwt.engine.RWTServlet.handleValidRequest(RWTServlet.java:135) at org.eclipse.rap.rwt.engine.RWTServlet.handleRequest(RWTServlet.java:117) at org.eclipse.rap.rwt.engine.RWTServlet.doPost(RWTServlet.java:107) java.lang.NullPointerException org.eclipse.swt.graphics.ImageSerializer.getResourceManager(ImageSerializer.java:95) org.eclipse.swt.graphics.ImageSerializer.access$1(ImageSerializer.java:94) org.eclipse.swt.graphics.ImageSerializer$PostDeserializationValidation$1.run(ImageSerializer.java:53) org.eclipse.rap.rwt.internal.engine.PostDeserialization.runProcessors(PostDeserialization.java:28) org.eclipse.rap.rwt.internal.engine.RWTClusterSupport.beforeService(RWTClusterSupport.java:62) org.eclipse.rap.rwt.internal.engine.RWTClusterSupport.beforeService(RWTClusterSupport.java:53) org.eclipse.rap.rwt.internal.engine.RWTClusterSupport.doFilter(RWTClusterSupport.java:41) java.lang.NullPointerException org.eclipse.rap.rwt.internal.service.LifeCycleServiceHandler.shutdownUISession(LifeCycleServiceHandler.java:148) org.eclipse.rap.rwt.internal.service.LifeCycleServiceHandler.synchronizedService(LifeCycleServiceHandler.java:80) org.eclipse.rap.rwt.internal.service.LifeCycleServiceHandler.service(LifeCycleServiceHandler.java:66) org.eclipse.rap.rwt.engine.RWTServlet.handleValidRequest(RWTServlet.java:135) org.eclipse.rap.rwt.engine.RWTServlet.handleRequest(RWTServlet.java:117) org.eclipse.rap.rwt.engine.RWTServlet.doPost(RWTServlet.java:107) java.lang.NullPointerException at org.eclipse.rap.rwt.internal.lifecycle.LifeCycleUtil.getSessionDisplay(LifeCycleUtil.java:37) at org.eclipse.rap.rwt.internal.lifecycle.LifeCycleUtil.getSessionDisplay(LifeCycleUtil.java:31) at org.eclipse.rap.rwt.internal.lifecycle.SimpleLifeCycle.execute(SimpleLifeCycle.java:48) at org.eclipse.rap.rwt.internal.service.RWTMessageHandler.executeLifeCycle(RWTMessageHandler.java:57) at org.eclipse.rap.rwt.internal.service.RWTMessageHandler.handleMessage(RWTMessageHandler.java:41) at org.eclipse.rap.rwt.internal.remote.MessageChainElement.handleMessage(MessageChainElement.java:29 _______________________________________________ rap-dev mailing list rap-dev@eclipse.org To change your delivery options, retrieve your password, or unsubscribe from this list, visit https://dev.eclipse.org/mailman/listinfo/rap-dev