??xml version="1.0" encoding="utf-8" standalone="yes"?> 作?|代?ldj_work#126.com,转蝲请保持完整?/p>
0Q?环境说明
Apache :apache_2.0.55 1 ?/p>
Tomcat: apache-tomcat-5.5.17 (zip? 2?/p>
mod_jk:: mod_jk-apache-2.0.55.so 1?/p>
W一部分Q负载均?/strong>
负蝲均衡Q就是apache客戯求均衡的分给tomcat1,tomcat2....d?/p>
1.安装apche,tomcat
http://httpd.apache.org/ 下蝲Apache 2.0.55 http://tomcat.apache.org/download-55.cgi 下蝲tomcat5.5 zip版本Q解压即可,l色版) http://apache.justdn.org/tomcat/tomcat-connectors/jk/binaries/win32/jk-1.2.15/ 下蝲mod_jk,注意和?apache版本匚w 按照jdk,我的路径?E:\ide\apache\Apache2 解压两䆾Tomcat, 路径分别?E:\ide\tomcat1,E:\ide\tomcat2 下蝲mod_jk
2.修改Apache配置文ghttp.conf
在apache安装目录下conf目录中找到http.conf 在文件最后加上下面一句话可以了 include "E:\ide\apache\Apache2\conf\mod_jk.conf"
每个Tomcat worker是一个服务于web server、等待执行servlet的Tomcat实例。例如我们经怋用像Apache之类的web server转发sevlethl位于其后面的一个Tomcatq程Q也是前面所说的workerQ。本文详l介l了如何配置各种cdworker和loadbalanceQƈ说明了各U类型worker的特性和loadbalance配置的原理?br />
二、ؓ什么用Tomcat workersQ?/span>
上文描述了一个非常简单的l构Q事实上能够配置多个Tomcat workers来处理web server转发的servleth。而这样配|的理由不外乎以下几U假想环境:
* 我们在开发环境中发布不同的Tomcat workers为各自不同的应用服务。当然在开发环境中的开发者共享同一个web serverQ但是每个Tomcat worke服务于拥有它的开发者?br />* 我们在不同的Tomcatq程上定义各自的虚拟LQ这样不同的公司可以使用各自的web siteQ从而他们的web site得到了合理的分割?br />* 我们提供负蝲q的web siteQ也意味着同时使用多个Tomcat workersQ而每个Tomcat workerh独立的主机ƈ且在workers之间要分配通过web server转发来的h?br />当然Q这些假x况也许ƈ不能늛使用多个workers的所有状c?br />
三、workers.properties配置说明Q?/span>
定义Tomcat workers的方法是在apache的conf目录下编写一个名为“workers.properties”的属性文件。本文将详细解释如何q行配置的:
1.定义Workers列表Q?/b>
定义workers的方法就是在apache的conf目录下编写一个workers.properties文gQ其作为apache的插件来发挥作用?br />定义workers列表的格式:
worker.list =<使用?”分割的worker 名字列表>
例如Q?br />
worker.list= worker1, worker2
当apache启动Ӟworkers.properties作ؓ插g初始化出现在worker.list列表中的workers?br />
2.定义Workers的类型:
每个被命名的worker都应有一些关于其自n的附加信息。这些信息包括了worker的类型和其它相关信息。这里讨论的是JK1.2.5中定义的workerscd?br />定义workercd的格式:
worker . worker名字. type =<workercd>
worker名字的命名最好遵循java的命名规范?br />workercd取g下面的表|
定义一个名为“local”的workerQ其使用ajpv12协议与Tomcat q程通讯Q?br />
worker.local.type=ajp12
定义一个名为“remote”的workerQ其使用ajpv13协议与Tomcat q程通讯Q?br />
worker.remote.type=ajp13
定义一个名为“fast”的workerQ其使用JNI的方式与Tomcat q程通讯Q?br />
worker.fast.type=jni
定义一个名为“loadbalancer”的workerQ其作ؓ对多个Tomcat q程的负载^衡用:
worker.loadbalancer.type=lb
各个cdh不同的行为,我们在下文中会详l解释?br />
3.讄Worker属性:
在定义worker之后Q还需要提供各个worker的属性,q些属性的定义使用下面的方式:
worker.<worker名字>.<属?gt;=<属性?gt;
3-1 ajp12cd的Worker属性:.
ajp12cd的worker工作时用基于TCP/IP socket的ajpv12协议转发hl“进E外”Tomcat worker?br />ajp12 worker属性如下:
hostQ?br />侦听ajp12h的Tomcat workerL?br />portQ?br />Tomcat workerL的侦听端口?br />lbfactorQ?br />当此Tomcat worker被用于一个负载^衡worker使用Ӟ此属性将被用。它定义了此worker的负载^衡权倹{?br />例如Q下面的“worker1”定义了一个位于www.x.comL上的TomcatQ它使用8007端口侦听apache发来的请求,q具?.5的负载权?br />
worker.worker1.host=www.x.com
worker.worker1.port=8007
worker.worker1.lbfactor=2.5
注意Q在ajpv12协议中,针对每个h都要一个连接徏立、用、关闭。其默认侦听端口?007?br />
3-2 ajp13cd的Worker属性:
ajp13cd的worker工作时用基于TCP/IP socket的ajpv13协议转发hl“进E外”Tomcat worker?br />ajpv13协议与ajpv12协议的主要不同:
* ajpv13h更丰富的二进制协议,它用将频繁使用的字W串~码为小整数的方式对h数据q行压羃?br />* ajpv13重用打开的socketq保留这些打开的socket以处理将来的h。这在apache与Tomcat之间h防火墙的|络环境下是必要的?br />* ajpv13h对SSL信息的处理能力,以致容器能够实现SSL的相x法(如isSecure()Q?br />
注意Qajp13当前只能用于支持“进E外”协议的Tomcat 4.0.x, 4.1.x and 5?br />下表描述了ajp13worker接受的属性:
hostQ?br />侦听ajp13h的Tomcat workerL?br />
portQ?br />Tomcat workerL的侦听端口?
lbfactorQ?br />当此Tomcat worker被用于一个负载^衡worker使用Ӟ此属性将被用。它定义了此worker的负载^衡权倹{?br />
cachesizeQ?br />当在多线E的web serverQ例如apache2.0、IIS 、NetscapeQ中使用JKӞ此属性是有效的。如果将cachesize的D|ؓ较高的|q些支持多线E的web server获得很好的处理能力。如果此属性不被设|,则连接cacheҎ将失效?br />
cache_timeoutQ?br />本属性用于声明JK在cache中保留一个打开的socket的时_它对减少web serer的线E数有所帮助?br />使用cache_timeout的原因:
周所周知Q一个n背重负的web serverQ例如apacheQ徏立childs/threads来处理负载,而当负蝲减少时它销毁无用的childs/threads。每个child在{发请求给Tomcat时要打开一个ajp13q接Q而在Tomcat那一端也徏立一个ajp13U程与之通讯。但是问题出现在一个ajp13q接建立完成后,child没有及时的释N个ajp13q接Q由于web server1保持它的childs/threadsq行已处理高负蝲Q即使childs/threads处理快速的静态内容,在Tomcat端也积累很多的无用ajp13U程?br />
socket_keepaliveQ?br />当防火墙位于web server与Tomcat之间Ӟ防火墙将试断开未激zȝ|络q接。此属性将告诉操作pȝ在未Ȁzȝq接中发送KEEP_ALIVE信息(发送间隔时间依赖于操作pȝ的设|,一般ؓ120U?Q这样将防止防火墙切断未Ȁzȝ|络q接?br />但此讄q不是万能钥匙,它对于某些防火墙也无能ؓ力?br />
socket_timeoutQ?br />此属性说明连接在未激zȝ状况下持l多久,web server主动切断之。这是一个Tomcat端的陈旧U程不致q多的好ҎQ但是也带来了在下一ơ请求到来时需要重新打开socket的开销。此属性与cache_timeout有类似的功效Q但是它工作在non-cache模式?br />
connect_timeoutQ?br />web server在连接徏立后一个PINGh发送到ajp13协议的连接上?此属性说明了web server{待PONG回应的时_以ms为单位)。此属性在jk 1.2.6版本被增加进来,以求避免Tomcat的死机,Tomcat 3.3.2+, 4.1.28+ and 5.0.13+实现了对使用ajp13?ping/pong的支持。此属性默认ؓ失效的?br />
prepost_timeoutQ?br />web server在{发一个请求后一个PINGh发送到ajp13协议的连接上。此属性说明了web server{待PONG回应的时_以ms为单位)。此属性在jk 1.2.6版本被增加进来,以求避免Tomcat的死机,Tomcat 3.3.2+, 4.1.28+ and 5.0.13+实现了对使用ajp13?ping/pong的支持。此属性默认ؓ失效的?br />
reply_timeoutQ?br />此属性告诉web server在接到远端的Tomcat已死q实时的切换到集中的另外一个Tomcat的回应之前等待一D|间。默认情况下web server永q等待。属性gؓweb server要等待回应的旉Q以ms为单位)Q所以如果具有运行时间较长的servlet时设|其D心。此属性在jk 1.2.6版本被增加进来,以求避免Tomcat的死机和在支持ajp13的servlet引擎上发生的问题。此属性默认ؓ失效的?br />
recovery_optionsQ?br />此属性说明了web server在检到Tomcatp|后如何进行恢复工作。默认情况下Qweb server{发请求给处于负蝲q模式中的另一个Tomcat。属性gؓ0Q说明全部恢复;属性gؓ1Q说明如果在Tomcat接到h后出现失败状况,则不q行恢复Q属性gؓ2Q说明如果在Tomcat发送http头给客户端后出现p|状况Q则不进行恢复;属性gؓ3Q说明如果在Tomcat接到h后出现失败状冉|者在Tomcat发送http头给客户端后出现p|状况Q则不进行恢复。此属性在jk 1.2.6版本被增加进来,以求避免Tomcat的死机和在支持ajp13的servlet引擎上发生的问题。此属性默认ؓ全部恢复?br />
例如Q一个名为“worker2”的worker的配|:
worker.worker2.host=www2.x.com
worker.worker2.port=8009
worker.worker2.lbfactor=3.5
worker.worker2.cachesize=10
worker.worker2.cache_timeout=600
worker.worker2.socket_keepalive=1
worker "worker2" want ajp13 connection to be dropped after 5mn (timeout)
worker.worker2.socket_timeout=300
说明Q上例中的worker要求操作pȝ在连接上发送KEEP-ALIVE信号?br />注意Q在ajpv13协议中默认端口ؓ8009?br />
4.讄lb Worker属性:
负蝲qcd的workerq不与Tomcat worker通讯Q它负责理q些Tomcat worker?br />
其管理范围如下:
* 初始化在web server的worker列表中定义的worker?br />* 使用worker的负载^衡权|执行Z权值的负蝲qQ将数量多的h发送到负蝲q权值高Q在web server看来是更加健壮的)的worker?br />* l护在同一个Tomcat worker上的同一个session的请求,使其发送到同一个Tomcat worker上。以辑ֈTomcat worker上的session一致性、持l性?br />* 标识已经p|的Tomcat workersQ悬I发向它们的hQ在被lb worker理的其它workers上寻扑֏以失败恢复的worker?br />被同一个lb worker理多个worker之间的负载^衡的Q基于它们的lbfactor和当前用户sessionQ,也可以尽量避免由于单一的Tomcatq程L而造成q个|站被“杀”的不良反应?br />下表说明了lb worker接受的属性:
* balanced_workersQ一个由“,”分割的worker列表Q用来声明lb worker需要被理的workers。这些workers不应出现在worker.list属性中?br />* sticky_sessionQ表q是否将对SESSION ID的请求\由回到相同的Tomcat worker。如果属性g?Q它被讄为JK_TRUEQsession是_性的Q即SESSION ID的请求\由回到相同的Tomcat workerQ当Tomcat正用能够跨多个Tomcat实例持久化session数据的Session ManagerӞ它将被设|ؓJK_FALSE。属性默认gؓJK_TRUE?br />例如Qworker balance1理着两个workersQworker1、worker2Q?br />
worker.balance1.balanced_workers=worker1, worker2
5.高lb Worker属性:
JK 1.2.x版本通过增加两个新的属性:local_worker_only ?local_worker 为lb worker增添了新的负载^衡和定w支持?br />下面让我们D一个实际的环境作ؓexampleQ?br />一个集具有两个节?worker1+worker2)Q一个web server与tomcat workers一前一后,一个负载^衡器Qlb WorkerQ位于节点的前面、web server的后面?br />配置如下Q?br />
worker.list=router
# Define a 'local_worker' worker using ajp13
worker.worker1.port=8009
worker.worker1.host=node1.domain.org
worker.worker1.type=ajp13
worker.worker1.lbfactor=1
worker.worker1.local_worker=1
# Define another 'local_worker' worker using ajp13
worker.worker2.port=8009
worker.worker2.host=node2.domain.org
worker.worker2.type=ajp13
worker.worker2.lbfactor=1
worker.worker2.local_worker=0
# Define the LB worker
worker.router.type=lb
worker.router.balanced_workers=worker1,worker2
worker.router.local_worker_only=1
在worker1和worker2上的local_worker标志告诉lb_worker哪个q接属于本地worker?br />
如果local_workergؓ?Q则它将被设|ؓJK_TRUEQ用来标记“local worker”,而JK_FALSE的情况则相反。如果至一个worker被标Cؓlocal workerQ则lb_worker工作于local worker模式。这U模式下Q所有的local workers被Ud在lb_worker中的内部worker列表的头部?br />
q意味着一个带有session id的请求到达lb_workerӞ相应的workerQ根据权值排序,权值最大的那个workerQ将被确定作为此h的接?处理者。如果这个workerL/当机Q请求将被发送到处于非错误状态的W一个local workerQ如果一个没有session id的请求到达lb_workerӞ此请求将被\由到W一个local worker。如果所有的local worker均处于错误状态,则这时“local_worker_only”标志显得尤光要。如果local_worker_only的属性gؓ?Q则它被讄?JK_TRUEQ否则被讄?JK_FALSE。当它被讄?JK_TRUEӞq个没有session id的请求将得到一个错误作为回应,否则lb_worker尝试将h路由到其它的被管理的worker上。如果其中的一个worker处于错误状态,q且恢复会话的工作ƈ没有M改变Qlocal worker查找这个没有session id的请求(因ؓ在local worker中保存有q个h的sessionQ,而其它的worker只能查找带有session id的请求?br />
注意Qlocal_worker默认值是0Qlocal_worker_only默认g??
6.Z么需要这么复杂的q程吗?
因ؓ我们对于一个关闭的节点需要一个具有灵性的l护?br />在节点前面的q器周期性的Ҏ个节点的特定端口q行查询。如果我们从集群中移C个节点,我们׃隐性的关闭掉这个特定的端口。由于负载^衡器不能q接它,q个节点被标记为down。但是我们没有移动在那个关闭的节点上的session到其它的节点上。在q个环境下,如果q器发送一个没有session id的请求到一个端口被x的节点,那么一个错误将发生。如果^衡器试C个节点被标记为down的状态,而没有其它的节点允许发送没有session id的请求。这栯些陈旧的sessionh只有\由到那个被关闭的节点才能被接受。在一D|间后Q这些陈旧的session超时。由于所有的陈旧的sessionq期Q那个不可达Q被关闭Q的节点失去这个请求。同时也会导致我们的servletpȝ发送一个没有session id的重定向回应l浏览器?br />
但是可能被关闭的节点会upQ重新加入到集群中来Q在它上面仍保留着陈旧的session。所以在最后一个session时后,更新节点能够为陈旧的session的恢复带来希望,而不是杀掉sessions或者把它们Ud其它节点上。而且有时如果那些陈旧的session中有许多big的对象,那么Ud它们也将p许多旉?br />
7.jnicd的Worker属性:
jni worker会在web serverq程中打开一个JVMQƈ在其中执行TomcatQ这叫做“进E内”worker。来往于JVM的消息将通过调用JNIҎ被传递,qjni worker比那些需要用ajp消息通讯的“进E外”worker执行的更快?br />
注意Q由于JVM是多U程的,jni worker应该只被用于在支持对U程的web serverQAOLServer, IIS, Netscape and Apache 2.0Q上。同时还应该认在web server上用的U程Ҏ是否与被使用的JK web server插g相匹配?br />
׃jni worker 打开了一个JVMQ它接受一些属性(例如classpath{)q将其传递给JVMQ?br />worker.worker?class_pathQ“进E内”的JVM要用的classpath。它包括所有的Tomcat的jar文g和class、配|文件等?br />
Z获得JSP~译器的支持Q我们需要将Javacd到classpath中。当然对于Java2需要添加tools.jar到classpathQ而对于JDK1.xx则要dclasses.zip到classpath?br />
worker.worker?class_pathQ用于以多行的Ş式声明多个classpath。JK环境用“:”或者“;”把q些classpathQ连接v来?br />
例如Q给名ؓ“wrkjni”的worker讄classpath?br />
worker.wrkjni.class_path=/var/tomcat3/lib/tomcat.jar
worker.wrkjni.class_path=/opt/IBMJava2-131/lib/tools.jar
worker.worker?bridgeQ用于标识将通过JNI方式被用的Tomcat的类型。此属性目前有两个属性|tomcat32 or tomcat33。Tomcat 3.2.x虽然已经q时Q但是被提供用于发布在一些类似iSeriespȝ上。此属性的默认gؓtomcat33?br />例如Q给“wrkjni”设|bridgecd为tomcat3.3?br />
worker.wrkjni.bridge=tomcat33
worker.worker?cmd_lineQ?此属性提供了在Tomcat启动代码执行的命令行。用时命令行的命令、参数分解ؓ多个cmd_line属性。JK环境通过在各个cmd_line属性g间添加空格将q些cmd_lineq接在一赗?br />例如Q设|“wrkjni”的cmd_line属性?br />
worker.wrkjni.cmd_line=-config
worker.wrkjni.cmd_line=/etc/tomcat3/conf/alt-server.xml
worker.wrkjni.cmd_line=-home
worker.wrkjni.cmd_line=/var/tomcat3
上面例子中的W一行声明了-config参数名,而第二行声明了与之对应的参数倹{第三行与第四行同理?br />
worker.worker?jvm_libQ用于声明JVM的实现库的完整\径。Jni worker使用q个路径动态装载JVM?br />例如Q设|“wrkjni”的JVM shared lib (IBM SDK on Linux)?br />
worker.wrkjni.jvm_lib=/opt/IBMJava2-131/jre/bin/classic/libjvm.so
例如Q设|“wrkjni”的JVM shared lib (Sun SDK on Windows)?br />
worker.wrkjni.jvm_lib=c:\JDK\1.3.1\jre\bin\classic
worker.worker?stdoutQ设|JVM写它的System.out的完整\径位|?
例如Q将“wrkjni”的JVMpȝ输出路径讄?var/log/http/jk-jvm-out.log?br />
worker.wrkjni.stdout=/var/log/http/jk-jvm-out.log
worker.worker?stderrQ设|JVM写它的System.err的完整\径位|?br />例如Q将“wrkjni”的JVMpȝ错误输出路径讄?var/log/http/jk-jvm-err.log
worker.wrkjni.stderr=/var/log/http/jk-jvm-out.log
worker.worker?msQ设|JVM的初始堆大小?br />例如Q设|“wrkjni”的JVM的初始堆?4M?br />
worker.wrkjni.ms=64
worker.worker?mxQ设|JVM的最大的堆大?br />例如Q设|“wrkjni”的JVM堆最大ؓ128M
worker.wrkjni.mx=128
worker.worker?syspropsQ设|JVM的系l属性?br />例如Q设|“wrkjni”的JVM使用法语?br />
worker.wrkjni.sysprops=-Duser.region=FR
worker.worker?ld_pathQ设|附加的动态链接库路径(cM于LD_LIBRARY_PATH)
例如Q添加一些动态链接库路径到“wrkjni”的java环境中?br />
worker.wrkjni.ld_path=/opt/IBMJava2-131/jre/bin/
worker.wrkjni.ld_path=/opt/IBMJava2-131/jre/bin/classic
注意Q在Linux下,上面的ld_pathq不能更新LD_LIBRARY_PATHQ所以需要在执行web server之前手动更新LD_LIBRARY_PATH,?br />
8.属性文件宏Q?/b>
我们可以在属性文件中定义“宏”。这些宏让我们定义属性,q在以后使用它们来构建其它的属性文件。当我们修改Java Home、Tomcat Home、系l\径分隔符时这是很有用的?br />例如Q定义了属性workers.tomcat_home、workers.java_home?br />
workers.tomcat_home=d:\tomcat
workers.java_home=d:\sdk\jdk1.2.2
在定义worker.inprocess.class_path时就可以使用前面定义的workers.tomcat_home?br />
worker.inprocess.class_path=$(workers.tomcat_home)$(ps)classes
9.一个简单而完整的worker.propertiesQ?/b>
文g中定义了比较完整的结构,可以做ؓ参考模版:
* 一个位于localhost的?007端口的ajp12 workerQ?br /> * 一个位于localhost的?008端口的ajp13 workerQ?br /> * 一个jni workerQ?br /> * 一个lb workerQ负责ajp12 worker、ajp13 workers的负载^衡?br />文g内容如下Q?br />
# Define some properties
workers.apache_log=/var/log/httpd/
workers.tomcat_home=/var/tomcat3
workers.java_home=/opt/IBMJava2-131/
ps=/
# Define 4 workers, 3 real workers using ajp12, ajp13, jni, the last one being a loadbalancing worker
worker.list=worker1, worker2, worker3, worker4
# Set properties for worker1 (ajp12)
worker.worker1.type=ajp12
worker.worker1.host=locahost
worker.worker1.port=8007
worker.worker1.lbfactor=5
# Set properties for worker2 (ajp13)
worker.worker2.type=ajp13
worker.worker2.host=locahost
worker.worker2.port=8009
worker.worker2.lbfactor=50
worker.worker2.cachesize=10
worker.worker2.cache_timeout=600
worker.worker2.socket_keepalive=1
worker.worker2.socket_timeout=300
# Set properties for worker3 (jni)
worker.worker3.type=jni
# Set worker3 bridge type, here Tomcat 3.3
worker.worker3.bridge=tomcat33
# Set worker3 classpath
worker.worker3.class_path=$(workers.tomcat_home)$(ps)classes
worker.worker3.class_path=$(workers.tomcat_home)$(ps)lib$(ps)tomcat.jar
# Set worker3 tomcat command line
worker.worker3.cmd_line=-home
worker.worker3.cmd_line=$(workers.tomcat_home)
# Set worker3 Tomcat/JVM settings
worker.worker3.jvm_lib=$(workers.java_home)$(ps)jre$(ps)bin$(ps)classic$(ps)libjvm.so
worker.worker3.stdout=$(workers.apache_log)$(ps)inprocess.stdout
worker.worker3.stderr=$(workers.apache_log)$(ps)inprocess.stderr
worker.worker3.sysprops=tomcat.home=$(workers.tomcat_home)
# Set properties for worker4 (lb) which use worker1 and worker2
worker.worker4.balanced_workers=worker1,worker2
]]>
LoadModule jk_module modules/mod_jk-apache-2.0.55.so
JkWorkersFile conf/workers.properties
worker.tomcat1.host=localhost #tomcat的主机地址Q如不ؓ本机Q请填写ip地址
worker.tomcat1.type=ajp13
worker.tomcat1.lbfactor = 1 #server的加权比重,D高,分得的请求越?/div>
worker.tomcat2.host=localhost #tomcat的主机地址Q如不ؓ本机Q请填写ip地址
worker.tomcat2.type=ajp13
worker.tomcat2.lbfactor = 1 #server的加权比重,D高,分得的请求越?/div>
#========controller,负蝲均衡控制?=======
worker.controller.type=lb
worker.controller.balanced_workers=tomcat1,tomcat2 #指定分担h的tomcat
worker.controller.sticky_session=1
System.out.println("===========================");
%>
<%@ 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>");
if (dataName != null && dataName.length() > 0) {
String dataValue = request.getParameter("dataValue");
session.setAttribute(dataName, dataValue);
}
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="index.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>
<distributable/>
</web-app>
]]>
(1)服务器有4収ͼ一台安装apache,三台安装tomcat
(2)apache2.0.55、tomcat5.5.15、jk2.0.4、jdk1.5.6或jdk1.4.2
(3)ip配置,一台安装apache的ip?92.168.0.88,三台安装tomcat的服务器ip分别?92.168.0.1/2/4
(?安装q程
(1)在三台要安装tomcat的服务器上先安装jdk
(2)配置jdk的安装\?在环境变量path中加入jdk的bin路径,新徏环境变量JAVA_HOME指向jdk的安装\?br />(3)在三台要安装tomcat的服务器上分别安装tomcat,调试三个tomcat到能够正常启?br />(4)tomcat的默认WEB服务端口?080,默认的模式是单独服务,我的三个tomcat的WEB服务端口修改?080/8888/9999
修改位置为tomcat的安装目录下的conf/server.xml
修改前的配置?/p> <Connector port="8080" maxHttpHeaderSize="8192"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" redirectPort="8443" acceptCount="100"
connectionTimeout="20000" disableUploadTimeout="true" />
修改后的配置?/p> <Connector port="7080" maxHttpHeaderSize="8192"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" redirectPort="8443" acceptCount="100"
connectionTimeout="20000" disableUploadTimeout="true" />
依次修改每个tomcat的监听端?7080/8888/9999)
(5)分别试每个tomcat的启动是否正?br />http://192.168.0.1:7080
http://192.168.0.2:8888
http://192.168.0.4:9999
(?负蝲均衡配置q程
(1)在那台要安装apache的服务器上安装apache2.0.55,我的安装路径为默认C:\Program Files\Apache Group\Apache2
(2)安装后测试apache能否正常启动Q调试到能够正常启动http://192.168.0.88
(3)下蝲jk2.0.4后解压羃文g
(4)解压羃后的目录中的modules目录中的mod_jk2.so文g复制到apache的安装目录下的modules目录?我的为C:\Program Files\Apache Group\Apache2\modules
(5)修改apache的安装目录中的conf目录的配|文件httpd.confQ在文g中加LoadModule模块配置信息的最后加上一句LoadModule jk2_module modules/mod_jk2.so
(6)分别修改三个tomcat的配|文件conf/server.xmlQ修改内容如?br />修改?/p> <!-- 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). -->
<!-- You should set jvmRoute to support load-balancing via AJP ie :
<Engine name="Standalone" defaultHost="localhost" jvmRoute="jvm1">
-->
<!-- Define the top level container in our container hierarchy -->
<Engine name="Catalina" defaultHost="localhost">
修改?p>
<!-- 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). --> <!-- You should set jvmRoute to support load-balancing via AJP ie :--> <Engine name="Standalone" defaultHost="localhost" jvmRoute="tomcat1"> <!-- Define the top level container in our container hierarchy <Engine name="Catalina" defaultHost="localhost"> --> |
其中的jvmRoute="jvm1"分别修改为jvmRoute="tomcat1"和jvmRoute="tomcat2"和jvmRoute="tomcat3"
(7)然后重启三个tomcatQ调试能够正常启动?br />(8)在apache的安装目录中的conf目录下创建文件workers2.propertieQ写入文件内容如?br />
# fine the communication channel [channel.socket:192.168.0.1:8009] info=Ajp13 forwarding over socket |
#配置W一个服务器
tomcatId=tomcat1 #要和tomcat的配|文件server.xml中的jvmRoute="tomcat1"名称一?br />debug=0
lb_factor=1 #负蝲q因子Q数字越大请求被分配的几率越?br />
# Define the communication channel [channel.socket:192.168.0.2:8009] info=Ajp13 forwarding over socket tomcatId=tomcat2 debug=0 lb_factor=1 # Define the communication channel [channel.socket:192.168.0.4:8009] info=Ajp13 forwarding over socket tomcatId=tomcat3 debug=0 lb_factor=1 [status:] info=Status worker, displays runtime information. [uri:/jkstatus.jsp] info=Display status information and checks the config file for changes. group=status: [uri:/*] info=Map the whole webapp debug=0 |
(9)在三个tomcat的安装目录中的webapps建立相同的应?我和应用目录名ؓTomcatDemo,在三个应用目录中建立相同 WEB-INF目录和页面index.jsp,index.jsp的页面内容如?/p>
<%@ 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 属性设|?br /> String dataName = request.getParameter("dataName"); if (dataName != null && dataName.length() > 0) { String dataValue = request.getParameter("dataValue"); session.setAttribute(dataName, dataValue); } out.print("<b>Session 列表</b>"); 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="index.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> |
(10)重启apache服务器和三个tomcat服务?到此负蝲 均衡已配|完成。测试负载均衡先试apache,讉Khttp://192.168.0.88/jkstatus.jsp
能否正常讉KQƈ查询其中的内容,有三个tomcat的相关配|信息和负蝲说明,讉Khttp://192.168.0.88/TomcatDemo/index.jsp看能够运?
能运行,则已建立负蝲均衡?/p>
(?tomcat集群配置
(1)负蝲均衡配置的条件下配置tomcat集群
(2)分别修改三个tomcat的配|文件conf/server.xml,修改内容如下
修改?/p>
<!-- <Cluster className="org.apache.catalina.cluster.tcp.SimpleTcpCluster" managerClassName="org.apache.catalina.cluster.session.DeltaManager" expireSessionsOnShutdown="false" useDirtyFlag="true" notifyListenersOnReplication="true"> <Membership className="org.apache.catalina.cluster.mcast.McastService" mcastAddr="228.0.0.4" mcastPort="45564" mcastFrequency="500" mcastDropTime="3000"/> <Receiver className="org.apache.catalina.cluster.tcp.ReplicationListener" tcpListenAddress="auto" tcpListenPort="4001" tcpSelectorTimeout="100" tcpThreadCount="6"/> <Sender className="org.apache.catalina.cluster.tcp.ReplicationTransmitter" replicationMode="pooled" ackTimeout="5000"/> <Valve className="org.apache.catalina.cluster.tcp.ReplicationValve" filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;"/> <Deployer className="org.apache.catalina.cluster.deploy.FarmWarDeployer" tempDir="/tmp/war-temp/" deployDir="/tmp/war-deploy/" watchDir="/tmp/war-listen/" watchEnabled="false"/> <ClusterListener className="org.apache.catalina.cluster.session.ClusterSessionListener"/> </Cluster> --> |
修改?/p>
<!-- modify by whh --> <Cluster className="org.apache.catalina.cluster.tcp.SimpleTcpCluster" managerClassName="org.apache.catalina.cluster.session.DeltaManager" expireSessionsOnShutdown="false" useDirtyFlag="true" notifyListenersOnReplication="true"> <Membership className="org.apache.catalina.cluster.mcast.McastService" mcastAddr="228.0.0.4" mcastPort="45564" mcastFrequency="500" mcastDropTime="3000"/> <Receiver className="org.apache.catalina.cluster.tcp.ReplicationListener" tcpListenAddress="auto" tcpListenPort="4001" tcpSelectorTimeout="100" tcpThreadCount="6"/> <Sender className="org.apache.catalina.cluster.tcp.ReplicationTransmitter" replicationMode="pooled" ackTimeout="5000"/> <Valve className="org.apache.catalina.cluster.tcp.ReplicationValve" filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;"/> <Deployer className="org.apache.catalina.cluster.deploy.FarmWarDeployer" tempDir="/tmp/war-temp/" deployDir="/tmp/war-deploy/" watchDir="/tmp/war-listen/" watchEnabled="false"/> <ClusterListener className="org.apache.catalina.cluster.session.ClusterSessionListener"/> </Cluster> <!-- modify by whh --> |
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"> <display-name>TomcatDemo</display-name> </web-app> |
配置?/p>
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"> <display-name>TomcatDemo</display-name> <distributable/> </web-app> |