一、程序
(1)jboss- 4.0.3 SP1
(2)mod_jk-apache- 2.2.4 .so
(3)apache_ 2.2.6 -win32-x86-openssl-0.9.8e.msi
二、CLUSTER簡介
会话状态复制用来复制集群中不同节点上客户端的连接状态,以实现当集群中的某一节点发生故障时,集群中的其它节点能够接管连接到故障节点的客户端请求,接管过程对客户端透明,客户端并不知道是否发生了服务提供者的转移。会话状态复制由JBOSS本身进行控制,当JBOSS以all的配置方式运行时,默认已经启动了会话状态复制。
负载均衡顾名思义,就是希望集群中的节点均衡的提供服务,以防止某一节点负载过中,导致连接到该节点的请求不能在期望的时间内完成,而其它的节点又存在大量的资源空闲。负载均衡并不由JBOSS本身控制,它需要额外的软件或硬件交换机或路由器进行负载均衡控制。本文是通过 Apache与mod_jk进行负载均衡配置。负载均衡可以选择针对每个请求的均衡,或者是针对每个用户的均衡。选择不同的粒度,需要不同的状态同步方式。
Web cluster实际上可以划分为两个话题:负载均衡 (load balance) 和状态同步。它们是互相独立的,单独配置。负载均衡的概念比较简单,重要的是负载均衡的粒度,可以选择针对每个request的均衡,或者是针对每个用户的均衡。选择不同的粒度,需要不同的状态同步方式。
1、基于request的负载均衡
该种方式下,负载均衡器 (load balancer)会根据各个node的状况,把每个http request进行分发。使用这样的均衡策略,就必须在多个node之间复制用户的session,实时保持整个cluster的用户状态同步,这种操作被称为session复制(session replication)。Jboss的实现原理是使用拦截器(interceptor),根据用户的同步策略拦截request,做同步处理后再交给 server产生响应。
该方法的优点是客户不会被绑定都具体的node,只要还有一个node存活,用户状态都不会丢失,cluster都能够继续工作。缺点是node之间通信频繁,响应速度有影响,多并发、高频操作的情况下性能下降比较厉害。
2、基于用户的负载均衡
该种方式下,当用户发出第一个request后,负载均衡器动态的把该用户分配到某个节点,并记录该节点的jvm路由,以后该用户的所有request 都会被绑定这个jvm路由,用户只会与该server发生交互,这种策略被称为粘性session(session sticky)。
该方法的优点是响应速度快,多个节点之间无须通信。缺点也很明显,某个node死掉以后,它负责的所有用户都会丢失session。
三、CLUSTER——基于用户的负载均衡配置
Jboss的负载均衡目前有两种方案,一是使用apache的mod_jk,二是使用jboss自带的负载均衡模块。現著重介紹使用apache的mod_jk的配置方案,主要的運行流程是,JBoss 的Web集群使用Apache的mod_jk,浏览器请求Apache服务器,Apache服务器根据workers.properties中的配置进行request分发,Apache服务器和Jboss中的Tomcat可以用ajp1.3进行通信的,request通过ajp1.3协议的包装被发送到 Jboss,而Jboss执行后返回结果。
1、Apache的配置
1)將mod_jk文件復制到%apache%/modules里面,并將mod_jk文件改名為mod_jk.so,改名是為了將來mod_jk文件更新后,不用再改動配置文件。
2)修改%apache%/conf/httpd.conf,在文件末尾添加:
# Include mod_jk's specific configuration file
Include conf/mod-jk2.conf
3)在%apache%/conf下新建文件mod_jk2.conf,文件内容如下:
# Load mod_jk module. Specify the filename
# of the mod_jk lib you’ve downloaded and
# installed in the previous section
LoadModule jk_module modules/mod_jk.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
其中LoadModule jk_module modules/mod_jk.so ,是指定所裝載的模塊路徑;JkWorkersFile conf/workers2.properties,是指定運行模式內容的路徑;JkMount /* loadbalancer的意思是,把所有的请求都发给loadbalancer处理,可以通过修改url来控制发送某些request。
4)在%apache%/conf下新建文workers2.properties,其内容为:
# 定义request所要转发到的节点
worker.list=loadbalancer,server1,server2
# 定义节点server1
# Define the first node...
worker.server1.port=8009
worker.server1.host=172.23.2.84
worker.server1.type=ajp13
worker.server1.lbfactor=1
worker.server1.local_worker=1
worker.server1.cachesize=10
# 定义节点server2
# Define the first node...
worker.server2.port=8009
worker.server2.host=172.23.2.14
worker.server2.type=ajp13
worker.server2.lbfactor=1
worker.server2.local_worker=1
worker.server2.cachesize=10
# 负载配置
# Now we define the load-balancing behaviour
worker.loadbalancer.type=lb
worker.loadbalancer.balanced_workers=server1,server2
worker.loadbalancer.sticky_session=1
#worker.loadbalancer.sticky_session_force=1
其中对于node的命名规则是worker.节点名.xxxx。所以上述文件定义了两个节点:server1和server2。8009端口是 jboss默认的ajp端口,另外需要注意的是worker.server2.lbfactor参数,它是节点的负载加权,它的值越大,获得负载的机会就越大,即分配到此节点的请求越多,如以上两个节点的权重比为1:1,则为平均分配,负载加权的設置可以根据node的硬件性能进行调整。
worker.loadbalancer.sticky_session参数是指定是否使用粘性session,等于0,每个请求将在两个节点中进行负载平衡;等于1参数的设定,则表明为会话粘性,不进行会话复制,也就意味着一旦用户通过APACHE连接到某台JBOSS SERVER(创建了session),则只要在该台JBOSS服务正常的情况下,该用户所有的请求都将会发送至该JBOSS SERVER,我在查詢網絡文檔時,曾經有人建議如果該參數設置為1即true,那么最好同時設置worker.loadbalancer.sticky_session_force=1,此参数表明如果集群中某台Tomcat服务器在多次请求没有响应后,是否将当前的请求,转发到其它Tomcat服务器上处理,但是我覺得此参数在sticky_session=true时,影响比较大,会导致转发到其它Tomcat服务器上的请求,找不到原来的session,所以如果此时请求中有读取session中某些信息的话,就会导致应用的null异常,建議還是不用設置。
所有需要负载均衡的节点,都必须在worker.loadbalancer.balanced_workers参数中列举出来。请记住所有node的名称和它对应着哪台机器,后面的配置中会使用到。
5)启动apache:%apache/bin/apache.exe,正常情况下没有任何提示。
6)负载均衡的配置基本完成,启动jboss,其中过程中会列出DefaultPatition中所有的节点:
run.bat -c all
2、JBOSS的配置
要在JBOSS中配置JVM路由( JVMRoute),否則APACHE就无法知道究竟哪些SESSION是属于哪个节点的。
1)修改jboss-service.xml配置文件%jboss%/server/all/deploy/jbossweb-tomcat55.sar/ META-INF/ jboss-service.xml將<attribute name="UseJK">false</attribute>,将false值改为true。
2)修改server.xml配置文件
修改server1上的%jboss%/server/all/deploy/jbossweb-tomcat55.sar/ server.xml,在32行左右有:
<Engine name="jboss.web" defaultHost="localhost">
给它增加一个jvmRoute属性:
<Engine jvmRoute="server1" name="jboss.web" defaultHost="localhost">
请注意,jvmRoute的值必须和mod_jk中的节点名字一致,否则无法正确路由,并且Cluster中的所有节点都应该做相应的配置,即要在server2上修改server.xml配置文件為<Engine jvmRoute="server2" name="jboss.web" defaultHost="localhost">
3)WEB程序的配置
需要在你的Web应用中修改配置文件,让它支持集群。在WEB-INF/web.xml中加入属性: <distributable/>
3、分布式热部署(distributable hot deploy)
其實,APACHE已經幫WEB開發者考慮到在CLUSTER環境下的部署应用問題,當CLUSTER環境下的所有JBOSS是以-c all的方式來啟動的,那么將自动支持分布式热部署,對于WEB開發者而言,只要將支持cluster的应用,打包稱EAR,WAR或SAR文件,放到%jboss%/server/all/farm下,那么处于同一CLUSTER中的其他节点会自动下载并且部署,JBOSS把这个称为Farm deploy。
這里有兩點是需要注意的:(1)JBOSS的分布式热部署功能是在JBOSS啟動后才有效,也就是說,要在JBOSS啟動后,將打包后的EAR,WAR或SAR文件發布到%jboss%/server/all/farm,同一CLUSTER中的其他节点才会自动下载并且部署;(2)JBOSS的分布式热部署功能只針對文件有效,也就是說只有將WEB項目打包成文件,JBOSS才能辨識并且通知同一CLUSTER中的其他节点。
四、相關設置
Apache服务器的配置文件httpd.conf中,默认有三个参数对性能的影响比较大,但根据不同的性能要求,参数的表现又不一样,太小并发提不上去,太大性能反而不好,建议根据项目的需要,实际做个测试,如并发要求800的话,可以设定为:
#每个进程的线程数,最大1920。NT只启动父子两个进程,不能设置启动多个进程
ThreadsPerChild 1000(最大为1920)
#每个子进程能够处理的最大请求数
MaxRequestsPerChild 1000(值为0,则不限制数量)
这里有一个需要特别注意的地方,JBoss的Tomcat中,关于AJP连接协议的默认配置,对于大并发量是不够用的,要做一些修改,进入jboss- 4.0.2 /server/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、及应用中的某些配置不够使用,这时候就要考虑换更好的机器或优化应用中的配置。