Windows中Apache2.2 Tomcat7 集群配置

    技术2022-05-14  24

    今天终于搞定了Apache和tomcat7整合集群以及负载均衡的问题,在此做个记录。

    客户的网站有时候会因为一个tomcat6的错误down掉,又比较难查出示什么原因,而且是没什么规律的。所以狠下心来做了个tomcat6到7的升级,并使用了tomcat7的集群。

       要说Tomcat7和6的配置确实有些不同,以前我在Server.xml的Engine节点内增加一个Listener就能自动生成一个mod_jk.conf-auto配置文件,包含到apache/conf/httpd.conf里面,然后修改一下就行了。现在就不同了,以下是我Tomcat6的server.xml配置。

    <Listener className="org.apache.jk.config.ApacheConfig" modJk="D:/Apache2.213/modules/mod_jk-1.2.26-httpd-2.2.4.so" />

    虽然提示我什么workers.properties找不到,但是照样能用。

    Tomcat7里面这招不好用了,写上这句就会报错误。无语了。只能狠下心重新查资料,看了网上的一些文章和tomcat自己带的文档。终于搞出来了,下面就跟大家分享一下我的经验,本人水平确实有限,望大家拍砖。

    首先说一下我的服务器端软件

    1.Apache,我采用带SSL模块的,因为我以后还要做CAS配置用,如果不用SSL版本也一样。httpd-2.2.17-win32-x86-openssl-0.9.8o.msi

    2.Tomcat版本是7.0.12,解压版的,要做集群,自动安装服务的有点不爽。

    一、配置apache

    1.加载链接器so文件

    安装就不说了,装好后,打开apache_home/conf/httpd.conf,找到如下文本:

    #LoadModule jk_module modules/mod_jk.so

    把它的注释去掉,从apache官网上找对应的Connector,我这个版本apache对应的是mod_jk-1.2.28-httpd-2.2.3.so。对于这块不熟的朋友我简单说一下:其中 1.2.28是Connector的版本,后面的2.2.3是对应的apache版本。其中主要是apache的版本要对应,没有正好匹配的要找相近的。我把 LoadModule jk_module modules/mod_jk.so改为: LoadModule jk_module modules/mod_jk-1.2.28-httpd-2.2.3.so。当然你也可以把so文件修改文件名为 mod_jk.so。当然这个so文件要放在 apache_home/modules里了,否则得写绝对路径了。

    这一步就算做好了,重启apache,如果没有错误说明OK。有错误无非2个。一个是文件路径写错了;另一个是so的版本与apache不匹配。

    2.增加apche与tomcat的连接

       在httpd.conf文件的末尾增加一句:Include conf/mod_jk.conf

       包含mod_jk的配置文件,当然这个文件我们还得自己建立。

       以下是我的mod_jk.conf内容:

       JkWorkersFile conf/workers.properties JkLogFile logs/mod_jk.log JkLogLevel info JkRequestLogFormat "%w %V %T" JkMount /* controller Alias /cas "D:/apache-tomcat-7.0.12/webapps/cas" <Directory "D:/apache-tomcat-7.0.12/webapps/cas">     #Options FollowSymLinks     #AllowOverride None </Directory>

     

    Alias /cas "D:/apache-tomcat-7.0.12/webapps/cas"和它下面的配置是我做cas的,不必理会,可以不要。

    JkWorkersFile conf/workers.properties指明worker的配置文件名,这也需要自己写。

    JkMount /* controller 中的“controller”是在workers.properties中配置的,目前先这么写吧。

    其他几行都是日志的配置,当时大家最好都加上,因为配置中随时有可能失败,在日志里可以查看到底出了什么错误。

    JkMount /* controller这句的还以大家应该都明白,相当于以前自动生成配置中的 JkMount /* ajp13

    当然这样配置只是为了方便,把所有的请求都转发到tomcat了,实际上肯定不会这么做的,否则apache只有纯转发的功能了,我们只需要把需要执行java代码的地址转发给tomcat,实际上可能这样配置:

    JkMount /*.do controller

    JkMount /*.jsp controller

    JkMount /yourServletURL controller

    我自己是配置一个VirtualHost,在VirtualHost配置这些转发的。

     以下是我的workers.properties内容

     worker.list=controller worker.controller.type=lb worker.controller.sticky_session=1 worker.controller.error_escalation_time=0 worker.controller.max_reply_timeouts=10 # localhost server 1 # ------------------------ worker.jvm1.reference=worker.template worker.jvm1.port=8009 worker.jvm1.host=localhost worker.jvm1.lbfactor = 5 worker.jvm1.activation=A # localhost server 2 worker.jvm2.reference=worker.template worker.jvm2.port=8019 worker.jvm2.host=localhost worker.jvm2.lbfactor=1 worker.jvm2.activation=A worker.template.type=ajp13                    worker.template.socket_connect_timeout=5000 worker.template.socket_keepalive=true worker.template.ping_mode=A worker.template.ping_timeout=10000 worker.template.connection_pool_minsize=0 worker.template.connection_pool_timeout=600 worker.template.reply_timeout=300000 worker.template.recovery_options=3 worker.controller.balance_workers=jvm1,jvm2

    具体的那些参数就不细说了,重点是tomcat的端口,默认的tomcat ajp13的端口是8009。我是在一台机器上配的2个tomcat,所以ajp的端口分别是8009和8019,还有worker.jvm1和 worker.jvm2分别代表2个Tomcat.这个在tomcat的server.xml中也有体现,下面再说这个。

    还有就是worker.controller.sticky_session=1这个参数配置为true或者1,说明需要session复制。

    二、配置Tomcat7

    打开Tomcat7的server.xml,找到<Server port="8005" shutdown="SHUTDOWN">,其中一个tomcat要把这个端口改掉,还有默认的8009,8080,8443端口,只要一台机器上部署多个Tomcat,这些端口不能重复的,反正访问的时候也不会用这些端口访问,随便改了。要注意的是<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" URIEncoding="GBK"/>,这个东西,port的值要和 workers.properties 中的 worker.jvm1.port、 worker.jvm2.port匹配。

    找到<Engine name="Catalina" defaultHost="localhost">,修改为<Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">(第一个tomcat)和<Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm2">(第二个Tomcat),这里的 jvmRoute的值就是workers.properties里的值了,匹配就好。

     

    在Engine节点内,增加如下配置:

     <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="4001" 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>

     

    那个注释掉Deployer不能加,会报个严重错误(虽然能启动成功),而且这东西是集群同步文件的,而且没有实现。上面这一段配置不用修改,端口、地址之类的不用动,原样复制就可以。

     

    这样Tomcat就算配置好了。测试一下,需要在应用的 web.xml中 web-app节点内增加

    <distributable/> 配置,这样程序就会知道需要集群了。在2个tomcat上搞2个一样的应用试验一下吧,停止一个tomcat,访问还是会成功的。

     

    需要注意的地方:

     1.配置好mod_jk的日志文件,有问题随时看。

    2. 如果你用的不是 mod_jk-1.2.28-httpd-2.2.3.so,比如我之前用的 mod_jk-1.2.26-httpd-2.2.4.so,可以用,但是 workers.properties里某些属性不支持,这我也是在日志里看到的,但是去掉不支持的属性也能用。

    3. 如果程序需要文件上传,不要上传到web目录下,最好配置上传到单独的目录中,这样集群中的所有应用才好共享同一个上传目录。否则如果一个tomcat不运行了,另一个tomcat在运行时查找本应用下的上传文件可能会找不到,因为可能传到死掉的那个tomcat应用目录下了。如果需要用浏览器直接访问这些上传的文件(不需权限控制),应该在Apache里给上传文件的路径配置一个Directory。确保文件通过web能够正常访问。我的配置如下:

    <VirtualHost *:80>     ServerAdmin aaa@yeah.net     ServerName www.xxx.cn     ServerAlias xxx.cn     #Allow from xxx.cn     ErrorLog logs/xxx.cn-error_log     CustomLog logs/xxx.cn-access_log common     DocumentRoot "E:/wwwroot/xxx_a" #主tomcat(第一个)应用根目录,我的程序叫xxx,部署2个分别较xxx_a,xxx_b     DirectoryIndex index.do index.jsp     Alias /html "E:/html" #生成静态文件的目录     <Directory E:/html>     Options FollowSymLinks     AllowOverride None     </Directory>     Alias /imageupload "D:/imageupload" #图片上传的目录     <Directory D:/imageupload>         Options FollowSymLinks         AllowOverride None     </Directory>     Alias /userfiles "E:/wwwroot/userfiles" #FckEditor的上传目录     <Directory E:/wwwroot/userfiles>     Options FollowSymLinks     AllowOverride None     </Directory>

       #禁止访问的路径配置,不让用户通过浏览器访问WEB-INF     <Directory E:/wwwroot/xxx_a/WEB-INF/>         Options FollowSymLinks         AllowOverride None         Order deny,allow         Deny from all     </Directory>

    </VirtualHost>

    4.如果web应用里有一些后台线程或后台任务之类的东西,最好的方式是单独做成一个非web应用,独立运行,这也是servlet规范推荐的方式。不方便的话,需要在web应用中配置一个参数,指定集群中的某一个实例运行这些线程,不要一个web程序的所有部署 实例 都运行线程,那样可能出现意想不到的后果。


    最新回复(0)