Tomcat負載均衡原理詳解及配置(Apache2.2.19+Tomcat7.0.12)

 原文地址: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

1.1 mod_proxy方式

  mod_proxy是一種分工合作的的形式,通過主服務器跳轉到各臺主機負責不同的任務而實現任務分工,這種形式不能實現負載均衡,只能提供主服務器的訪問跳轉
修改apache的httpd.conf文件配置

打開httpd.conf文件,取消下面四行的註釋,用以打開代理所需的.so支持模塊。

View Code

打開文件conf\extra\httpd-vhosts.conf,可以看到如下代碼:

View Code

根據需要更改<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 />節點,然後在節點結束後加上:
View Code

這裏的"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包實現負載平衡,公司生產服務器暫時就採用這種方式。
修改apache的httpd.conf文件配置

打開httpd.conf文件,取消下面四行的註釋,用以打開代理所需的.so支持模塊。

View Code
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文件最後添加以下代碼:

View Code
複製代碼
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服務器可不必修改),修改內容如下:

View Code
複製代碼
…………
<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目錄下新建如下頁面

View Code
複製代碼
<%@ 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/>標籤,如果沒有則手動建立目錄結構

View Code
複製代碼
<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目錄下
至此所有操作已完成 

啓動tomcat1、tomcat2、apache。打開瀏覽器,輸入http://localhost/test/test.jsp回車,刷新幾次即可從tomcat1與tomcat2的控制檯看到負載效果。輸入session即可看到session複製效果

 

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等。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章