How to Run ZK on Apache + Tomcat clustering, Part II

From Documentation
Revision as of 02:17, 14 December 2010 by Char (talk | contribs) (→‎Introduction)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
DocumentationSmall Talks2007MayHow to Run ZK on Apache + Tomcat clustering, Part II
How to Run ZK on Apache + Tomcat clustering, Part II

Author
Ian Tsai, Engineer, Potix Corporation
Date
May 17, 2007
Version
  1. Apache 2.2.4 latter
  2. Apache JK Connector 1.2.22
  3. Apache-Tomcat-5.5.X
  4. ZK freshly
  5. Eclipse3.2


Introduction

Last time in How to Run ZK on Apache + Tomcat clustering, Part I, I introduced how to build a simple environment to run ZK. This time I'll try to describe how ZK support clustering, and some issue should be take care while developing ZK component.

Container Management HttpSession Replication

In the case we build last time, although loadbalancing is already done by Apache JK module and the rest is just a little configuration, session replication is such a importent issue for component developer to pay attention.


Because ZK maintains an UI component model in each user's HttpSession Attribute, and server use this model to fully recognize the meaning of user's operation. We need to know which part definded in the HttpSession specification that helps ZK to replicate this model to other clustering nodes. (If you are not sure what HttpSession is, please read this and this.)


Java(TM) Servlet API Specification 2.2 guarantees that those Objects implement these two interfaces should be serialized by container if needed. this mechanism is used in session Virtual Memory System and Clustering system:

  • java.io.Serializable

Session replication is based on object serialization. objects must implement serializable while transfering between jvms.

  • avax.servlet.http.HttpSessionActivationListener

This interface's methods will fired by container while session replication between two containers is finished. this helps session objects to rebuild resource references.


ZK Session Object Serialization

In order to successfully start session replication function, Add this tag to the zk.xml:

	 <system-config>
		 <ui-factory-class> 
		 	org.zkoss.zk.ui.http.SerializableUiFactory  
		 </ui-factory-class>
	 </system-config>

Which changes ZK's setting to use SerializableUiFactory, session created now (SerializableSession) will implement java.io.Serializable and javax.servlet.http.HttpSessionActivationListener. The session replication machanism implemented by container will synchronize user's session data to every cluster nodes. Picture shown bellow demonstrates what ZK stores in HttpSession.


Session Object Model.jpg

Because ZK stores every user's session object(org.zkoss.zk.ui.Session) in HttpSession's Attribute(by use of httpSession.setAttribute(...)). While Servlet's GET POST method are invoked, ZK WebManager will get users session object from HttpSession.

  • While Serialization: bidirect avoiding

As shown in ZK's user session model, ZK framework has bidirect references that will cause dead loop while serializing. This issue not only occurs in ZK but also happening in any object serialization works. ZK use keyword transient to cut off references. Let's take a code clip for example:

public class DesktopImpl implements Desktop, DesktopCtrl, java.io.Serializable {
	private static final Log log = Log.lookup(DesktopImpl.class);
    private static final long serialVersionUID = 20070416L;

	/** Represents media. It must be distinguishable from component's ID. */
	private static final String MEDIA_PREFIX = "med";

	private transient WebApp _wapp;
	private transient Session _sess;
	private String _id;
	/** The current directory of this desktop. */
	private String _dir;
	/** The URI to access the update engine. */
	private final String _updateURI;
	/** Map(String id, Page page). */
	private final Map _pages = new LinkedHashMap(3);


  • While De-Serialization: transient reference & local resource reference rebuild

Those references we cut off before and those local resource that miss linked must be handled now. ZK's SerializableSession and use a method chain sessionDidActivate(...) to accomplish this requirement. Detailed infomation is shown in next topic.


Notice of developing serializable ZK Component

1.Extends org.zkoss.zk.ui.AbstractComponent, Mostly extends AbstractComponent will be more convenient.

2.Set transient to fields that you would not serialized. For example, database Connection pool and thread pool.

3.Rebuild the resource's reference you cut off. Overrides "public void sessionDidActivate(Page page)" method like this:


 	public void sessionDidActivate(Page page) {
		super.sessionDidActivate(page);
		// write you implementation here...
	}

Because AbstractComponent.sessionDidActivate(page) provides a DFS(Depth First Search) recursive call to rebuild child component's parent reference, while write your implementation code befor, call super method first.


zkDemo in clustering

Here is an easy failover test for zkdemo. Before our step by step, Tomcat MCast service must be set properly. please remember to ensure your computer is connected to a Hub or something to make your Ethernet Card could receive it's own package.


1.Start Apache server + Tomcat Node 1.

Following last time I demonstrated you'll see such messages like this:


Info: Register manager /zkdemo to cluster element Host with name localhost
2007/5/19 PM 02:04:39 org.apache.catalina.cluster.session.DeltaManager start
Info: Starting clustering manager at /zkdemo
2007/5/19 PM 02:04:39 org.apache.catalina.cluster.session.DeltaManager getAllClusterSessions
Info: Manager [/zkdemo]: skipping state transfer. No members active in cluster group.
2007/5/19 PM 02:04:39 org.zkoss.zk.ui.sys.ConfigParser parse:56
Info: Parsing jndi:/localhost/zkdemo/WEB-INF/zk.xml
2007/5/19 PM 02:04:40 org.zkoss.zk.ui.sys.ConfigParser parseClass:257
Info: Using org.zkoss.zk.ui.http.SerializableUiFactory for interface org.zkoss.zk.ui.sys.UiFactory
2007/5/19 PM 02:04:40 org.apache.coyote.http11.Http11BaseProtocol start
Info: Starting Coyote HTTP/1.1 on http-8080
      

2.Browse http://localhost/zkdemo and do some operation. Thus ZK will create some components in Session.


3.Start Tomcat Node 2.

While starting Node 2, this instance will broadcast its self to net and try to find other members. If finded and successfully joining to the membership, other members will replicate their Sessions to this new member. The messages are like these:


Tomcat Node 1

2007/5/19 PM 02:15:17 org.apache.catalina.cluster.tcp.SimpleTcpCluster memberAdded
Info: Replication member added:org.apache.catalina.cluster.mcast.McastMember
[tcp://10.1.3.57:4001,catalina,10.1.3.57,4001, alive=0]
2007/5/19 PM 02:15:17 org.apache.catalina.cluster.tcp.FastAsyncSocketSender checkThread
Info: Create sender [/10.1.3.57:4,001] queue thread to tcp background replication
2007/5/19 PM 02:15:20 org.apache.catalina.cluster.tcp.SimpleTcpCluster logSendMessage
Info: SEND 2007/5/19:U 02:15:20 0 10.1.3.57:4,001 SESSION-STATE-/zkdemo 
2007/5/19 PM 02:15:20 org.apache.catalina.cluster.tcp.SimpleTcpCluster logSendMessage
Info: SEND 2007/5/19:U 02:15:20 0 10.1.3.57:4,001 SESSION-STATE-TRANSFERED/zkdemo 
2007/5/19 PM 02:15:20 org.apache.catalina.cluster.tcp.SimpleTcpCluster logReceiveMessage
Info: RECEIVE 2007/5/19:U 02:15:19 484 10.1.3.57:4,001 GET-ALL-/zkdemo true
      


Tomcat Node 2

2007/5/19 PM 02:15:15 org.apache.catalina.cluster.mcast.McastService start
Info: Sleeping for 2000 milliseconds to establish cluster membership
2007/5/19 PM 02:15:15 org.apache.catalina.cluster.tcp.SimpleTcpCluster memberAdded
Info: Replication member added:org.apache.catalina.cluster.mcast.McastMember
    [tcp://10.1.3.57:4002,catalina,10.1.3.57,4002, alive=639016]
2007/5/19 PM 02:15:16 org.apache.catalina.cluster.tcp.FastAsyncSocketSender checkThread
Info: Create sender [/10.1.3.57:4,002] queue thread to tcp background replication
2007/5/19 PM 02:15:17 org.apache.catalina.cluster.mcast.McastService registerMBean
Info: membership mbean registered (Catalina:type=ClusterMembership,host=localhost)
....
2007/5/19 PM 02:15:19 org.apache.catalina.cluster.tcp.SimpleTcpCluster logSendMessage
Info: SEND 2007/5/19:U 02:15:19 16 10.1.3.57:4,002 GET-ALL-/zkdemo 
2007/5/19 PM 02:15:19 org.apache.catalina.cluster.session.DeltaManager getAllClusterSessions
Attention!: 
    Manager [/zkdemo], requesting session state from org.apache.catalina.cluster.mcast.McastMember
    [tcp://10.1.3.57:4002,catalina,10.1.3.57,4002, alive=642532]. 
    This operation will timeout if no session state has been received within 60 seconds.
     	
2007/5/19 PM 02:15:22 org.apache.catalina.cluster.tcp.SimpleTcpCluster logReceiveMessage
Info: RECEIVE 2007/5/19:U 02:15:20 2,250 10.1.3.57:4,002 SESSION-STATE-/zkdemo true
2007/5/19 PM 02:15:22 org.apache.catalina.cluster.tcp.SimpleTcpCluster logReceiveMessage
Info: RECEIVE 2007/5/19:U 02:15:22 0 10.1.3.57:4,002 SESSION-STATE-TRANSFERED/zkdemo true
      

4.Shutdown Tomcat Node 1. At the first step, we browse zkdemo at Node1, now we turn off it, the service now should provided by Node 2.

2007/5/19 PM 03:11:52 org.apache.catalina.cluster.tcp.SimpleTcpCluster memberDisappeared
Info: Received member disappeared:org.apache.catalina.cluster.mcast.McastMember
    [tcp://10.1.3.57:4001,catalina,10.1.3.57,4001, alive=3391890]
2007/5/19 PM 03:11:52 org.apache.catalina.cluster.util.FastQueue remove
Info: FastQueue.remove: Remove aborted although queue enabled
      

5.Use the same browser and do more operation, seeing any different. There is nothing different in browser side because session is successfully replicated to Node 2.


Summary

ZK holds users data in HttpSession to use container managment functionality to do session replication. Correct setting in zk.xml, make sure component extends AbstractComponent and overrides sessionDidActivate(page) method will make component survive in clustering environment.

Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License.