网上关于 Apache + JK + Tomcat 的集群配置例子很多,按着例子配置下来,基本都能运行,不过,在一些重要的地方却没有进一步的说明。这次公司一个产品就是采用 Apache+JK+Tomcat 集群,在整个配置、测试过程中,遇到了许多的问题,经过不断测试、摸索,最后总算是搞定了,性能也达到了预期的目标。针对网上的例子,感觉有必要再详细的介绍一下我的配置过程,对一些要特别注意的地方进行补充。

集群有别于分布式的解决方案,它采用的是每台服务器运行相同应用的策略,由负责平衡的服务器进行分流,这对提高整个系统的并发量及吞吐量是更有效的办法。而集群对请求的处理又有两种不同的方式:负载平衡、状态复制 ( 即集群 ) ,状态复制需要在各服务器间复制应用状态,而负载平衡则不用,每台服务器都是独立的。实践证明,在各应用服务器之间不需要状态复制的情况下,负载平衡可以达到性能的线性增长及更高的并发需求。

对于集群的其它基础知识,在此就不再做累赘。以下就这次 Apache + JK + Tomcat 的负载平衡配置进行总结,重点关注整个配置及注意事项。

准备软件

1、  Tomcat JBoss(本文档中采用的是JBoss4.0.2/SPAN>);

2、  apache2.0.54/SPAN>是开源的Web服务器,下载地址为: http://www.apache.org/dist/httpd/binaries/

3、  mod_jk-1.2.14apache-2.0.54.so 模块,jkmod_jserv的替代者,它是Tomcat-Apache插件,为ApacheTomcat的连接器,处理TomcatApache之间的通信,在集群配置中充当负载均衡器的作用,当前的最新版本为1.2.15,不过不同JK版本与不同的Apache版本之间的搭配有一些差异,有的甚至配不起来。JK2是符合apache2.x系列的新品,但由于其配置太过麻烦,使用的人很少,所以目前已停止开发,所以我们采用了jk连接器,下载地址:http://www.apache.org/dist/tomcat/tomcat-connectors/jk/binaries/

集群与负载平衡

使用 mod_jk 默认的以轮循方式进行平衡负载,假设有四个服务器节点,有 10 个请求,则四个节点分别接受请求编号如下:

节点 1

节点 2

节点 3

节点 4

1

2

3

4

5

6

7

8

9

10

 

 

而集群方式也是使用这种方法进行平衡。 Tomcat 中的集群原理是通过组播的方式进行节点的查找并使用 TCP 连接进行会话的复制。

     集群不同于负载平衡的是,由于集群服务需要在处理请求之间不断地进行会话复制,复制后的会话将会慢慢变得庞大,因此它的资源占用率是非常高的,如果在并发量大的应用中,复制的会话大小会变得相当大,而使用的总内存更是会迅速升高。

     但集群的会话复制,增加了系统的高可用性。由于在每台服务器都保存有用户的 Session 信息,如果服务器群中某台当机,应用可以自动切换到其它服务器上继续运行,而用户的信息不会丢失,这提高了应用的冗错性。

具体采用负载平衡还是集群,这要看应用的需求了。

安装配置 Apache

1 、下载 Apache 的安装程序 apache_2.0.54win32-x86-no_ssl.exe 后,安装很简单,一路回车,就此略过。

2 、安装完毕后,将下载的 mod_jk-1.2.14apache-2.0.54.so 复制到 Apache 安装目录下的 modules 子目录中。

3 、然后进入 Apache 安装目录下的 conf 子目录中,打开 httpd.conf 配置文件,在最后插入以下一行:

Include conf/mod_jk.conf

4、  conf 子目录下,建立一个新的配置文件: mod_jk.conf ,此文件为 Apache 加载连接器的配置文件,文件名可修改,但要与 httpd.conf Include 的文件名一致,内容如下:

# Load mod_jk module. Specify the filename

# of the mod_jk lib you’ve downloaded and

# installed in the previous section

# 加载 mod_jk 模块

LoadModule jk_module modules/mod_jk-1.2.14apache-2.0.54.so

# Where to find workers.properties

JkWorkersFile conf/workers2.properties

# Where to put jk logs

JkLogFile logs/mod_jk.log

# Set the jk log level [debug/error/info]

JkLogLevel info

# Select the log format

JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "

# JkOptions indicate to send SSL KEY SIZE,

JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories

# JkRequestLogFormat set the request format

JkRequestLogFormat "%w %V %T"

# 请求分发配置,可以配置多项

JkMount /* loadbalancer

# 关掉主机 Lookup ,如果为 on ,很影响性能,可以有 10 多秒钟的延迟。
HostnameLookups Off

注: 蓝色加粗的两行是重点,第一句是 Apache 加载 JK 模块用的;第二句为配置哪些 URL 请求将由负载平衡器来处理。

5、  conf 子目录下,建立一个新的配置文件: workers2.properties ,此文件为负载平衡的配置文件,文件名不能修改,这是 JK 默认的名字,内容如下:

worker.list=loadbalancer

# Define the first node...

worker.server99.port=8009

worker.server99.host=192.168.11.99

worker.server99.type=ajp13

worker.server99.lbfactor=1

worker.server99.local_worker=1

worker.server99.cachesize=1000

worker.server99.cache_timeout=600

worker.server99.socket_keepalive=1

worker.server99.socket_timeout=0

worker.server99.reclycle_timeout=300

worker.server99.retries=3

# Define the second node...

worker.server202.port=8009

worker.server202.host=192.168.11.202

worker.server202.type=ajp13

worker.server202.lbfactor=1

worker.server202.local_worker=1

worker.server202.cachesize=1000

worker.server202.cache_timeout=600

worker.server202.socket_keepalive=1

worker.server202.socket_timeout=0

worker.server202.reclycle_timeout=300

worker.server202.retries=3

# Now we define the load-balancing behaviour

worker.loadbalancer.type=lb

worker.retries=3

worker.loadbalancer.balance_workers=server99 ,server202

worker.loadbalancer.sticky_session=true

worker.loadbalancer.sticky_session_force=true

注: 以上定义了两个 worker ,一个为 server99 ,另一个为 server202 ,定义了一个负载平衡服务器 loadbalancer ,其中标蓝色的为重点配置项,相关的详细说明可以看官方的网站文档: http://tomcat.apache.org/connectors-doc/ ,其它节点的定义可以直接 Copy ,修改一下节点名及 IP 就好了。
A
worker.list=loadbalancer

设定工作的负载平衡器,各 Tomcat 节点不能加入此列表。

    B worker.server99.lbfactor

负载平衡的权重比,如果此权重比越大,则分配到此节点的请求越多,如以上两个节点的权重比为 1:1 ,则为平均分配。

C worker.loadbalancer.balance_workers=server99,server202

   指定此负载平衡器负责的 Tomcat 应用节点。

D worker.loadbalancer.sticky_session=true

   此处指定集群是否需要会话复制,如果设为 true ,则表明为会话粘性,不进行会话复制,当某用户的请求第一次分发到哪台 Tomcat 后,后继的请求会一直分发到此 Tomcat 服务器上处理;如果设为 false ,则表明需求会话复制。

E worker.loadbalancer.sticky_session_force=true

   如果上面的 sticky_session 设为 true 时,建议此处也设为 true ,此参数表明如果集群中某台 Tomcat 服务器在多次请求没有响应后,是否将当前的请求,转发到其它 Tomcat 服务器上处理;此参数在 sticky_session=true 时,影响比较大,会导致转发到其它 Tomcat 服务器上的请求,找不到原来的 session ,所以如果此时请求中有读取 session 中某些信息的话,就会导致应用的 null 异常。

6 Apache 服务器的配置文件 httpd.conf 中,默认有三个参数对性能的影响比较大,但根据不同的性能要求,参数的表现又不一样,太小并发提不上去,太大性能反而不好,建议根据项目的需要,实际做个测试,如并发要求 800 的话,可以设定为:

# 一个连接的最大请求数量

MaxKeepAliveRequests   1000 (值为 0 ,则不限制数量)

# 每个进程的线程数,最大 1920 NT 只启动父子两个进程,不能设置启动多个进程

ThreadsPerChild      1000 (最大为 1920

# 每个子进程能够处理的最大请求数

MaxRequestsPerChild   1000 (值为 0 ,则不限制数量)

这三个参数要根据不同的需求,不同的服务器进行调整。

安装配置 Tomcat JBoss

1 、对于 Tomcat JBoss 的安装,这里不做说明,目前我们是采用 Apache+JBoss ,不过, JBoss 也是用的 Tomcat ,所以这里的配置也是适合 Tomcat 的;

2 、对于 JBoss 的配置,很简单,只需要改两个地方就可以了:

第一个地方:进入 jboss-4.0.2server\default\deploy\jbossweb-tomcat55.sar ,打开 server.xml ,大约在第 32 行左右,有 ,在其中加入一个参数,变为:

第二个地方:进入 jboss-4.0.2server\default\deploy\jbossweb-tomcat55.sar\META-INF 目录,打开 jboss-service.xml ,大约在 110 行,有 false/SPAN>,将其改为:

true/SPAN>

这里有一个需要特别注意的地方, JBoss Tomcat 中,关于 AJP 连接协议的默认配置,对于大并发量是不够用的,要做一些修改,进入 jboss-4.0.2server\default\deploy\jbossweb-tomcat55.sar ,打开 server.xml ,找到 的地方,这里是定义 AJP 连接器的地方,它的配置中没有 maxThreads 项,默认为 200 ,我们可以做修改:

<="" address="${jboss.bind.address}" port="8009" />

         emptySessionPath="true" enableLookups="false" redirectPort="8443"

         protocol="AJP/1.3" maxThreads="3000"/>

maxThreads 的值要看你的并发量多大,设置太大也不好。

运行

至此,整个配置全部完成,注意一点是,在各 JBoss 节点,重启或新增加一个 JBoss 节点时,需要重新启动 Apache ,而对于服务器群中某个 JBoss 节点 shutdown Apache 会自动侦测,不用重新启动。

如果在运行过程中,群中的某个 JBoss 节点 shutdown ,则已登录到此服务器上的用户的请求将出错,此服务器负责的 session 将丢失,但 Apache 会自动侦测到此服务器已 shutdown ,后继的新请求将不会再引导到此节点。

对于负责请求分发的 Apache 服务器,需要消耗大量的 CPU 资源,因此如果在测试过程中出现一些 Service Temporarily Unavailable Server  has shut down the connection prematurely 这样的错误,这一般都是服务器配置不够好引起的,或者是 Apache Tomcat 、及应用中的某些配置不够使用,这时候就要考虑换更好的机器或优化应用中的配置。

常见问题

一、 cannot connect to server :无法连接到服务器。这种情况是服务器的配置有问题,服务器无法承受过多的并发连接了,需要优化服务器的配置:

如操作系统采用更高版本,如 windows 2003 server

优化 tomcat 配置: maxThreads="500" minSpareThreads="400" maxSpareThreads="450"

但是 tomcat  最多支持 500 个并发访问

优化 apache 配置:

ThreadsPerChild 1900

MaxRequestsPerChild  10000

二、  Action.c(10): Error -27791: Server  has shut down the connection prematurely

HTTP Status-Code=503 (Service Temporarily Unavailable)
一般都是由于服务器配置不够好引起的,需要优化硬件和调整程序了。

三、无法处理请求:

当我们输入  ***.do  命令后, apache 却返回错误信息,而连接 tomcat 却没有问题。原因是没有把 .do 命令转发给 tomcat 处理。解决方法如下:

apache 配置文件中配置如下内容:

JkMount /*.jsp loadbalancer

JkMount /*.do loadbalancer