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

From Documentation
DocumentationSmall Talks2007AprilHow to Run ZK on Apache + Tomcat clustering, Part I
How to Run ZK on Apache + Tomcat clustering, Part I

Author
Ian Tsai, Engineer, Potix Corporation
Date
April 30, 2007
Version
  1. Apache 2.2.4 latter
  2. Apache JK Connector 1.2.22
  3. Apache-Tomcat-5.5.20
  4. ZK newest
  5. Eclipse3.2


Introduction

Let's think more about ZK framework's natural property: Program simple ZUML page and let server-side computing facade complex client-side AJAX presentation. For this purpose, our machine will have to do session talking, event processing and page interpretation. Those are all stateful works and relied on your server's stability.

Clustering is a useful technology for this situation. In the past, this could be a rocket science for general web developer, but now open source's power offering us an easy way to attach it... with a little configuration. This series of articles will try to use Eclipse to show how to develop ZK web application in a clustering environment, and what kind of traps, errors and myths you should avoid. The topic of the first article here is very simple:

Let's build an easy clustering environment to run ZK-Demo.


A Simple Case of Clustering

The clustering demonstration we'll build in this article is shown below:

FrLittle.jpg


Procedure for Eclipse & Tomcat Configuration

  1. Launch the IDE Eclipse3.2. If you don't have it, download here.
  2. Create a web project you desired. In this case, we use zkDemo which I name it zkDemoWeb. Right click your Package Explorer [new] -> [project] then create [Web] -> [Dynamic Web Project]. Fill those blanks with your definitions.
  3. Right click the project you created. Chose [Run As]->[Run On Server], and then you can choose an existing server or Manually define a new one.
  4. Add your web project to this server config. Clicking [Finish] and Eclipse will create a project named "Servers" for its self. If you have doing this before and manually define a new server, Eclipse will add a new item for your config.
  5. Add more server nodes. Now we got a project, a server config. For the next, we'll create more Tomcat server config to build our clustering system. Right click [Servers] -> [New] -> [Other...] and create new Server config items. Because session replication costly while cluster nodes more then three (it's about math, think about fully connected graph K3~K4), I only add two more.
  6. Configuring Tomcat server nodes' [server.xml] which is in:TOMCAT_HOME/conf/server.xml To enable the cluster features correctly. You can read more detail information here, or following steps 7.
  7. Set these ports in [server.xml] to different. Because we run tomcat instances at the same machine. We need to avoid conflict between cluster nodes. The ports need to set different are:
I.Server admin port: origin is 8005, I set 8025 to 8027.
            <Server port="8006" shutdown="SHUTDOWN">
            </Server>
II.Default HTTP Connector port: I set 8081 to 8083.
                <!-- Define a non-SSL HTTP/1.1 Connector on port 8080 -->
                <Connector acceptCount="100" 
                	connectionTimeout="20000" 
                	disableUploadTimeout="true" 
                	enableLookups="false" 
                	maxHttpHeaderSize="8192" 
                	maxSpareThreads="75" 
                	maxThreads="150" 
                	minSpareThreads="25" 
                	port="8081" 
                	redirectPort="8444"/>
III.AJP 1.3 Connector port: origin is 8009, I set 8009 to 8011
                <!-- Define an AJP 1.3 Connector on port 8010 -->
                <Connector enableLookups="false" port="8010" protocol="AJP/1.3" redirectPort="8444"/>
IV.Set engine's attribute:[jvmRoute]. This attribute let load balancer pass sessions correctly between cluster node and user's browser. Booking each nodes name and we'll use it at procedure for Apache & JK Side.
                <!-- You should set jvmRoute to support load-balancing via AJP ie : --> 
                <Engine defaultHost="localhost" jvmRoute="worker1" name="Standalone">
V.Unmark cluster tag section. Set 's [tcpListenPort] in different. I set them 4001 to 4003.
                <Receiver className="org.apache.catalina.cluster.tcp.ReplicationListener" 
                    tcpListenAddress="auto" 
                    tcpListenPort="4002" 
                    tcpSelectorTimeout="100" 
                    tcpThreadCount="6"/>


8. Configuring your web project distributable. The step is simple. First, All your session attributes must implement java.io.Serializable. and the second, make sure your web.xml has the <distributable/> element.


To show the Eclipse archive hierarchy more directly, Here is the Eclipse screen capture: Eclipse.png

Procedure for Apache & JK Configuration

  1. Download and install Apache Httpd and you can view the detail docs here.
  2. Download JK Connector here(mod jk-apache-2.2.4.so) and you can view the detail docs here.
  3. Configuring Apache + JK. Put the unzipped file [mod_jk-apache-2.2.4.so] to [Apache_home/ modules] and create two files in [Apache_home/conf] for JK's Configuration. Named them [uriworkermap.properties] and [workers.properties]. You can download samples here.
  4. Configuring [httpd.conf] which is:Apache_Home/conf/httpd.conf. This file is Apache HTTP Server's central control. In order to tell Apache the existence of JK Connector module and the module's config, we add this part inside:


      #***********module JK Module*******************
      LoadModule jk_module modules/mod_jk.so
       
              
      #
      # Configure mod_jk
      #

      JkWorkersFile conf/workers.properties
      JkMountFile conf/uriworkermap.properties
      JkLogFile logs/mod_jk.log
      JkLogLevel warn
5. Configure [workers.properties]. The following code shows how to set JK as a load balancer and how to mount cluster nodes onto it.


        # Define some properties
        # Define ApacheJkLb,jkstatus which can be used in uriworkermap.properties. the ApacheJkLb is loadbalancing worker 
        
        worker.list= ApacheJkLb, jkstatus

        # Set properties for worker1 (ajp13)
        worker.worker1.type=ajp13
        worker.worker1.host=localhost
        worker.worker1.port=8010
        worker.worker1.lbfactor=1
        worker.worker1.connection_pool_timeout=600
        worker.worker1.socket_keepalive=True
        worker.worker1.socket_timeout=60
        
        # Set properties for worker2 (ajp13)
        worker.worker2.type=ajp13
        worker.worker2.host=localhost
        worker.worker2.port=8009
        worker.worker2.lbfactor=1
        worker.worker2.connection_pool_timeout=600
        worker.worker2.socket_keepalive=True
        worker.worker2.socket_timeout=60
        
        # Set properties for worker3 (ajp13)
        worker.worker3.type=ajp13
        worker.worker3.host=localhost
        worker.worker3.port=8011
        worker.worker3.lbfactor=1
        worker.worker3.connection_pool_timeout=600
        worker.worker3.socket_keepalive=True
        worker.worker3.socket_timeout=60
        
        
       # Set "worker.WORKER_NAME.type=lb" will open JK's Load balancering function. In other words, JK becomes a load balancer.
        worker.ApacheJkLb.type=lb
       # Add those workers to the load balancer you  defind befor. 
        worker.ApacheJkLb.balance_workers=worker1,worker2,worker3
       #  Set "worker.WORKER_NAME.type=status" to open a channel to Admin JK Connector.
        worker.jkstatus.type=status


6. Configure [uriworkermap.properties]. The following code defines the strategy to direct clients request. Please read the comments for details.
       
      # General syntax for this file is:
      # [URL]=[Worker name]


      #
      #Direct those requests have such patterns to the cluster nodes defined in workers.properties
      #
      #

      /zkDemoWeb/*=ApacheJkLb
      /*.zul=ApacheJkLb
      /*.dsp=ApacheJkLb
        
      #
      # Except  /jkManager because we need a url to jkstatus 
      #

      /jkManager=jkstatus



        
      #
      # For no mapping the url has to start with exclamation (!)
      # Usually used in static data requests. because httpd serv these is faster then Tomcat.
      # So here's an EASY WAY to "Over Write" ZK's  .css, .img and .js. 
      # you have neither CRUD zk's jar file nor editing language-addon.xml...
      # you just redirect all these kind of requests to Apache Http Server!!!
      #

      !/img/*.jpeg=ApacheJkLb
      !/img/*.gif=ApacheJkLb
      !/img/*.jpg=ApacheJkLb
      !/img/*.png=ApacheJkLb
      !/flash/*.swf=ApacheJkLb
      !/activex/*.ocx=ApacheJkLb
      !/css/*.css=ApacheJkLb
      !/js/*.js=ApacheJkLb

Running our Clustering System

The sequence to start which side doesn't matter. Just put the zkDemo into the project you created and enjoy it! Let's take a look of the console:


2007/4/30 AM 08:37:30 org.apache.catalina.cluster.tcp.SimpleTcpCluster start
INFO: Cluster is about to start
2007/4/30 AM 08:37:30 org.apache.catalina.cluster.tcp.ReplicationTransmitter start
INFO: Start ClusterSender at cluster Standalone:type=Cluster,host=localhost with name Standalone:
    type=ClusterSender,host=localhost
2007/4/30 AM 08:37:30 org.apache.catalina.cluster.mcast.McastService start
INFO: Sleeping for 2000 milliseconds to establish cluster membership
2007/4/30 AM 08:37:32 org.apache.catalina.cluster.mcast.McastService registerMBean
INFO: membership mbean registered (Standalone:type=ClusterMembership,host=localhost)
2007/4/30 AM 08:37:32 org.apache.catalina.cluster.deploy.FarmWarDeployer start
INFO: Cluster FarmWarDeployer started.
2007/4/30 AM 08:37:33 org.apache.catalina.cluster.session.DeltaManager start
INFO: Register manager /zkDemoWeb to cluster element Host with name localhost
2007/4/30 AM 08:37:33 org.apache.catalina.cluster.session.DeltaManager start
INFO: Starting clustering manager at /zkDemoWeb
2007/4/30 AM 08:37:33 org.apache.catalina.cluster.session.DeltaManager getAllClusterSessions


While your Tomcat started with no error message, you must see some messages like this.

INFO: Parsing jndi:/localhost/zkDemoWeb/WEB-INF/zk.xml
2007/4/30 AM 08:37:33 org.zkoss.zk.ui.sys.ConfigParser parseClass:255
INFO: Using org.zkoss.zk.ui.http.SerializableUiFactory for interface   org.zkoss.zk.ui.sys.UiFactory
2007/4/30 AM 08:37:34 org.apache.coyote.http11.Http11BaseProtocol start
INFO: Starting Coyote HTTP/1.1 on http-8081
2007/4/30 AM 08:37:34 org.apache.jk.common.ChannelSocket init
INFO: JK: ajp13 listening on /0.0.0.0:8010
2007/4/30 AM 08:37:34 org.apache.jk.server.JkMain start
INFO: Jk running ID=0 time=0/47  config=null
2007/4/30 AM 08:37:34 org.apache.catalina.storeconfig.StoreLoader load
INFO: Find registry server-registry.xml at classpath resource
2007/4/30 AM 08:37:34 org.apache.catalina.startup.Catalina start
INFO: Server startup in 3969 ms

2007/4/30 AM 08:38:44 org.apache.catalina.cluster.tcp.SimpleTcpCluster memberAdded
INFO: Replication member added:org.apache.catalina.cluster.mcast.McastMember[tcp://10.1.3.52:4001,catalina,10.1.3.52,4001, alive=0]

This console clip shows the first Node detect the second Node has being added, And they replicate their sessions.


Little Trick

Serve your static data with Apache can speed up your user's responsiveness. And it can do MORE... Overwrite ZK's theme!

Continue...




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