都是從網上搜集,再通過自己的實踐總結出來的,相信對沒做過Load Balancing的同學會有一定幫助。
先來三章概念:
1. JBoss集群配置概念
JBoss集群(Cluster)是 一組計算機節點的集合,它們作為一個整體向用戶提供一組網絡資源。一個理想的集群對用戶是透明的。用戶由單一入口訪問集群的資源,從來不會意識到集群中的 節點。在他們看來,集群是一個系統,而非多個計算機系統。集群還應該支持隨意增加和減少集群系統的節點,而這同樣不會影響到用戶的訪問。
2. JBoss集群分類
習慣上,JBoss集群配置的關鍵是把集群分為高可用(HighAvailability,簡稱HA)集群和高性能計算(HighPerfermanceComputing,簡稱HPC)集群兩類。HA集群的目標是提高系統的可使用性(availability),即可靠性(reliability)和可維護性(maintainability)。請不要將集群中的可使用性(availability)與UE和交互設計中的可用性(Usability)混淆。HA集群的核心是防止單點失效,這一般是通過失敗轉移來實現的,即在一個節點失效后由另一個節點接替服務。不丟失用戶狀態。HA集群的其他主要特性還包括負載均衡、session同步等。我們使用的SQLServer數據庫的雙機熱備和Oracle的RAC都屬於HA集群。HPC集群采用並行計算技術提供超大規模計算和存儲能力,多數超級計算機都是HPC集群。這不是我們關注的集群。
3. JBoss集群架構
JBoss集群是HA集群。JBoss集群有2種架構。一是客戶端攔截器(Client-sideinterceptor)架構,一是負載均衡器(Loadbalancer)架構。客戶端攔截器架構適於用C/S結構,負載均衡器架構適用於B/S結構。本文只敘述負載均衡器架構的JBoss集群。
負載均衡器架構由負載均衡器和n個集群節點組成。每個節點是一個JBoss服 務器實例。負載均衡器是全局唯一的前置機,全部用戶請求都發到負載均衡器,由其轉發到各節點。當負載均衡器發現一個節點失效后,會將請求轉發到另一個節點 上,從而保證服務得以延續。負載均衡器同時負責加權靜態負載均衡調度。總之,負載均衡器的健康程度決定了集群的全局健康度,負載均衡器失敗將導致集群全部 失效。這是前置機架構集群的主要潛在問題。
JBoss的負載均衡器架構集群實際是由Tomcat的HTTP集群實現的。JBoss有自己的負載均衡器,但效果不佳,官方文檔沒有介紹,幾乎沒有人使用。一般情況下,我們都是采用apache+mod_jk作為負載均衡器。下文敘述的都是基於這種架構。mod_jk是apache的一個插件,負責apache與tomcat之間的通訊,是JBoss集群配置(tomcat集群)的關鍵。
4.准備環境
文件都上傳在金山網盤上
文件名:mod_jk-1.2.28-httpd-2.2.3.so, 訪問地址: http://www.kuaipan.cn/file/id_55504313337774089.htm ,訪問密碼:T5P6iu
文件名: jboss-4.2.3.GA.zip , http://www.kuaipan.cn/file/id_55504313337774088.htm 訪問密碼:Tt6aA4
文件名:apache_2.2.11-win32-x86-no_ssl.msi, http://www.kuaipan.cn/file/id_55504313337774087.htm 訪問密碼:epzU33
如果失效了搜索下面文件名下載:
1)jboss-4.2.3.GA.zip
2)apache_2.2.11-win32-x86-no_ssl
3)mod_jk-1.2.28-httpd-2.2.3.so
5、安裝JDK什么的不用說了吧 略過N字
6、安裝apache_2.2.11-win32-x86-no_ssl
安裝無非就是下一步下一步,不過有幾點要注意:
1)路徑不要有中文,不要空格(地球上的程序員都知道)
2)apache安裝時提示占用的端口為80和8080 ,這兩個端口都是容易占用的端口,安裝的時候最好確保沒被占用,
雖然安裝之后可以修改他的端口,但是安裝的時候要是被占用,不知道會不會有什么影響。
正確安裝后可以在電腦右下角看到圖標,還是先把他關掉吧,下面要做配置了
7、修改apache配置文件。
1)、找到安裝apache時的目錄下 conf/httpd.conf文件,在最后一行添加 Include conf/mod_jk.conf
2)、把mod_jk-1.2.28-httpd-2.2.3.so 文件 更名為 mod_jk.so后,復制到安裝目錄下/modules文件夾中。注意同目錄下有個manual,不要搞錯了。
3)、在 conf文件夾下新建文件mod_jk.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/workers.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
或者我網盤中也有 mod_jk.conf http://www.kuaipan.cn/file/id_55504313337774090.htm 訪問密碼:ejLrRQ
4)、在conf文件夾下 新建文件 workers.properties

worker.list=loadbalancer,node1,node2 # Define the first node... worker.node1.port=8009 worker.node1.host=10.0.0.114 worker.node1.type=ajp13 worker.node1.lbfactor=1 worker.node1.local_worker=1 worker.node1.cachesize=10 worker.node1.cache_timeout=600 worker.node1.reply_timeout=100 worker.node1.socket_timeout=300 # Define the first node... worker.node2.port=9711 worker.node2.host=10.0.0.114 worker.node2.type=ajp13 worker.node2.lbfactor=1 worker.node2.local_worker=1 worker.node2.cachesize=10 worker.node2.cache_timeout=600 worker.node2.reply_timeout=100 worker.node2.socket_timeout=300 # Now we define the load-balancing behaviour worker.loadbalancer.type=lb worker.loadbalancer.balanced_workers=node1,node2 worker.loadbalancer.sticky_session=0

reply_timeout:此屬性告訴web server在接到遠端的Tomcat已死並實時的切換到集群中的另外一個Tomcat的回應之前等待一段時間。默認情況下web server將永遠等待。屬性值為web server要等待回應的時間(以ms為單位),所以如果具有運行時間較長的servlet時設置其值要小心。此屬性在jk 1.2.6版本被增加進來,以求避免Tomcat的死機和在支持ajp13的servlet引擎上發生的問題。此屬性默認為失效的。 cache_timeout:本屬性用於聲明JK在cache中保留一個打開的socket的時間,它對減少web serer的線程數有所幫助。眾所周知,一個身背重負的web server(例如apache)建立childs/threads來處理負載,而當負載減少時它將銷毀無用的childs/threads。每個 child在轉發請求給Tomcat時要打開一個ajp13連接,而在Tomcat那一端也將建立一個ajp13線程與之通訊。 socket_timeout:此屬性說明連接在未激活的狀況下持續多久,web server將主動切斷之。這是一個使Tomcat端的陳舊線程不致過多的好方法,但是也帶來了在下一次請求到來時需要重新打開socket的開銷。此屬性與cache_timeout有類似的功效,但是它工作在non-cache模式。 本例采用一台計算機同時啟動2個jboss的方案實現的。所以ip一樣,AJP/1.3端口不一樣。JBoss的Web集群使用apache的 mod_jk,瀏覽器請求apache服務器,apache服務器根據workers.properties中的配置進行request分發,apache服務器和Jboss中的Tomcat可以用ajp1.3進行通信的,request通過ajp1.3協議的包裝被發送到 Jboss,Jboss執行后返回結果。 其中對於node的命名規則是worker.節點名.xxxx。所以上述文件定義了兩個節點:node1和node2。8009端口是jboss默認的ajp端口,另外需要注意的是worker.node2.lbfactor參數,它是節點的負載加權,它的值越大,獲得負載的機會就越大。可以根據node的硬件性能進行調整。 上面的文件中配置了兩個節點,name分別為 node1,node2,指定兩個節點的IP,並在worker.loadbalancer.balance_workers中指定所有的node列表,worker.loadbalancer.sticky_session設置是否啟用“粘着的”Session,sticky session是指來自同一IP的請求將被發送到同一個Jboss節點,sticky session設為0的話同一session的不同請求會被負載均衡分發到不同的jboss節點上。
5)、在conf/目錄創建新文件uriworkermap.properties 內容如下

/jmx-console=loadbalancer /jmx-console/*=loadbalancer /web-console=loadbalancer /web-console/*=loadbalancer
至此apache的配置基本結束唯一剩下的就是workers.properties中節點的IP還需要根據之后的部署環境來改變
8、Jboss集群節點配置
1) 修改 JBOSS_HOME/server/all/deploy/jboss-web.deployer/server.xml
將Engine 修改如下:<Engine name="jboss.web" defaultHost="localhost" jvmRoute="node1">
這個node1 應該是與workers.properties中節點名字一樣,還有一個jboss 就應該是node2了。
2)修改 JBOSS_HOME/server/all/deploy/ jboss-web.deployer/META-INF/ jboss-service.xml
找到<attributename="UseJK">改為:<attribute name="UseJK">true</attribute>
9、部署(到此關於負載均衡的配置就結束了。當然還差一點點,關於session的復制,稍后再說,先把基本的跑起來。)
1)部署之前先把之前的workers.properties 中的兩個ip改成待部署的兩台服務器的ip 和端口,注意 文件中設置的端口並非server.xml 中的TCP端口,而是下面一點的AJP端口
2)啟動你的Apache服務器 必須先啟動Apache
3)啟動jboss 這邊要注意了 啟動時一定要這樣啟動: 搞一個快捷方式到桌面 ,右鍵 屬性 在目標中 加上參數 -c all -b xxx.xxx.xxx.xxx(jboss所在服務器的ip)
10、部署完也該測試下
1)測試的話自己建個web程序,然后寫個servlet 打印一句話,然后把web工程放到jboss/server/all/frame/下 ,
這樣兩個jboss下就都有了,如果不行再放一次,然后重啟jboss。
2)訪問 http://localhost:<port>/ port 是apache的端口,不要訪問錯了。首先應該可以看到jboss的歡迎頁。
如果可以看到,那應該沒問題了,可以把和apache在同一服務器的那個jboss關掉,如果還可以訪問,說明99% OK
3)進一步測試, 訪問你之前寫的那個servlet, 它打印的語句應該分別在兩台服務器的jboss控制台中輪流顯示。
11、Jboss集群的session復制
集群的缺陷和粘着session
截止到現在,Jboss集群工作得很完美,除了session。
目前配置的Jboss集群中,各節點是被動的、相互獨立的,相當於增加了節點狀態檢測的DNS輪詢,所以session也是相互獨立的。當同一用戶的2個請求被轉發到不同的Jboss 節點 上時,會出現session信息假”丟失”的現象。
為此,Jboss提出粘着session(stickysession)概念。使用粘着session后,來自同一IP的請求將被發送到同一個Jboss節點,從而保證session使用的連續性。如果應用中沒有 使用 session,則可以使用非粘着session的jboss集群。這樣,負載分布更為合理。
設置方法是編輯負載均衡器的/usr/local/apache2/conf/workers.properties的worker.loadbalancer.sticky_session。設置為1使用粘着session,設置為0不使用粘着session。
使用粘着session還存在一種隱患,當某個節點發生故障時,該節點的session將全部丟失。要徹底解決這個問題,就要用到jboss session復制。
jboss session復制是jboss session同步的一種實現。原理是在各Jboss節點間建立橫向聯系,每個節點都將本節點的session變化同步到其他所有節點上。
jboss的session復制與HTTP集群是相互配合、相互獨立的兩個系統。session復制是節點間的橫向聯系,HTTP集群是負載均衡器與節點的縱向聯系。
12、配置Jboss節點
JBOSS_HOME/server/all/deploy/jbossweb-cluster.sar/META-INF/jboss-service.xml,
找到<attribute name="ClusterConfig">,有udp和tcp兩種方式,任選一種即可,將bind_addr改為本機ip,
<tcpping initial_hosts 值設為:node1 IP[7810],node2 IP[7810] ;
找到 server/all/deploy/tc5-cluster.sar/META-INF/jboss-service.xml
找到<config><udp,將><config>到</config>全部注釋掉.
jboss session復制有UDP和TCP兩種方式.UDP采用多播方式,但問題比較多,所以采用TCP方式。
找到<config> <tcp,將><config>到</config>生效.並對該部分進行以下修改:
·
· 將全部down_thread和up_thread的false都改為true.
·
· 在<tcp bind_addr=”后填入本機的IP,比如<TCP bind_addr=”>
·
· 在<tcpping initial_hosts=”后填入本機和集群其他全部Jboss節點的IP[7810],比如
<tcpping initial_hosts=”192.168.130.95[7810],192.168.130.99[7810],192.168.130.112[7810]”></tcpping>
·
其他參數還包括:

ClusterName是集群名稱,比如partition1.
在同一局域網內,可以存在多個jboss集群,根據集群名稱區分它們.所以,集群中各節點配置的集群名稱必須一致,而機器IP則沒有特殊要求,只要它們能相互連通. 理論上,可以在一台機器上安裝多個Jboss實例,分屬於不同的集群.但這會極大地增加復雜度,是不好的配置方式.jijian91嚴重不建議給自己找麻煩。
IsolationLevel是隔離等級.
可選值包括:SERIALIZABLE, REPEATABLE_READ, READ_COMMITTED,READ_UNCOMMITTED, 和 NONE。這里的隔離級別和數據庫的隔離級別有同樣的含義,對於大多數WEB應用程序來講通常設置為REPEATABLE_READ。
CacheMode是緩存模式。
由於session復制是通過緩存實現的,所以實際上是復制模式.可選值包括:REPL_SYNC 和REPL_ASYNC,確定改變是應該同步還是異步復制。缺省值是REPL_ASYNC.使用同步復制,確保在請求完成之前傳播改變,session同步沒有滯后,但效率低。
在應用程序的web.xml的<web-app>段中增加<distributable />,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee ; http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd ;">
<distributable />
</web-app>
在web-inf中添加jboss-web.xml文件,內容如下:
<!DOCTYPE jboss-web PUBLIC
"-//JBoss//DTD Web Application 4.2//EN"
"http://www.jboss.org/j2ee/dtd/jboss-web_4_2.dtd">
<jboss-web>
<replication-config>
<replication-trigger>SET_AND_NON_PRIMITIVE_GET</replication-trigger>
<replication-granularity>SESSION</replication-granularity>
<replication-field-batch-mode>true</replication-field-batch-mode>
</replication-config>
<context-root>/</context-root>
</jboss-web>
13、測試session 復制
新建servlet 然后下面是測試的代碼

import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet implementation class testSession */ public class testSession extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public testSession() { super(); // TODO Auto-generated constructor stub } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { synchronized (request) { doPost(request, response); } } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Object o = request.getSession().getAttribute("index"); if(o==null){ request.getSession().setAttribute("index", 1); System.out.println(1); }else{ request.getSession().setAttribute("index", new Integer(o.toString()).intValue()+1); System.out.println(request.getSession().getAttribute("index").toString()); } } }
紅色字都是滿重要的地方,或者是我在看網上資料是含糊不清的地方,在此做下總結。方便以后工作。