配置环境需要:1.Apache服务器,下载地址:​​http://httpd.apache.org/download.cgi#apache22​

 2.tomcat6.0或者tomcat7.0,(集群中tomcat不能既有tomcat6又有tomcat7,否则虽能够负载均衡,但不能进行session复制,下载地址:​​http://tomcat.apache.org/​

 3.jk是tomcat提供给http服务器的插件mod_jk-1.2.31-httpd-2.2.3.so     下载地址:​​http://archive.apache.org/dist/tomcat/tomcat-connectors/jk/binaries/win32/jk-1.2.31/​

 

修改Apache配置

1、修改httpd.conf

我的Apache安装在D:\Program Files\Apache Software Foundation\Apache2.2,找到conf目录下的httpd.conf,在文件的最后一行添加

include "D:\Program Files\Apache Software Foundation\Apache2.2\conf\mod_jk.conf"

2、新建mod_jk.conf文件,内容如下:

#加载mod_jk Module

LoadModule jk_module modules/mod_jk-1.2.31-httpd-2.2.3.so

#指定workers.properties文件路径

JkWorkersFile conf/workers.properties

#指定那些请求交给tomcat处理,"controller"为在workers.propertise里指定的负载分配控制器名

JkMount /*.jsp controller

3、将下载的JK插件mod_jk-1.2.31-httpd-2.2.3.so复制到Apache安装目录的modules目录下。

4、新建并编辑workers.properties文件,内容如下:

worker.list = controller,tomcat1,tomcat2  #server 列表 

#========tomcat1========  

worker.tomcat1.port=11009    #ajp13 端口号,在tomcat下server.xml配置,默认8009

worker.tomcat1.host=localhost   #tomcat的主机地址,如不为本机,请填写ip地址 

worker.tomcat1.type=ajp13  

worker.tomcat1.lbfactor = 1   #server的加权比重,值越高,分得的请求越多

#========tomcat2========  

worker.tomcat2.port=12009    #ajp13 端口号,在tomcat下server.xml配置,默认8009 

worker.tomcat2.host=localhost   #tomcat的主机地址,如不为本机,请填写ip地址 

worker.tomcat2.type=ajp13 

worker.tomcat2.lbfactor = 1  #server的加权比重,值越高,分得的请求越多 

#========tomcat3========  

worker.tomcat3.port=8009    #ajp13 端口号,在tomcat下server.xml配置,默认8009 

worker.tomcat3.host=localhost   #tomcat的主机地址,如不为本机,请填写ip地址 

worker.tomcat3.type=ajp13 

worker.tomcat3.lbfactor = 1  #server的加权比重,值越高,分得的请求越多

#========controller,负载均衡控制器======== 

worker.controller.type=lb

worker.controller.balanced_workers=tomcat1,tomcat2,tomcat3

worker.controller.sticky_session=false(false指的是实现session复制)

这里可以配置任意多个Tomcat,此处配置了3个Tomat服务器,2个本地,1个远程,所以为了它们都能够顺利启动起来,本地的服务器端口都是不同的,如果Tomcat不再同一机器上,没必要改端口的。下面是tomcat1的server.xml的配置

<?xml version='1.0' encoding='utf-8'?>

<!--

  Licensed to the Apache Software Foundation (ASF) under one or more

  contributor license agreements.  See the NOTICE file distributed with

  this work for additional information regarding copyright ownership.

  The ASF licenses this file to You under the Apache License, Version 2.0

  (the "License"); you may not use this file except in compliance with

  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software

  distributed under the License is distributed on an "AS IS" BASIS,

  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

  See the License for the specific language governing permissions and

  limitations under the License.

-->

<!-- Note:  A "Server" is not itself a "Container", so you may not

     define subcomponents such as "Valves" at this level.

     Documentation at /docs/config/server.html

 -->

<Server port="8001" shutdown="SHUTDOWN">

  <!--APR library loader. Documentation at /docs/apr.html -->

  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />

  <!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->

  <Listener className="org.apache.catalina.core.JasperListener" />

  <!-- Prevent memory leaks due to use of particular java/javax APIs-->

  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />

  <!-- JMX Support for the Tomcat server. Documentation at /docs/non-existent.html -->

  <Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" />

  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />

  <!-- Global JNDI resources

       Documentation at /docs/jndi-resources-howto.html

  -->

  <GlobalNamingResources>

    <!-- Editable user database that can also be used by

         UserDatabaseRealm to authenticate users

    -->

    <Resource name="UserDatabase" auth="Container"

              type="org.apache.catalina.UserDatabase"

              description="User database that can be updated and saved"

              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"

              pathname="conf/tomcat-users.xml" />

  </GlobalNamingResources>

  <!-- A "Service" is a collection of one or more "Connectors" that share

       a single "Container" Note:  A "Service" is not itself a "Container", 

       so you may not define subcomponents such as "Valves" at this level.

       Documentation at /docs/config/service.html

   -->

  <Service name="Catalina">  

    <!--The connectors can use a shared executor, you can define one or more named thread pools-->

    <!--

    <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" 

        maxThreads="150" minSpareThreads="4"/>

    --> 

    

    <!-- A "Connector" represents an endpoint by which requests are received

         and responses are returned. Documentation at :

         Java HTTP Connector: /docs/config/http.html (blocking & non-blocking)

         Java AJP  Connector: /docs/config/ajp.html

         APR (HTTP/AJP) Connector: /docs/apr.html

         Define a non-SSL HTTP/1.1 Connector on port 8080

    -->

    <Connector port="8081" protocol="HTTP/1.1" 

               connectionTimeout="20000" 

               redirectPort="8443" />

    <!-- A "Connector" using the shared thread pool-->

    <!--

    <Connector executor="tomcatThreadPool"

               port="8080" protocol="HTTP/1.1" 

               connectionTimeout="20000" 

               redirectPort="8443" />

    -->           

    <!-- Define a SSL HTTP/1.1 Connector on port 8443

         This connector uses the JSSE configuration, when using APR, the 

         connector should be using the OpenSSL style configuration

         described in the APR documentation -->

    <!--

    <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"

               maxThreads="150" scheme="https" secure="true"

               clientAuth="false" sslProtocol="TLS" />

    -->

    <!-- Define an AJP 1.3 Connector on port 8009 -->

    <Connector port="11009" protocol="AJP/1.3" redirectPort="8443" />

    <!-- An Engine represents the entry point (within Catalina) that processes

         every request.  The Engine implementation for Tomcat stand alone

         analyzes the HTTP headers included with the request, and passes them

         on to the appropriate Host (virtual host).

         Documentation at /docs/config/engine.html -->

    <!-- You should set jvmRoute to support load-balancing via AJP ie :

    <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">         

    --> 

    <Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat1">

      <!--For clustering, please take a look at documentation at:

          /docs/cluster-howto.html  (simple how to)

          /docs/config/cluster.html (reference documentation) -->

     <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>  

<!-- <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"  

                 channelSendOptions="8">  -->

          <!--                

          <Manager className="org.apache.catalina.ha.session.BackupManager"  

                    expireSessionsOnShutdown="false"  

                    notifyListenersOnReplication="true"  

                    mapSendOptions="8"/> -->  

            

         <!-- <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="auto"  

                      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"/>  

         <Interceptor className="org.apache.catalina.tribes.group.interceptors.ThroughputInterceptor"/>  

          </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>   -->


      <!-- The request dumper valve dumps useful debugging information about

           the request and response data received and sent by Tomcat.

           Documentation at: /docs/config/valve.html -->

      <!--

      <Valve className="org.apache.catalina.valves.RequestDumperValve"/>

      -->

      <!-- This Realm uses the UserDatabase configured in the global JNDI

           resources under the key "UserDatabase".  Any edits

           that are performed against this UserDatabase are immediately

           available for use by the Realm.  -->

      <Realm className="org.apache.catalina.realm.UserDatabaseRealm"

             resourceName="UserDatabase"/>

      <!-- Define the default virtual host

           Note: XML Schema validation will not work with Xerces 2.2.

       -->

      <Host name="localhost"  appBase="webapps"

            unpackWARs="true" autoDeploy="true"

            xmlValidation="false" xmlNamespaceAware="false">

        <!-- SingleSignOn valve, share authentication between web applications

             Documentation at: /docs/config/valve.html -->

        <!--

        <Valve className="org.apache.catalina.authenticator.SingleSignOn" />

        -->

        <!-- Access log processes all example.

             Documentation at: /docs/config/valve.html -->

        <!--

        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"  

               prefix="localhost_access_log." suffix=".txt" pattern="common" resolveHosts="false"/>

        -->

      </Host>

    </Engine>

  </Service>

</Server>

另外两个tomcat的server.xml的配置和上面类似,只需把红色的端口改一下即可。

 

注意:AJP13的connector的port和jvmRoute名称和workers.properties中配置对应。

 



测试

 

建立测试项目

建立test项目,把这个项目分别部署到三个tomcat服务器下面,同时需要在项目的WEB-INF文件夹下的web.xml中添加<distributable/>这个标签

建立test2.jsp,内容如下:

 

<%@ page contentType="text/html; charset=GBK" %>
<%@ page import="java.util.*" %>
<html><head><title>Cluster App Test</title></head>
<body>
Server Info:
<%
out.println(request.getLocalAddr() + " : " + request.getLocalPort()+"<br>");%>
<%
out.println("<br> ID " + session.getId()+"<br>");
// 如果有新的 Session 属性设置
String dataName = request.getParameter("dataName");
if (dataName != null && dataName.length() > 0) {
String dataValue = request.getParameter("dataValue");
session.setAttribute(dataName, dataValue);
}
out.println("<b>Session 列表</b><br>");
System.out.println("============================");
Enumeration e = session.getAttributeNames();
while (e.hasMoreElements()) {
String name = (String)e.nextElement();
String value = session.getAttribute(name).toString();
out.println( name + " = " + value+"<br>");
System.out.println( name + " = " + value);
}
%>
<form action="test2.jsp" method="POST">
名称:<input type=text size=20 name="dataName">
<br>
值:<input type=text size=20 name="dataValue">
<br>
<input type=submit>
</form>
</body>
</html>


 

Session测试

将项目部署到3个服务器之后,然后分别启动Apache和3个Tocmat服务器,这些Tomcat启动顺序随意,然后打开​​http://localhost/test/test2.jsp​​,

按F5每刷新一次页面,session的ID都是一样的说明实现了session的复制,这样就大功告成了!