[seam-commits] Seam SVN: r10052 - branches/enterprise/JBPAPP_4_3_FP01.
seam-commits at lists.jboss.org
seam-commits at lists.jboss.org
Tue Feb 17 05:52:35 EST 2009
Author: manaRH
Date: 2009-02-17 05:52:35 -0500 (Tue, 17 Feb 2009)
New Revision: 10052
Added:
branches/enterprise/JBPAPP_4_3_FP01/clustering-howto.txt
Log:
JBPAPP-1495
Added: branches/enterprise/JBPAPP_4_3_FP01/clustering-howto.txt
===================================================================
--- branches/enterprise/JBPAPP_4_3_FP01/clustering-howto.txt (rev 0)
+++ branches/enterprise/JBPAPP_4_3_FP01/clustering-howto.txt 2009-02-17 10:52:35 UTC (rev 10052)
@@ -0,0 +1,213 @@
+= 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. Have two IP addresses available (two computers, two network cards, or two IP addresses bound to the same interface).
+
+On *nix, you can bind a new IP address to a network interface using the following command:
+
+ /sbin/ifconfig eth1:2 192.168.1.3
+
+Replace eth1 with your interface name and make the IP address conform to your network.
+
+If you're on Windows, follow these steps:
+
+ - Open your network adapter
+ - Click Properties
+ - Select Internet Protocol (TCP/IP) then click Properties
+ - Click Advanced...
+ - Select the IP settings tab and click Add...
+ - Type in an IP address, click Add
+ - Click OK on all open windows
+
+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.
+
+Here are the steps I follow when I test the booking example:
+
+1. Remove all cookies in your browser (or at least the JSESSIONID cookie for the domain 192.168.1.2)
+
+2. Open the booking example on the master instance:
+
+ http://192.168.1.2/seam-booking
+
+3. Sign in using gavin/foobar, then click on the Find Hotels button
+
+4. Get a booking started:
+
+ a. Choose one of the hotels and click its View Hotel link
+ b. Click on the Book Hotel button
+
+5. Build a URL to access the application on the slave instance
+
+ a. Copy the URL in the workspace list at the bottom of the page
+ b. Change 192.168.1.2 to 192.168.1.3
+ c. Get the value of the JSESSIONID cookie from the current page
+ d. Insert ;jsessionid= plus the value of the JSESSIONID cookie before the ? in the URL
+
+6. Visit the URL in a browser that has cookies disabled (the easiest way to ensure the session id in the URL is used)
+
+ links "http://192.168.1.3/seam-booking/book.seam;jsessionid=****?cid=4
+
+7. Complete the booking form and click the Proceed button
+
+8. Now return to the first browser and change the URL to match the confirm page, keeping the cid request parameter
+
+ http://192.168.1.2/seam-booking/confirm.seam?cid=4
+
+9. (optional) Verify you can continue w/o the slave instance running. Go into the JMX console and execute the shutdown() method on jboss.system:type=Server
+
+10. Confirm the booking.
+
+Here's another approach that I wrote before I did the step-by-step:
+
+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