tomcat(9)-linux apache tomcat集群环境搭建

一、集群的基本知识
        集群技术是目前非 常流行的提高系统服务能力与高可靠性( HA- High Availability )的手段,通过把多个独立的服务器组成一个集群可以实现失效无缝转移。也就是说当有某一台集群中的服务器当机后,其上的用户状态数据可以无缝迁移到集群中 的其他服务器上。这样,正在使用应用的客户可以完全感觉不到影响,大大提供了系统的可靠性。

集群有很多种类和层次,例如:操作系统集群(如 Linux 、 Solaris 等),数据库集群(如 DB2 、 Oracle 等),应用服务器集群(如 GlassFish 、 WebLogic 等) ,Web 集群(如 Tomcat 等)。本教程将向读者介绍由 Tomcat 搭建的 Web 集群。

不管是由什么技术搭建的集群,其基本组成由下图所示:

 

1-1

从图中可以看出,每个集群都需要一个负载均衡器,其负责根据一定的算法将外界发送到集群的请求尽量均匀地分配到集群中的每个服务器,使得集群中所有 服务器的负载尽量平衡。对外界的客户端而言其并不知道具体访问了集群中的哪台服务器,多台服务器从逻辑上对外界而言可以看作一台"大"服务器。这样,当集 群的服务能力不能满足当前的需要时,可以非常方便地再向集群中添加新的服务器来满足需要。可以看出,使用了集群之后,系统具有非常好的可扩展性。

当不幸集群中有某台服务器突然当机时,其用户状态数据可以迁移到其他服务器上,不影响在线用户的使用。这样,通过使用集群技术可以方便地实现系统的高可靠性。

本教程中将介绍的使用 Tomcat 搭建的 Web 集群结构如图 1-2 所示:

1-2

从图中可以看出集群的负载均衡器由开源的 Apache 服务器担任,集群中的 Web 服务器由两个 Tomcat 服务器分别担任,后台的数据库服务器由一个 MySQL 服务器担任。

提示:本教程中介绍的是 Web 集群,因此数据库服务器只有一个,并没有搭建集群。在需要的情况下,多台数据库服务器也可以组成集群以提高服务能力与可靠性。

二、安装JDK

三、安装TOMCAT

  1. 下载tomcat,可以通过下面的命令下载:

#wget http://apache.mirror.phpchina.com/tomcat/tomcat-6/v6.0.18/bin/apache-tomcat-6.0.18.tar.gz

  1. 解压启动测试:

#tar -zxvf apache-tomcat-6.0.18.tar.gz
#./apache-tomcat-6.0.18/bin/startup.sh

在浏览器中输入:http://localhost:8080,看是否启动正常,若正常进行第三步。

  1. 下面通过一个简单的" Test.jsp "程序进一步验证 Tomcat 是否安装成功,新建名称为" Test.jsp "的 Jsp 源文件并在其中输入如下代码。

<%@ page contentType="text/html;charset=GBK"%>
<html>
<head>
<title> Tomcat_ _测试 </title>
</head>
<body>
<font color = "red" size = "20" >
<% out.print( "_ _恭喜您,成功的安装并启动了 Tomcat_ _!!! " ); %>
</font>
</body>
</html>

  1. 重启(命令如下),然后输入:http://localhost:8080/Test.jsp 看是否正常。

#./apache-tomcat-6.0.18/bin/shutdown.sh
#./apache-tomcat-6.0.18/bin/startup.sh

四:TOMCAT集群的搭建

  1. 安装两个或以上tomcat

#./apache-tomcat-6.0.18/bin/shutdown.sh
#mv apache-tomcat-6.0.18 /usr/local/TC6_A
#cd /usr/local
#cp -a TC6_A TC6_B

提示:进行上述步骤操作的原因是,本案例中集群的各个 Tomcat 服务器实例运行在同一个物理服务器上,因此集群中有几个 Tomcat 实例一般就需要几个 Tomcat 的安装。另外,由于集群中的各个 Tomcat 实例位于同一个物理服务器上的一个操作系统下,因此各个实例占用的各种网络端口不能相同,否则集群中的多个 Tomcat 实例不能同时正常启动,下面的步骤将介绍如何修改 Tomcat 实例需要使用的各个网络端口。

  1. 修改 Tomcat 实例需要使用的各个网络端口
  • 找到 server.xml 配置文件中的" Server "配置项目,并进行修改。

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

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

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

说明:第一行为两个 Tomcat 修改前的情况,第二行为 TC6_A Tomcat 修改后的情况,第三行为 TC6_B Tomcat 修改后的情况。

  • 找到 server.xml 配置文件中的相应" Connector "配置项目,并进行修改。
    • 修改前内容如下:

<!-- Define an AJP 1.3 Connector on port 8009 -->
<Connector port = "8009" protocol = "AJP/1.3" redirectPort = "8443" />

  • TC6_A 中修改后内容如下:

<!-- Define an AJP 1.3 Connector on port 8009 -->
<Connector port = " 10009 " protocol = "AJP/1.3" redirectPort = " 10043 " />

  • TC6_B 中修改后内容如下:

<!-- Define an AJP 1.3 Connector on port 8009 -->
<Connector port = " 20009 " protocol = "AJP/1.3" redirectPort = " 20043 " />

提示:此步骤目的是修改 AJP Connector 端口。

  • 找到 server.xml 配置文件中的另一个相应" Connector "配置项目,并进行修改。
    • 修改前内容如下:

<Connector port = "8080" protocol = "HTTP/1.1" connectionTimeout = "20000"
 redirectPort = "8443" />

  • TC6_A 中修改后内容如下:

<Connector port = "10001" protocol = "HTTP/1.1" connectionTimeout = "20000"
 redirectPort = "10043" />

  • TC6_B 中修改后内容如下:

<Connector port = "20001" protocol = "HTTP/1.1" connectionTimeout = "20000"
 redirectPort = "20043" />

提示:此步骤目的是修改 HTTP Connector 端口,其中的" 10001 "与" 20001 "是未来通过浏览器访问集群中各个 Tomcat 实例的 HTTP 端口。

  • 通过修改 Engine 配置选项,配置集群中每个 Tomcat 实例的名称。
    • 修改前内容如下:

<!-- You should set jvmRoute to support load-balancing via AJP ie :
<Engine name = "Standalone" defaultHost = "localhost" jvmRoute = "jvm1">
<Engine name = "Catalina" defaultHost = "localhost">
-->

  • TC6_A 中修改后内容如下:

<Engine name = "Standalone" defaultHost = "localhost" jvmRoute = " Tomcat1">

  • TC6_B 中修改后内容如下:

<Engine name = "Standalone" defaultHost = "localhost" jvmRoute = " Tomcat2">

提示:请读者注意在修改过程中要注释掉原来 name 为 Catalina 的 Engine 配置项目,将 name 为 Standalone 的 Engine 配置项目的注释去掉并修改 jvmRoute 属性。

  • 修改配置文件中的 Cluster 配置项目,对集群的各项参数进行设置。
    • 修改前内容如下:

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

  • TC6_A 中修改后内容如下:

<Cluster className = "org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions = "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" />

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

  • TC6_B 中修改后内容如下:

<Cluster

className = "org.apache.catalina.ha.tcp.SimpleTcpCluster"

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

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

提示:上述配置内容主要是对集群中各个 Tomcat 实例间进行通信的方式、端口以及 Session 共享算法的设置。本教程由于篇幅所限,不能一一详细介绍,有兴趣的读者可以参看 Tomcat 的官方文档,其中有非常详细的说明。

3、测试搭建,分别启动两个tomcat,看是否正常,若正常进行第四步。
http://localhost:10001
http://localhost:20001

4、简单的 JSP 来进一步测试对" TC6_A "和" TC6_B "的设置是否成功,分别建立两个文件:Hello.jsp。

<%@ page contentType="text/html;charset=GBK"%>
<html>
<head>
<title>Tomcat 测试 </title>
</head>
<body>
<font color="red" size="20">
<!— 使用 out 内建对象打印一条消息到输出页面 -->
<% out.print( "Tomcat 集群测试 A !!! " ); %>
</font>
</body>
</html>
TC6_B的改一行输出:
<% out.print( "Tomcat 集群测试 B !!! " ); %>

如果能顺利地在浏览器中见到上述两个页面,则说明集群中的两个 Tomcat 实例工作完全正常。下面就可以为集群安装、设置 Apache 负载均衡器了。

五、Apache负载均衡器的安装与配置

  1. 下载安装

# wget http://www.apache.org/dist/httpd/httpd-2.2.9.tar.gz
# tar -zxvf httpd-2.2.9.tar.gz
# cd httpd-2.2.9
# ./configure --prefix=/usr/local/httpd --enable-mods-shared='proxy proxy_ajp proxy_balancer'
# make
# make install

  1. 配置Apache 为 Tomcat 集群的负载均衡器

ProxyRequests Off
ProxyPass / balancer://myCluster/
<Proxy balancer://myCluster/>
BalancerMember ajp://localhost:10009 route=Tomcat1
BalancerMember ajp://localhost:20009 route=Tomcat2
</Proxy>

说明:其中" myCluster "是集群的名称," ajp://localhost:10009 route=Tomcat1 " 对应 Tomcat 集群中的 TC6_A 实例," ajp://localhost:20009 route=Tomcat2 " 对应 Tomcat 集群中的 TC6_B 实例。经过上述配置后, Apache 就可以成为前面搭建的 Tomcat 集群的负载均衡器了。

六、感受成果

  1. 重启apache httpd后,访问:http://localhost/Hello.jsp
  2. Apache 作为 Tomcat 集群的负载均衡器,使用的是轮换算法,其均匀地将请求发送到集群中的各个 Tomcat 实例。因此,从1的测试中可以看出,是轮换访问两个不同 Tomcat 实例中的 Hello.jsp 页面的。当然,看到轮换的情况也就说明 Apache 负载均衡器正常工作了。

七、补充重要细节
   
    1、在应用时候,工程的web.xml里面要加上这么一个属性,实现Session共享:
……
<distributable/> 

</web-app>

    文件中的“ <distributable/> ”项,是由于本案例将部署到集群中的多个服务器上。如果在配置文件中没 有此项,则应用在集群中不能实现分布式 Session 共享,也就是说当机后用户状态数据(存放在 Session 中的)无法无缝迁移到 Tomcat 集群中的其他服务器上。此项非常重要,请读者多加留心。

    然后在依次启动TC6_A,TC6_B,你会在TC6_A的日志里面看到他们的通信日志,不然就是没有成功。

    2、Tomcat6 集群要求负载均衡器工作在“ sticky session ”模式下,否则集群可能工作不正常。

ProxyPass ”项目进行如下修改。

  • 修改前

ProxyPass / balancer://myCluster/

  • 修改后

ProxyPass / balancer://myCluster/ lbmethod=byrequests stickysession=JSESSIONID nofailover=Off

提示: 修改后添加的“ stickysession=JSESSIONID ”项就是让 Apache 负载均衡器工作在“ sticky session ”模式下。所谓“ sticky session ”模式就是对于使用到同一个 Session 的请求绑定到集群中的特定服务器上,而不是轮换访问各个服务器,这样 Session 就不会工作不正常了。当然,对于使用不同 Session 的请求,还是进行负载均衡轮换的。

原文地址:https://www.cnblogs.com/yiyaxuan/p/12553075.html