一、程序
(1)jboss-4.0.3SP1
(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、及應用中的某些配置不夠使用,這時候就要考慮換更好的機器或優化應用中的配置。