看到很多人在做这类实验,前段时间公司在新上线的站点上本来也准备使用集群的,但由于程序中有sso认证缓存没有实现分布式,所以计划搁浅了。本来调整自己程序的实现方式后也是可以做集群的,但单独一台小机的压力测试结果还算比较满意,暂时放一放,况且传闻集群下session复制问题多多,我今天也在验证这个问题。以下是从没掌握配置到了解的过程概要:
下面是看着别人配置apache的笔记,1:修改apahce 的httpd.conf配置文件,添加mod_jk模块和映射
那么以.jsp和.action的请求将会发送到Tomcat中处理。其他的静态文件继续由apache来负责。添加worker的配置文件workers.properties
修改每个tomcat的server.xml配置文件,打开cluster配置,tomcat的doc上有简单配置介绍。
至此,我启动apache、tomcat1、tomcat2,最重要的是,启动我的sniffer工具,我喜欢从更底层来看数据的交互。由于load balance的配置上,两个tomcat的负载因子一致,所以基本上apache会把关于.jsp和.action的请求轮询的发送给这两个tomcat。我在tomcat里发布的是一个需要登陆的站点,通过sniffer可以看到,cookie里面的jsssionid在不断的变化(一个jsp中嵌套有其他的资源,比如验证码,由于每次请求的tomcat都在变化,客户端和服务端的sessionid根本没办法保持长时间的同步)。虽然在workers.properties中已经配置了 sticky_session选项,但测试中并没有成功,查看tomat的cluster-howto.html,在Cluster Basics这个章节中有说到:
于是在所有的tomcat配置文件server.xml中的修改Engine节点信息:
一位做类似实验的人说,tomcat的广播是绑定在某个网卡上的,如果机器上有多个网卡,那么这个绑定将会是第一块。这种问题在我以前做Dynamips实验、IDS测试中都遇到过,因为电脑曾经建立过VPN,所以第一块网卡就成了VPN虚拟网卡。解决的办法是修改tomcat的server.xml配置文件在Cluster节点下的Membership节点添加一个属性mcastBindAddress="192.168.0.20",Receiver节点中添加一个属性 tcpListenAddress= "192.168.0.20",这个IP是这个tomcat对外通讯的地址。
重启tomcat,第一台tomcat启动的时候,信息和前面的还是一样的,因为当前只有一台启动。第二台tomcat启动的时候,可以看到他们之间在相互发送广播。浏览器访问apache的时候,apache调度一个worker为该客户端端服务,登陆后,可以在sniffer中看到大量的广播信息。在server.xml中可以配置广播的发送频率,但不管怎么说,随着tomcat的数量增大,广播的量是相当惊人的。如果应用程序中频繁的操作session的话,这种情况更是难以想象。
failover实验,进行登陆实验。apache开始为浏览器分配的tomcat1,既登陆过程由worker来完成。登陆结束后,把tomcat1关闭,浏览器刷新,apahce返回503。由此可见,tomcat意外宕机的话,切换还是需要一定的时间的(用户还是能感受到服务器出现了问题)。再次刷新浏览器,apahce把原来tomcat1的客户交给了tomcat2接管,客户端还是处于登陆状态,说明session广播成功。
再次启动tomcat1,tomcat2中能看到tomcat1加入到集群中,但原先的客户并不会交回给tomcat1。关闭tomcat2,这里我尝试过两次,出现了不同的结果,第一次操作快一些,既关闭tomcat2后很快就刷新浏览器,用户离线了,既session出现了问题;第二次操作慢的时候,tomcat1倒是能很好的得到浏览器对应的session信息。
apache
2.2
192.168.0.20
tomcat1 192.168.0.20 (worker1 Tomcat 6.0 )
tomcat2 192.168.0.99 (worker2 Tomcat 6.0 )
tomcat1 192.168.0.20 (worker1 Tomcat 6.0 )
tomcat2 192.168.0.99 (worker2 Tomcat 6.0 )
下面是看着别人配置apache的笔记,1:修改apahce 的httpd.conf配置文件,添加mod_jk模块和映射
#到apache网站下载该模块
LoadModule jk_module modules/mod_jk.so
JkWorkersFile conf/workers.properties
JkMount /*.jsp controller
JkMount /*.action controller
LoadModule jk_module modules/mod_jk.so
JkWorkersFile conf/workers.properties
JkMount /*.jsp controller
JkMount /*.action controller
那么以.jsp和.action的请求将会发送到Tomcat中处理。其他的静态文件继续由apache来负责。添加worker的配置文件workers.properties
worker.list
=
controller
# ======== tomcat1 ========
worker.tomcat1.port = 8009
worker.tomcat1.host = 192.168.0.20
worker.tomcat1.type = ajp13
worker.tomcat1.lbfactor = 1
# ======== tomcat2 ========
worker.tomcat2.port = 8009
worker.tomcat2.host = 192.168.0.99
worker.tomcat2.type = ajp13
worker.tomcat2.lbfactor = 1
# ======== controller , load balance ========
worker.controller.type = lb
worker.controller.balance_workers = tomcat1 , tomcat2
worker.controller.sticky_session = 1
# ======== tomcat1 ========
worker.tomcat1.port = 8009
worker.tomcat1.host = 192.168.0.20
worker.tomcat1.type = ajp13
worker.tomcat1.lbfactor = 1
# ======== tomcat2 ========
worker.tomcat2.port = 8009
worker.tomcat2.host = 192.168.0.99
worker.tomcat2.type = ajp13
worker.tomcat2.lbfactor = 1
# ======== controller , load balance ========
worker.controller.type = lb
worker.controller.balance_workers = tomcat1 , tomcat2
worker.controller.sticky_session = 1
修改每个tomcat的server.xml配置文件,打开cluster配置,tomcat的doc上有简单配置介绍。
至此,我启动apache、tomcat1、tomcat2,最重要的是,启动我的sniffer工具,我喜欢从更底层来看数据的交互。由于load balance的配置上,两个tomcat的负载因子一致,所以基本上apache会把关于.jsp和.action的请求轮询的发送给这两个tomcat。我在tomcat里发布的是一个需要登陆的站点,通过sniffer可以看到,cookie里面的jsssionid在不断的变化(一个jsp中嵌套有其他的资源,比如验证码,由于每次请求的tomcat都在变化,客户端和服务端的sessionid根本没办法保持长时间的同步)。虽然在workers.properties中已经配置了 sticky_session选项,但测试中并没有成功,查看tomat的cluster-howto.html,在Cluster Basics这个章节中有说到:
If you are using mod_jk
,
make sure that jvmRoute attribute is set at your Engine
<Engine name = " Catalina " jvmRoute = " node01 " > and that the jvmRoute attribute value matches your
worker name in workers.properties
<Engine name = " Catalina " jvmRoute = " node01 " > and that the jvmRoute attribute value matches your
worker name in workers.properties
<
Engine
name
="Catalina"
defaultHost
="localhost"
jvmRoute
="tomcat1"
>
重启tomcat和apache,可以发现单个客户端的请求都只会交付给某个tomcat来执行,既apache把这个客户端的所有请求交给某个具体标示的tomcat来处理。
关于session复制,这是个比较争议的问题,我在sniffer中没有看到有广播包。当然,使用telnet是可以连接到两台机器的4000端口的,说明现在tomcat的广播发送不正确。在cluster-howto.html指出,如果需要对app进行session复制,那么要在web.xml中添加以下节点:
<distributable/
>
重启tomcat,没有什么迹象现实session复制是正常的,sniffer上没有任何相关信息,通过浏览器登陆应用程序,然后停止一个tomcat,在浏览相关信息,变成未登陆状态。说明session复制没有正常工作,倒是在控制台是上的一个提示给我找到了搜索解决该问题的关键"Manager [localhost#]: skipping state transfer. No members active in cluster group."
一位做类似实验的人说,tomcat的广播是绑定在某个网卡上的,如果机器上有多个网卡,那么这个绑定将会是第一块。这种问题在我以前做Dynamips实验、IDS测试中都遇到过,因为电脑曾经建立过VPN,所以第一块网卡就成了VPN虚拟网卡。解决的办法是修改tomcat的server.xml配置文件在Cluster节点下的Membership节点添加一个属性mcastBindAddress="192.168.0.20",Receiver节点中添加一个属性 tcpListenAddress= "192.168.0.20",这个IP是这个tomcat对外通讯的地址。
重启tomcat,第一台tomcat启动的时候,信息和前面的还是一样的,因为当前只有一台启动。第二台tomcat启动的时候,可以看到他们之间在相互发送广播。浏览器访问apache的时候,apache调度一个worker为该客户端端服务,登陆后,可以在sniffer中看到大量的广播信息。在server.xml中可以配置广播的发送频率,但不管怎么说,随着tomcat的数量增大,广播的量是相当惊人的。如果应用程序中频繁的操作session的话,这种情况更是难以想象。
failover实验,进行登陆实验。apache开始为浏览器分配的tomcat1,既登陆过程由worker来完成。登陆结束后,把tomcat1关闭,浏览器刷新,apahce返回503。由此可见,tomcat意外宕机的话,切换还是需要一定的时间的(用户还是能感受到服务器出现了问题)。再次刷新浏览器,apahce把原来tomcat1的客户交给了tomcat2接管,客户端还是处于登陆状态,说明session广播成功。
再次启动tomcat1,tomcat2中能看到tomcat1加入到集群中,但原先的客户并不会交回给tomcat1。关闭tomcat2,这里我尝试过两次,出现了不同的结果,第一次操作快一些,既关闭tomcat2后很快就刷新浏览器,用户离线了,既session出现了问题;第二次操作慢的时候,tomcat1倒是能很好的得到浏览器对应的session信息。