[seam-commits] Seam SVN: r9718 - trunk.

seam-commits at lists.jboss.org seam-commits at lists.jboss.org
Thu Dec 4 03:25:04 EST 2008


Author: dan.j.allen
Date: 2008-12-04 03:25:03 -0500 (Thu, 04 Dec 2008)
New Revision: 9718

Added:
   trunk/clustering-howto.txt
Log:
JBSEAM-3397 the clustering how-to


Added: trunk/clustering-howto.txt
===================================================================
--- trunk/clustering-howto.txt	                        (rev 0)
+++ trunk/clustering-howto.txt	2008-12-04 08:25:03 UTC (rev 9718)
@@ -0,0 +1,163 @@
+= Deploying a Seam application into a JBoss AS cluster using HTTP session replication =
+
+The procedure outlined in this tutorial has been validated with an seam-gen application and the Seam booking example.
+
+In the tutorial, I assume that the IP addresses of the master and slave servers are 192.168.1.2 and 192.168.1.3,
+respectively. I am intentionally not using the mod_jk load balancer so that it's easier to validate that both nodes are
+responding to requests and interchanging sessions.
+
+The log messages shown below were generated from the deployment of a WAR application named vehicles.war and its
+cooresponding datasource named vehiclesDatasource. The booking example fully supports this process and you can find instructions on how to deploy it to a cluster in the examples/booking/readme.txt file.
+
+I'm using the farm deployment method in these instructions, though you could also deploy the application normally and
+allow the two servers to negotiate a master/slave relationship based on startup order.
+
+All timestamps have been zeroed out to reduce noise.
+
+== A note about SELinux ==
+
+You might run into problems getting your nodes to see one another if they are on different machines and the machines are
+running RHEL/Fedora. JBoss AS clustering relies on UDP multicasting provided by jGroups. The SELinux configuration that
+ships with RHEL/Fedora blocks these packets by default. You can allow them to pass by modifying the iptables rules (as
+root). The following commands apply to an IP address that matches 192.168.1.x.
+
+  /sbin/iptables -I RH-Firewall-1-INPUT 5 -p udp -d 224.0.0.0/4 -j ACCEPT
+  /sbin/iptables -I RH-Firewall-1-INPUT 9 -p udp -s 192.168.1.0/24 -j ACCEPT
+  /sbin/iptables -I RH-Firewall-1-INPUT 10 -p tcp -s 192.168.1.0/24 -j ACCEPT
+  /etc/init.d/iptables save
+
+== A note about SFSBs ==
+
+If you are deploying an application with SFSBs and HTTP session replication to a JBoss AS cluster, you must ensure that your SFSB classes are annotated with @Clustered (from the JBoss EJB 3 annotation API) or marked as clustered in the jboss.xml descriptor. See the booking example for details.
+
+With that out of the way, it's time to get started.
+
+== Tutorial ==
+
+1. Create two instances of JBoss AS (just extract the zip twice)
+2. Deploy the JDBC driver to server/all/lib/ on both instances if not using HSQLDB
+3. Add <distributable/> as the first child element in WEB-INF/web.xml
+4. Set the distributable property on org.jboss.seam.core.init to true to enabled the ManagedEntityInterceptor
+  (i.e., <core:init distributable="true"/> in WEB-INF/components.xml)
+5. Bind a new IP address to the NIC 
+
+  /sbin/ifconfig eth1:2 192.168.1.3
+
+replace eth1 with your interface name and make the IP address conform to your network
+
+6. Start the master JBoss AS instance on the first IP:
+
+  ./bin/run.sh -c all -b 192.168.1.2
+
+You should see the following in the log:
+
+00:00:00,000 INFO  [DefaultPartition] Number of cluster members: 1
+00:00:00,000 INFO  [DefaultPartition] Other members: 0
+00:00:00,000 INFO  [DefaultPartition] Fetching state (will wait for 30000 milliseconds):
+00:00:00,000 INFO  [DefaultPartition] State could not be retrieved (we are the first member in group)
+
+7. Verify that the server/all/farm directory is empty in the slave JBoss AS instance
+8. Start the slave JBoss AS on second the IP
+
+  ./bin/run.sh -c all -b 192.168.1.3
+
+Should see the following in the log:
+
+00:00:00,000 INFO  [DefaultPartition] Number of cluster members: 2
+00:00:00,000 INFO  [DefaultPartition] Other members: 1
+00:00:00,000 INFO  [DefaultPartition] Fetching state (will wait for 30000 milliseconds):
+00:00:00,000 INFO  [DefaultPartition] state was retrieved successfully (in 120 milliseconds)
+
+Back in the first instance's log you should see acknowledgement of the new member:
+
+00:00:00,000 INFO  [DefaultPartition] I am (192.168.1.2:1099) received membershipChanged event:
+00:00:00,000 INFO  [DefaultPartition] Dead members: 0 ([])
+00:00:00,000 INFO  [DefaultPartition] New Members : 1 ([192.168.1.3:1099])
+00:00:00,000 INFO  [DefaultPartition] All Members : 2 ([192.168.1.2:1099, 192.168.1.3:1099])
+
+9. Deploy the -ds.xml to server/all/farm of the master instance
+
+In the log of the master instance you should see acknowlegement of this deployment:
+
+00:00:00,000 INFO  [ConnectionFactoryBindingService] Bound ConnectionManager 'jboss.jca:service=DataSourceBinding,name=vehiclesDatasource' to JNDI name 'java:vehiclesDatasource'
+00:00:00,000 INFO  [ClusterFileTransfer] Start push of file vehicles-ds.xml to cluster.
+00:00:00,000 INFO  [ClusterFileTransfer] Finished push of file vehicles-ds.xml to cluster.
+
+In the log of the slave instance you should see a complimentary message:
+
+00:00:00,000 INFO  [FarmMemberService] farmDeployment(), deploy locally: farm/vehicles-ds.xml
+00:00:00,000 INFO  [ConnectionFactoryBindingService] Unbound ConnectionManager 'jboss.jca:service=DataSourceBinding,name=vehiclesDatasource' from JNDI name 'java:vehiclesDatasource'
+
+10. Deploy the application to the server/all/farm directory
+
+In the log of the master instance you should see acknowlegement of this deployment after the normal application startup
+messages have finished:
+
+00:00:00,000 INFO  [ClusterFileTransfer] Start push of file vehicles.war to cluster.
+
+Wait ~3 minutes for the deployed archive to be transferred (I don't know why it takes so long)
+
+In the log of the master instance you should see acknowlegement of this deployment prior to the normal application
+startup messages:
+
+00:00:00,000 INFO  [FarmMemberService] farmDeployment(), deploy locally: farm/vehicles.war
+
+Once the application is transfered, you should see confirmation in the log of the master instance:
+
+00:00:00,000 INFO  [ClusterFileTransfer] Finished push of file vehicles.war to cluster.
+
+Then you should see the application startup messages appear in the slave instance.
+
+You're application is now running in a cluster with HTTP session replication! But, of course, you are going to want to
+validate that the clustering actually works.
+
+= Validating the distributable services of an application running in a cluster =
+
+It's all well and fine to see the application start successfully on two different JBoss AS servers, but seeing is
+believing. You likely want to validate that the two instances are exchanging HTTP sessions to allow the slave to take
+over when the master instance is stopped.
+
+Start off by visiting the application running on the master instance in your browser. That will produce the first HTTP
+session. Now, open up the JBoss AS JMX console on that instance and navigate to the following MBean:
+
+category: jboss.cache
+entry: service=TomcatClusteringCache
+method: printDetails()
+
+Invoke the printDetails() method. You will see a tree of active HTTP sessions. Verify that the session your browser is
+using corresponds to one of the sessions in this tree. Here is a shortcut for invoking that method:
+
+  http://192.168.1.2:8080/jmx-console/HtmlAdaptor?action=invokeOpByName&name=jboss.cache%3Aservice%3DTomcatClusteringCache&methodName=printDetails
+
+Now switch over to the slave instance and invoke the same method in the JMX console. You should see an identical list
+(at least underneath this application's context path). Here's the shortcut to that method.
+
+  http://192.168.1.3:8080/jmx-console/HtmlAdaptor?action=invokeOpByName&name=jboss.cache%3Aservice%3DTomcatClusteringCache&methodName=printDetails
+
+So you can see that at least both servers claim to have identical sessions. Now, time to test that the data is
+serializing and unserializing properly.
+
+Sign in using using the URL of the master instance. Then, construct a URL for the second instance by putting the
+;jsessionid=XXXX immediately after the servlet path and changing the IP address. You should see that the session has
+carried over to the other instance. Now kill the master instance and see that you can continue to use the application
+from the slave instance. Remove the deployments from the server/all/farm directory and start the instance again. Switch
+the IP in the URL back to that of the master instance and visit the URL. You'll see that the original session is still
+being used.
+
+One way to watch objects passivate and activate is to create a session- or conversation-scoped Seam component and
+implement the appropriate life-cycle methods. You can either use methods from the HttpSessionActivationListener
+interface (Seam automatically registers this interface on all non-EJB components):
+
+  public void sessionWillPassivate(HttpSessionEvent e);
+  public void sessionDidActivate(HttpSessionEvent e);
+
+or you can simply mark two no-argument public void methods with @PrePassivate and @PostActivate, respectively. Note that
+the passivation step occurs at the end of every request, while the activation step occurs when a node is called upon.
+
+The really nice part about Seam is that it is working very hard to make replication transparent by automatically keeping
+track of dirty object and ensuring that they are propagated. All you need to do is maintain a dirty flag on your
+session- or conversation-scoped component. Seam automatically takes care of JPA entity instances for you.
+
+= Notes and outstanding issues =
+
+* transient fields aren't always reinitialized, required a fix to SecurityInterceptor; might show up elsewhere




More information about the seam-commits mailing list