Tomcat負載均衡原理詳解及配置

結構圖

使用Tomcat的童鞋們注意了。爲了增長tomcat的性能和穩定性,咱們通常採用balance和session同步機制。 下圖列出了咱們經常使用也是最簡單的解決方案。 html

說明

1 balance

1.1 mod_proxy方式

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

打開httpd.conf文件,取消下面四行的註釋,用以打開代理所需的.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  #Include conf/extra/httpd-vhosts.conf

打開文件conf\extra\httpd-vhosts.conf,能夠看到以下代碼: java

複製代碼
 1  #
 2  # Use name-based virtual hosting.
 3  #
 4  NameVirtualHost *:80
 5 
 6  #
 7  # VirtualHost example:
 8  # Almost any Apache directive may go into a VirtualHost container.
 9  # The first VirtualHost section is used for all requests that do not
10  # match a ServerName or ServerAlias in any  < VirtualHost >  block.
11  #
12  < VirtualHost  *:80 >
13      ServerAdmin webmaster@dummy-host.leader89
14      DocumentRoot "C:/Program Files/Apache Software Foundation/Apache2.2/docs/dummy-host.leader89"
15      ServerName dummy-host.leader89
16      ServerAlias www.dummy-host.leader89
17      ErrorLog "logs/dummy-host.leader89-error.log"
18      CustomLog "logs/dummy-host.leader89-access.log" common
19  </ VirtualHost >
20 
21  < VirtualHost  *:80 >
22      ServerAdmin webmaster@dummy-host2.leader89
23      DocumentRoot "C:/Program Files/Apache Software Foundation/Apache2.2/docs/dummy-host2.leader89"
24      ServerName dummy-host2.leader89
25      ErrorLog "logs/dummy-host2.leader89-error.log"
26      CustomLog "logs/dummy-host2.leader89-access.log" common
27  </ VirtualHost >
複製代碼

根據須要更改<VirtualHost>節點內的參數。 web

說明: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 />節點,而後在節點結束後加上:
複製代碼
 1  < Directory  "C:/Program Files/Apache Software Foundation/Apache2.2/docs/dummy-host.leader89" >
 2  Options Indexes FollowSymLinks
 3  AllowOverride all
 4  Order Allow,Deny
 5  Allow from all
 6  </ Directory >
 7  < Directory  "C:/Program Files/Apache Software Foundation/Apache2.2/docs/dummy-host2.leader89" >
 8  Options Indexes FollowSymLinks
 9  AllowOverride all
10  Order Allow,Deny
11  Allow from all
12  </ 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多域名多站點的功能。 apache

1.2 mod_proxy_blancer方式

  mod_proxy_balancer是mod_proxy的擴展,提供負載平衡支持,經過mod_proxy_balancer.so包實現負載平衡,公司生產服務器暫時就採用這種方式。
  修改apache的httpd.conf文件配置

打開httpd.conf文件,取消下面四行的註釋,用以打開代理所需的.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文件最後添加如下代碼: tomcat

按 Ctrl+C 複製代碼
按 Ctrl+C 複製代碼

將下載的tomcat壓縮包解壓兩份,分別命名爲tomcat一、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目錄下
至此全部操做已完成 

啓動tomcat一、tomcat二、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等。
相關文章
相關標籤/搜索