原文位址:http://www.cnblogs.com/leader_89/archive/2011/08/01/2109181.html
Tomcat負載均衡原理詳解及配置(Apache2.2.19+Tomcat7.0.12)
結構圖
使用Tomcat的童鞋們注意了。為了增加tomcat的性能和穩定性,我們一般采用balance和session同步機制。 下圖列出了我們常用也是最簡單的解決方案。
說明1 balance
- 負載均衡我們一般采用Apache proxy和Apache+mod_jk方式
-
所使用軟體:Apache2.2.19 http://httpd.apache.org/download.cgi#apache22;
Tomcat7 http://tomcat.apache.org/download-70.cgi
1.1 mod_proxy方式
mod_proxy是一種分工合作的的形式,通過主伺服器跳轉到各台主機負責不同的任務而實作任務分工,這種形式不能實作負載均衡,隻能提供主伺服器的通路跳轉
修改apache的httpd.conf檔案配置
打開httpd.conf檔案,取消下面四行的注釋,用以打開代理所需的.so支援子產品。
View Code
打開檔案conf\extra\httpd-vhosts.conf,可以看到如下代碼:
根據需要更改<VirtualHost>節點内的參數。
說明:NameVirtualHost *:80和<VirtualHost *:80>中 的*為目前伺服器IP,如果有固定IP可以用IP把*替換掉,我這裡使用的是動态IP,是以用*,我看apache幫助文檔的時候,一直認為這裡的*為對 應的域名,這個想法應該是錯誤的,因為我填上域名的時候一直沒有設定成功。ServerName這個填域名,DocumentRoot填 ServerName上域名對應的根目錄。
注:
如果通路域名出現403權限錯誤,且對應的檔案夾everyone的權限都是全部控制,則問題出在httpd.conf上。
編輯httpd.conf,找到DocumentRoot "C:/Program Files/Apache Software Foundation/Apache2.2/htdocs"這項,這是預設根目錄路徑,但是要更改的不是這個,一直往下找,找到<Directory />節點,然後在節點結束後加上:
這裡的"C:/Program Files/Apache Software Foundation/Apache2.2/docs/dummy-host.leader89"和"C:/Program Files/Apache Software Foundation/Apache2.2/docs/dummy-host2.leader89"為前面VirtualHost裡的路徑。
儲存httpd.conf和httpd-vhosts.conf,然後重新開機Apache。
然 後通路dummy-host.leader89打開的是C:/Program Files/Apache Software Foundation/Apache2.2/docs/dummy-host.leader89目錄,
通路dummy-host2.leader89的是C:/Program Files/Apache Software Foundation/Apache2.2/docs/dummy-host2.leader89目錄,
實作了單IP多域名多站點的功能。
1.2 mod_proxy_blancer方式
mod_proxy_balancer是mod_proxy的擴充,提供負載平衡支援,通過mod_proxy_balancer.so包實作負載平衡,公司生産伺服器暫時就采用這種方式。
1 #LoadModule proxy_http_module modules/mod_proxy_http.so
2 #LoadModule proxy_connect_module modules/mod_proxy_connect.so
3 #LoadModule proxy_module modules/mod_proxy.so
4 #LoadModule proxy_module modules/mod_proxy_blancer.so
在httpd.conf檔案最後添加以下代碼:
1 ProxyPass / balancer://proxy/ #注意這裡以"/"結尾
2 <Proxy balancer://proxy>
3 BalancerMember http://127.0.0.1:8080/ loadfactor=3 #BalancerMember 及其後面的URL表示要配置的背景伺服器、test表示該伺服器下的項目名稱
4 BalancerMember http://127.0.0.1:8081/ loadfactor=1 #參數”loadfactor”表示背景伺服器負載到由Apache發送請求的權值,該值預設為1
5 </Proxy>
将下載下傳的tomcat壓縮包解壓兩份,分别命名為tomcat1、tomcat2。修改tomcat2中conf/server.xml中部分端口号(因為我在本機做測試,是以為了解決端口号被占用的問題修改tomcat2的端口号,使tomcat1與tomcat2能夠同時啟動,實作多伺服器;如果有多台PC伺服器可不必修改),修改内容如下:
…………
<Server port="9005" shutdown="SHUTDOWN"> #此處修改為9005,避免與tomcat1的8005沖突
…………
…………
<Connector port="8081" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" /> #此處修改為8081,避免與tomcat1的8080沖突
…………
<!-- Define an AJP 1.3 Connector on port 8009 -->
<Connector port="9009" protocol="AJP/1.3" redirectPort="8443" /> #此處修改為9009,避免與tomcat1的8009沖突。如果使用的是mod_proxy_blancer方式此處可以注釋掉,如果使用的是mod_jk方式則此處必須存在
…………
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/> #去掉該行注釋即可實作session複制功能
…………
1)輪詢均衡政策的配置
ProxyPass / balancer://proxy/
<Proxy balancer://proxy>
BalancerMember http://127.0.0.1:8080/
BalancerMember http://127.0.0.1:8081/
</Proxy>
實作負載均衡的原理如下:
假設Apache接收到http://localhost/test請求,由于該請求滿足ProxyPass條件(其URL字首為“/"),該請求會 被分發到背景某一個BalancerMember,譬如,該請求可能會轉發到http://127.0.0.1:8080/進行處理?當第二 個滿足條件的URL請求過來時,該請求可能會被分發到另外一台BalancerMember,譬如,可能會轉發到http://127.0.0.1:8081/如此循環反複,便實作了負載均衡的機制?
2)按權重配置設定均衡政策的配置
ProxyPass / balancer://proxy/
<Proxy balancer://proxy>
BalancerMember http://127.0.0.1:8080/ loadfactor=3
BalancerMember http://127.0.0.1:8081/ loadfactor=1
</Proxy>
參數"loadfactor"表示背景伺服器負載到由Apache發送請求的權值,該值預設為1,可以将該值設定為1到100之間的任何值?以上面 的配置為例,介紹如何實作按權重配置設定的負載均衡,現假設Apache收到http://myserver/test 4次這樣的請求,該請求分别被負載到背景 伺服器,則有3次連續的這樣請求被負載到BalancerMember為http://127.0.0.1:8080/的伺服器,有1次這樣的請求被 負載BalancerMember為http://127.0.0.1:8081/背景伺服器?實作了按照權重連續配置設定的均衡政策?
3)權重請求響應負載均衡政策的配置
ProxyPass / balancer://proxy/ lbmethod=bytraffic
<Proxy balancer://proxy>
BalancerMember http://127.0.0.1:8080/ loadfactor=3
BalancerMember http://127.0.0.1:8081/ loadfactor=1
</Proxy>
參數“lbmethod=bytraffic"表示背景伺服器負載請求和響應的位元組數,處理位元組數的多少是以權值的方式來表示的? “loadfactor"表示背景伺服器處理負載請求和響應位元組數的權值,該值預設為1,可以将該值設定在1到100的任何值?根據以上配置是這麼進行均 衡負載的,假設Apache接收到http://myserver/test請求,将請求轉發給背景伺服器,如果BalancerMember為http://127.0.0.1:8080/背景伺服器負載到這個請求,那麼它處理請求和響應的位元組數是BalancerMember為http://127.0.0.1:8081/伺服器的3倍(回想(2)均衡配置,(2)是以請求數作為權重負載均衡的,(3)是以流量為權重負載均衡的,這是 最大的差別)?
至此配置以完成
在tomcat1中webapps檔案夾下建立test項目檔案夾,test目錄下建立如下頁面
<%@ 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.println("<b>Session 清單</b><br>");
System.out.println("============================");
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="test.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>
如需session複制功能此步驟為必須操作
打開項目的WEB-INF下的web.xml在</web-app>内添加<distributable/>标簽,如果沒有則手動建立目錄結構
<web-app 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" version="2.4">
<display-name>TomcatDemo</display-name>
<distributable/> #一般均放在web-app結束節點上一行
</web-app>
将tomcat1下的test項目複制一份到tomcat2的webapps目錄下
至此所有操作已完成
1.3 mod_jk方案
mod_jk是比較專門針對Tomcat的方法,通過AJP協定連接配接Tomcat
1)需要下載下傳mod_jk-1.2.31-httpd-2.2.3.so http://archive.apache.org/dist/tomcat/tomcat-connectors/jk/binaries/win32/jk-1.2.31/mod_jk-1.2.31-httpd- 2.2.3.so包并放到Apache安裝目錄下的modules子目錄中
2)然後配置mod_jk.conf
3)配置workers2.properties
注意:因為mod_jk2方式不被推薦,mod_jk2已經不再被更新了。是以,此處不予列舉,如有需要參考者請留言,将随後貼出。
proxy、proxy_blancer和mod_jk的比較
- proxy的缺點是,當其中一台tomcat停止運作的時候,apache仍然會轉發請求過去,導緻502網關錯誤。但是隻要伺服器再啟動就不存在這個問題。
-
mod_jk方式的優點是,Apache 會自動檢測到停止掉的tomcat,然後不再發請求過去。
缺點就是,當停止掉的tomcat伺服器再次啟動的時候,Apache檢測不到,仍然不會轉發請求過去。
-
proxy和mod_jk的共同優點是.可以隻将Apache置于公網,節省公網IP位址資源。
可以通過設定來實作Apache專門負責處理靜态網頁,讓Tomcat專門負責處理jsp和servlet等動态請求。
共同缺點是:如果前置Apache代理伺服器停止運作,所有叢集服務将無法對外提供。
-
proxy和mod_jk對靜态頁面請求的處理,都可以通設定來選取一個盡可能優化的效果。
mod_proxy_balancer和mod_jk都需要修改tomcat的配置檔案配合
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat1">
- 這三種Tomcat叢集方式對實作最佳負載均衡都有一定不足,mod_proxy_balancer和mod_jk相對好些,mod_jk的設定能力更強些。lbfactor參數來配置設定請求任務。
- apache自帶mod_proxy功能子產品中目前隻可以實作兩種不同的負載均衡叢集實作方式,第一種是分工合作的的形式,通過各台主機負責不同的任務而實 現任務分工。第二種是不同的機器在擔任同樣的任務,某台機器出現故障主機可以自動檢測到将不會影響到用戶端,而第一種卻不能實作但第一種實作方式的優點在 于他是主伺服器負擔相應沒第二種大因為台隻是提供跳轉指路功能,形象的說他不給你帶路隻是告訴你有條路可以到,但到了那是否可以看到你見的人他已經不會去管你了。相比之下第二種性能要比第一種會好很多;但他們都有個共同點都是一托N形式來完成任務的是以你的主機性能一定要好。
2 session同步
- 對于tomcat的叢集有兩種方式,這個主要是針對session而言的。一種就是sticky模式,即黏性會話模式;另外一種就是session複制模式了。
2.1 sticky模式
- 利用負載均衡器的sticky模式的方式把所有同一session的請求都發送到相同的Tomcat節點。這樣不同使用者的請求就被平均配置設定到叢集 中各個tomcat節點上,實作負載均衡的能力。這樣做的缺點是沒有災難恢複的能力。一旦一個節點發生故障,這個節點上所有的session資訊全部丢 失;
- 這種方式其實是由前端balancer實作的,基本不需要webServer做任何改動(隻需要修改jvmRoute="tomcat1")
- 同一使用者同一session隻和一個webServer互動,一旦這個webserver發生故障,本次session将丢失,使用者不能繼續使用
2.2 複制模式
- 利用Tomcat session複制的機制使得所有session在所有Tomcat節點中保持一緻。當一個節點修改一個session資料的時候,該節點會把這個 session的所有内容序列化,然後廣播給所有其它節點。這樣當下一個使用者請求被負載均衡器配置設定到另外一個節點的時候,那個節點上有完備的 session資訊可以用來服務該請求。這種做法的問題是對session哪怕有一點點修改,也要把整個sessions資料全部序列化 (serialize),還要廣播給叢集中所有節點,不管該節點到底需不需要這個session。這樣很容易會造成大量的網絡通信,導緻網絡阻塞。一般采 用這種方式,當Tomcat節點超過4個時候,整個叢集的吞吐量就不能再上升了;
-
此方式是通過tomcat本身提供的功能,隻需要修改server.xml檔案
(1)修改Engine節點資訊: <Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat1">
(2)去掉<Cluster> <\Cluster> 的注釋符
(3)web.xml中增加 <distributable/>
2.3 Terracotta模式
- 另一種方式就是利用開源軟體Terracotta。Terracotta的基本原理是對于叢集間共享的資料,當在一個節點發生變化的時 候,Terracotta隻把變化的部分發送給Terracotta伺服器,然後由伺服器把它轉發給真正需要這個資料的節點。這樣對網絡的壓力就非常小, 各個節點也不必浪費CPU時間和記憶體進行大量的序列化操作。把這種叢集間資料共享的機制應用在session同步上,相當于對tomcat第二種叢集實作 機制進行了優化,既避免了對資料庫的依賴,又能達到負載均衡和災難恢複的效果。在對比測試中,采用Terracotta搭建Tomcat叢集,節點達到8 個時候,整個叢集的吞吐量還一直是線性增長的。
2.4 三種模式比較
- sticky模式最大的缺點就是不支援failover,一旦某一個webServer發生故障則此節點上的session就會丢失,是以不建議使用。
-
複制模式可以保證個别節點發生故障不丢失session,但是複制時需要序列化資料這會影響到系統的性能。
另外性能随着伺服器增加急劇下降,而且容易引起廣播風暴。經測試當Tomcat節點超過4個時候,整個叢集的吞吐量就不能再上升了。
需要修改server.xml和web.xml檔案
-
使用第三方軟體Terracotta進行session同步,配置對原來的web應用完全透明,原有程式不用做任何修改。。
資料不需要序列化,也不占用webServer的記憶體,執行效率高。
- terracotta本身支援HA,增加了系統的穩定性。
- Terracotta是開源的,并且可以內建在很多主流的開源軟體中,如Jetty、Tomcat、Spring、Geronimo和EHCache等。