1.1 術語定義
服務軟體是b/s或c/s結構的s部分,是爲b或c提供服務的服務性軟件系統。
服務硬體指提供計算服務的硬件、比如pc機、pc服務器。
服務實體通指服務軟體和服務硬體。
客戶端指接受服務實體服務的軟件或硬件。
1.2 兩大關鍵特性
集羣是一組協同工作的服務實體,用以提供比單一服務實體更具擴展性與可用性的服務平臺。在客戶端看來,一個集羣就象是一個服務實體,但事實上集羣由一組服務實體組成。與單一服務實體相比較,集羣提供了以下兩個關鍵特性:
· 可擴展性--集羣的性能不限於單一的服務實體,新的服務實體可以動態地加入到集羣,從而增強集羣的性能。
· 高可用性--集羣通過服務實體冗餘使客戶端免於輕易遇到out of service的警告。在集羣中,同樣的服務可以由多個服務實體提供。如果一個服務實體失敗了,另一個服務實體會接管失敗的服務實體。集羣提供的從一個出錯的服務實體恢復到另一個服務實體的功能增強了應用的可用性。
1.3 兩大能力
爲了具有可擴展性和高可用性特點,集羣的必須具備以下兩大能力:
· 負載均衡--負載均衡能把任務比較均衡地分佈到集羣環境下的計算和網絡資源。
· 錯誤恢復--由於某種原因,執行某個任務的資源出現故障,另一服務實體中執行同一任務的資源接着完成任務。這種由於一個實體中的資源不能工作,另一個實體中的資源透明的繼續完成任務的過程叫錯誤恢復。
負載均衡和錯誤恢復都要求各服務實體中有執行同一任務的資源存在,而且對於同一任務的各個資源來說,執行任務所需的信息視圖(信息上下文)必須是一樣的。
1.4 兩大技術
實現集羣務必要有以下兩大技術:
· 集羣地址--集羣由多個服務實體組成,集羣客戶端通過訪問集羣的集羣地址獲取集羣內部各服務實體的功能。具有單一集羣地址(也叫單一影像)是集羣的一個基本特徵。維護集羣地址的設置被稱爲負載均衡器。負載均衡器內部負責管理各個服務實體的加入和退出,外部負責集羣地址向內部服務實體地址的轉換。有的負載均衡器實現真正的負載均衡算法,有的只支持任務的轉換。只實現任務轉換的負載均衡器適用於支持ACTIVE-STANDBY的集羣環境,在那裏,集羣中只有一個服務實體工作,當正在工作的服務實體發生故障時,負載均衡器把後來的任務轉向另外一個服務實體。
· 內部通信--爲了能協同工作、實現負載均衡和錯誤恢復,集羣各實體間必須時常通信,比如負載均衡器對服務實體心跳測試信息、服務實體間任務執行上下文信息的通信。
具有同一個集羣地址使得客戶端能訪問集羣提供的計算服務,一個集羣地址下隱藏了各個服務實體的內部地址,使得客戶要求的計算服務能在各個服務實體之間分佈。內部通信是集羣能正常運轉的基礎,它使得集羣具有均衡負載和錯誤恢復的能力。
從上圖可知,由服務實體1、服務實體2和負載均衡器組成了一個集羣。服務實體1和服務實體2參與對客戶端的服務支持工作,均衡負載器爲客戶端維護集羣的單一影像。集羣實體間通過內部的通信網交流信息,這種交流機制一般採用組播協議。負載均衡器通過內部通信網探測各服務實體的心跳信息,服務實體間通過內部通信網完成任務資源的傳播。可以看出,配置集羣主要由配置服務實體和配置負載均衡器兩部分組成。本文使用tomcat 4.12、apache 2.0.43配置集羣環境,相關軟件的部署圖如下:
服務實體1/2,負載均衡器可以部署在不同的機器上,也可以在同一機器上,本文環境爲同一機器。
2.1 準備軟件
· tomcat是開源servlet /jsp服務器,下載地點 http://jakarta.apache.org/ ;
· apache 2.0.43 是開源的www服務器,下載地點 http://www.apache.org/dist/httpd/binaries/ ;
· JavaGroups是一個實現集羣服務實體間通信的通信協議,下載地址: http://www.javagroups.com/ ;
在apache下配置負載均衡器分爲三步,注意每次修改httpd.conf和workers2.properties時不要忘了重新啓動apache。
jk2的配置全在一個配置文件中,文件名爲workers2.properties,和apache 的httpd.conf放在同一個目錄下。以下是這個文件的內容:
[uri:/*] group=lb:lb1 #++++++++++++++++++++++++++++++++++++++++++ |
對於jk2模塊的負載均衡配置可參見相關站點,值得提及的是jk2的負載均衡還支持權重分配等優秀功能。
2.3 配置tomcat
同屬於一個集羣下的兩個服務實體,要求功能的同一性,所以我們可先安裝和配置第一個tomcat,接着拷貝形成第二個tomcat,最後配置第二個tomcat。
2.3.1 安裝第一個tomcat
安裝tomcat 非常簡單,本文就不再描述。我們假設第一個tomcat的安裝路徑爲d:/tomcat1。
拷貝tomcat-javagroups.jar和javagroups.jar到d:/tomcat1/ server/lib 路徑下。
2.3.2 配置第一個tomcat
2.3.2.1 配置jk2
tomcat 中的jk2 connector缺省端口爲8009,爲了在一臺機器上運行兩個tomcat,修改D:/Tomcat1/conf/jk2.properties,設置jk2 connector的端口爲11009,整個文件內容如下:
#++++++++++++++ channelSocket.port=11009 #++++++++++++++ |
2.3.2.2 修改server.conf
首先爲了讓一臺機器上運行兩個tomcat,修改server.conf的tomcat 停止指令監聽端口:
<Server port="8005" shutdown="SHUTDOWN" debug="0"> 改爲 <Server port="11005" shutdown="SHUTDOWN" debug="0"> |
然後打開JK2 AJP connector ,關閉其它connector,下面是JK2 AJP 1.3的樣子,這裏已把它的端口改爲11009:
<!-- Define a Coyote/JK2 AJP 1.3 Connector on port 8009 --> <Connector className="org.apache.coyote.tomcat4.CoyoteConnector" port="11009" minProcessors="5" maxProcessors="75" enableLookups="true" redirectPort="8443" acceptCount="10" debug="0" connectionTimeout="20000" useURIValidationHack="false" protocolHandlerClassName="org.apache.jk.server.JkCoyoteHandler"/> |
接着配置需要集羣支持的webapp(比如examples) 的context,添加如下
<Manager className="org.apache.catalina.session.InMemoryReplicationManager" protocolStack="UDP(mcast_addr=228.1.2.3;mcast_port=45566;ip_ttl=32):PING(timeout=3000; |
num_initial_members=6):FD(timeout=5000):VERIFY_SUSPECT(timeout=1500): pbcast.STABLE(desired_avg_gossip=10000):pbcast.NAKACK(gc_lag=10; retransmit_timeout=3000):UNICAST(timeout=5000;min_wait_time=2000): MERGE2:FRAG:pbcast.GMS(join_timeout=5000;join_retry_timeout=2000; shun=false;print_local_addr=false)"> </Manager> |
注意protocolStack的值必須在一行內寫完。
2.3.3 配置第二個tomcat
我們先把已經配好的第一個tomcat複製一份,形成第二個tomcat,假設路徑爲d:/tomcat2。
2.3.3.1 配置jk2
修改D:/Tomcat2/conf/jk2.properties,設置jk2 connector的端口12009,整個文件內容如下:
#++++++++++++++ channelSocket.port=12009 #++++++++++++++ |
2.3.3.2 修改server.conf
有了第一個tomcat的配置我們只需修改server.conf的tomcat 停止指令監聽端口:
<Server port="11005" shutdown="SHUTDOWN" debug="0"> 改爲 <Server port="12005" shutdown="SHUTDOWN" debug="0"> |
然後設置JK2 AJP connector 端口爲12009。
啓動apache,tomcat1和tomcat2。
2.4.1 測試負載均衡
我們先準備兩個文件,第一個文件爲test.jsp,拷貝到第一個tomcat 的根web應用的目錄即d:/tomcat1/webapps/ROOT 下:
<html> <body bgcolor="red"> <center> <%= request.getSession().getId() %> |
<h1>Tomcat 1</h1> </body> </html> |
第二個文件也爲test.jsp,拷貝到第二個tomcat 的根web應用的目錄即d:/tomcat2/webapps/ROOT 下:
<html> <body bgcolor="blue"> <center> <%= request.getSession().getId() %> <h1>Tomcat 2</h1> </body> </html> |
從不同的瀏覽器中多次輸入地址http://localhost/test.jsp 會看到不同的顏色,這表明apache中的jk2模塊起到了負載均衡的作用。
2.4.2 測試錯誤恢復
訪問url: http://localhost/examples/servlet/SessionExample 可以得到一個關於session的例子,我們用它來測試集羣的錯誤恢復能力。
測試步驟如下:
1. 關閉tomcat1和tomcat2;
2. 啓動tomcat1
3.
4. 在瀏覽器中輸入屬性名tomcat1和屬性值tomcat1再提交,返回的頁面顯示session中有剛剛輸入的tomcat1屬性;
5. 啓動tomcat2;
6. 過一會後(等待tomcat2和tomcat1通信並複製信息)關閉tomcat1;
7. 在瀏覽器中輸入屬性名tomcat2和屬性值tomcat2再提交,返回的頁面顯示session中有剛剛輸入的tomcat2屬性,還有先前輸入的tomcat1屬性;
8. 啓動tomcat1;
9. 過一會後(等待tomcat2和tomcat1通信並複製信息)關閉tomcat2;
10. 在瀏覽器中輸入屬性名tomcat11和屬性值tomcat11再提交,返回的頁面顯示session中有剛剛輸入的tomcat11屬性,還有先前輸入的tomcat1和tomcat2屬性;