linux下配置tomcat集群的負載均衡
一、首先了解下與集群相關的幾個概念
集群:
集群是一組協同工作的服務實體,用以提供比單一服務實體更具擴展性與可用性的服務平台。在客戶端看來,一個集群就象是一個服務實體,但 事實上集群由一組服務實體組成。與單一服務實體相比較,集群提供了以下兩個關鍵特性:
· 可擴展性--集群的性能不限於單一的服務實體,新的服 務實體可以動態地加入到集群,從而增強集群的性能。
· 高可用性--集群通過服務實體冗余使客戶端免於輕易遇到out of service的警告。在集群中,同樣的服務可以由多個服務實體提供。如果一個服務實體失敗了,另一個服務實體會接管失敗的服務實體。集群提供的從一個出 錯的服務實體恢復到另一個服務實體的功能增強了應用的可用性。
為了具有可擴展性和高可用性特點,集群的必須具備以下兩大能力:
· 負 載均衡--負載均衡能把任務比較均衡地分布到集群環境下的計算和網絡資源。
· 錯誤恢復--由於某種原因,執行某個任務的資源出現故障,另一服 務實體中執行同一任務的資源接着完成任務。這種由於一個實體中的資源不能工作,另一個實體中的資源透明的繼續完成任務的過程叫錯誤恢復。
負載均衡 和錯誤恢復都要求各服務實體中有執行同一任務的資源存在,而且對於同一任務的各個資源來說,執行任務所需的信息視圖(信息上下文)必須是一樣的。
集 群分類:
Linux集群主要分成三大類( 高可用集群, 負載均衡集群,科學計算集群)
高可用集群( High Availability Cluster)
常見的就是2個節點做 成的HA集群,有很多通俗的不科學的名稱,比如"雙機熱備", "雙機互備", "雙機".
高可用集群解決的是保障用戶的應用程序持續對外提供服 務的能力。 (請注意高可用集群既不是用來保護業務數據的,保護的是用戶的業務程序對外不間斷提供服務,把因軟件/硬件/人為造成的故障對業務的影響降低到最小程 度)。
負載均衡集群(Load Balance Cluster)
負載均衡系統:集群中所有的節點都處於活動狀態,它們分攤系統的工作負載。一般Web服 務器集群、數據庫集群 和應用服務器集群都屬於這種類型。
負載均衡集群一般用於相應網絡請求的網頁服務器,數據庫服務器。這種集群可以在接到請求時,檢查接受請求較少,不繁忙的服務器,並把請求轉到這些服務器 上。從檢查其他服務器狀態這一點上 看,負載均衡和容錯集群很接近,不同之處是數量上更多。
科學計算集群(High Performance Computing Cluster)
高性能計算(High Perfermance Computing)集群,簡稱HPC集群。這類集群致力於提供單個計算機所不能提供的強大的計算能力。
負載均衡與雙機熱備的區別
負載均衡是在這多台服務器之上增加了一台負載均衡服務器,負載均衡服務器的作用是把用戶的請求平均分配到每個節點;增加集群整體的處理能力;實現網絡訪 問的均衡。
雙機熱備相當於2台服務器其中有一台是另一台的備機,也可以互為備機;主機在運行服務時,備機處於檢測狀態,主機發生故障后,備機 將接管主機的服務。
負載均衡是解決服務器壓力過大,網絡請求大量並發而設計的產品; 負載均衡的優點:WEB訪問流暢,用戶請求平均分布在每個節點上。
雙機熱備是為保障24*7小時高可用不停機而推出的產品; 雙機熱備的優點是:能保障用戶服務不間斷。
負載均衡的缺點:適用靜態WEB,如果是數據庫將不起作用,數據庫的多向同步目前還沒有完全解決的 方案。
雙機熱備缺點:用傳統加加陣列的方式增加了存儲空間,同樣也形成了單點故障;有可能雙機熱備成為虛設,因為一旦陣列崩潰,服務也意味這 停止。
Tomcat集群的三種負載均衡方式優缺點對照
1.使用DNS輪詢.
2.使用Apache R-proxy方式。
3. 使用Apache mod_jk方式.
DNS輪詢的缺點是,當集群中某台服務器停止之后,用戶由於dns緩存的緣故,便無法訪問服務,
必 須等到dns解析更新,或者這台服務器重新啟動。
還有就是必須把集群中的所有服務端口暴露給外界,沒有用apache做前置代理的方式安全,
並 且占用大量公網IP地址,而且tomcat還要負責處理靜態網頁資源,影響效率。
優點是集群配置最簡單,dns設置也非常簡單。
R- proxy的缺點是,當其中一台tomcat停止運行的時候,apache仍然會轉發請求過去,導致502網關錯誤。
但是只要服務器再啟動就不存 在這個問題。
mod_jk方式的優點是,Apache 會自動檢測到停止掉的tomcat,然后不再發請求過去。
缺點就是,當停 止掉的tomcat服務器再次啟動的時候,Apache檢測不到,仍然不會轉發請求過去。
R-proxy和mod_jk的共同優點是.可 以只將Apache置於公網,節省公網IP地址資源。
可以通過設置來實現Apache專門負責處理靜態網頁,讓Tomcat專門負責處理jsp和 servlet等動態請求。
共同缺點是:如果前置Apache代理服務器停止運行,所有集群服務將無法對外提供。
R-proxy和 mod_jk對靜態頁面請求的處理,都可以通設置來選取一個盡可能優化的效果。
這三種方式對實現最佳負載均衡都有一定不足,mod_jk相對好 些,可以通過設置lbfactor參數來分配請求任務。
二、配置tomcat集群的方法(Apache mod_jk方式)
環 境 linux redhat 4台,安裝tomcat和apache,和jdk配置的過程過於基礎,略過,這里主要講述如何配置
版本: linux redhat server 5.4企業版 tomcat6.0 apache2.2 jdk1.6
1.依次在前三台機器安 裝tomcat,jdk並配置環境變量等信息;
2.在第四台機器安裝apache
3.配置apache服務器
a:在apache 網站或其他站點下載mod_jk-1.2.26-httpd-2.2.4.so文件(不一定非要這個版本),將該文件復制到apache的modules 目錄,並設置讀執行權限 用chmod 777 *或其他命令
b:在apache_home目錄下的conf/httpd.conf文件中添加
LoadModule jk_module modules/mod_jk-1.2.26-httpd-2.2.4.so
JkWorkersFile conf/workers.properties
JkMount /* lbcontroller
代碼解釋
LoadModule jk_module modules/mod_jk-1.2.26-httpd-2.2.4.so //表示載入JK模塊
JkWorkersFile conf/workers.properties //tomcat實例配置
JkMount /* lbcontroller //設置apache分發器,/*表示apache將所有文件都由分發器lbcontroller 進行分發,你可以自行設置*.jsp,*.do等
c: 配置 workers.properties文件
在apache_home下conf目錄中新建workers.properties文 件,輸入以下內容
worker.list=lbcontroller
#Tomcat1實例配置
worker.tomcat80.host=10.71.144.80
worker.tomcat80.port=8009
worker.tomcat80.type=ajp13
# 分發權重 值越大負載越大
worker.tomcat1.lbfactor = 1
#Tomcat2實例配置
worker.tomcat81.host=10.71.144.81
worker.tomcat81.port=8009
worker.tomcat81.type=ajp13
# 分發權重 值越大負載越大
worker.tomcat81.lbfactor = 1
#Tomcat3實例配置 #負載均衡分發控制器
worker.tomcat82.host=10.71.144.82
worker.tomcat82.port=8009
worker.tomcat82.type=ajp13
# 分發權重 值越大負載越大
worker.tomcat82.lbfactor = 1
worker.lbcontroller.type=lb
worker.lbcontroller.balance_workers=tomcat80,tomcat81,tomcat82
worker.lbcontroller.sticky_session=True
代 碼解釋
worker.list=lbcontroller //內容即為httpd.conf文件中的分發器名稱。需要注意的內容 是,tomcat實例名稱
worker.tomcat80.host=....
...
worker.tomcat82.host=....
...
//這里就是tomcat80和tomcat82必須與之后tomcat中的server.xml中jvmRoute值一致
4. 配置tomcat集群
配置每個tomcat目錄下的server.xml文件,具體修改內容如下
a:Engine配置
修 改前
<Engine name="Catalina" defaultHost="localhost">
修改后
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat80" >
具 體tomcat中jvmRoute的值根據在workers.properties的配置,注意IP地址、tomcat實例名稱和jvmRoute值必須 一一對應,其他的tomcat配置方法一致
b:Cluster配置
<!--
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" >
-->
修 改后,去掉注釋並添加一些內容如下
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="8">
<Manager className="org.apache.catalina.ha.session.DeltaManager"
expireSessionsOnShutdown="false"
notifyListenersOnReplication="true"/>
<Channel className="org.apache.catalina.tribes.group.GroupChannel">
<Membership className="org.apache.catalina.tribes.membership.McastService"
address="228.0.0.4"
port="45564"
frequency="500"
dropTime="3000"/>
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
address="auto"
port="4001"
autoBind="100"
selectorTimeout="5000"
maxThreads="6"/>
<!-- timeout="60000"-->
<Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
<Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender" />
</Sender>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.ThroughputInterceptor"/>
</Channel>
<Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
filter=""/>
<Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>
<ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>
<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>
上述配置跟tomcat官方建議的配置,去掉了
<Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
tempDir="/tmp/war-temp/"
deployDir="/tmp/war-deploy/"
watchDir="/tmp/war-listen/"
watchEnabled="false"/>
如果不去掉這部分,則tomcat啟動會報"FarmWarDeployer can only work as host cluster subelement!."
c:session復制配置
tomcat集群中的 session管理,主要有兩種方式:
1).粘性session
表示從同一窗口發來的請求都將有集群中的同一個tomcat進行處理。配 置方式是在上面workers.properties文件中
worker.lbcontroller.sticky_session=True
粘性session的好處在不會在不同的tomcat上來回跳動處理請求,但是壞處是如果處理該session的tomcat崩潰,那么之后 的請求將由其他tomcat處理,原有session失效而重新新建一個新的session,這樣如果繼續從session取值,會拋出 nullpointer的訪問異常。
2).session復制
session復制是指tomcat彼此之間通過組播方式將session 發到各個tomcat實例上,如果其中一個訪問出錯,則另外tomcat仍然具有有效的session內容,從而能正常接管其session。壞處是當 tomcat實例很多,或者用戶在session中有大量操作時,組播發送的信息量十分驚人。session復制配置則是在發布的web應用程序中的 web.xml中添加
<distributable/>
此外,session復制所需的JDK必須是JDK 5.0及其以上版本
5.測試配置
新建一個jsp頁面,寫入如下代碼,保存index.jsp,分別在tomcat的webapp目錄下建 立ydl文件夾,將寫好的index.jsp文件上傳到3台服務器的tomcat\webapp\ydl目錄下
測試的index.jsp文件內容
<%@ page contentType="text/html; charset=GBK" %>
<%@ page import="java.util.*" %>
<html><head><title>Cluster App Test</title></head>
<body>
Server Info:
<%
out.println(request.getLocalAddr() + " : " + request.getLocalPort()+"<br>");%>
<%
out.println("<br> ID " + session.getId()+"<br>");
// 如果有新的 Session 屬性設置
String dataName = request.getParameter("dataName");
if (dataName != null && dataName.length() > 0) {
String dataValue = request.getParameter("dataValue");
session.setAttribute(dataName, dataValue);
}
out.print("<b>Session 列表</b>");
Enumeration e = session.getAttributeNames();
while (e.hasMoreElements()) {
String name = (String)e.nextElement();
String value = session.getAttribute(name).toString();
out.println( name + " = " + value+"<br>");
System.out.println( name + " = " + value);
}
%>
<form. action="index.jsp" method="POST">
名稱:<input type=text size=20 name="dataName">
<br>
值:<input type=text size=20 name="dataValue">
<br>
<input type=submit>
</form>
</body>
</html>
重 啟apache服務器和三個tomcat服務器,到此集群負載均衡已配置完成。測試負載均衡先測試apache,訪問
http://10.70.144.480/ydl/index.jsp
看 能夠運行,能運行,則已建立負載均衡
關閉和啟動任何一個tomcat,另外兩個tomcat前台打印相關日志信息並自動復制一份session
a:先啟動 apache服務器httpd
b:啟動名為tomcat80的服務器
前台啟動tomcat輸出日志方法
#cd /home/support/tomcat-apache6.0/bin
#./catalin.sh run
在瀏覽器中輸入訪 問地址http://10.70.144.480/ydl/index.jsp
可 以看到請求被轉發到了tomcat80進行處理
c:啟動tomcat81
可以發現,tomcat81啟動后搜索到了tomcat2實例, 並進行了session復制,在tomcat2的控制台也可以找到輸出打印日志
關閉tomcat80(ctrl+c)后繼續刷新url訪問。 tomcat81控制台中輸出的session 依然與之前tomcat80中的一致,並且在session中保存的屬性值仍然有效。