基於mod_proxy+Apache 2.2.16+Tomcat 7的負載均衡與集羣配置

基於mod_proxy+Apache 2.2.16+Tomcat 7的負載均衡與集羣配置

Peter Wei

 

週日晚和GF的老鄉們喝了五糧液,導致週一起不了牀,只好請假在家睡覺。白天睡了半天,晚上自然睡不着覺。正好現在的項目中也用到了負載均衡和集羣的東西,雖然有新手貼的危險,但還是手癢,決定寫點東西,以備不時之需。也希望能對大家有所幫助。

 

第一章.        背景簡介

對於大多數企業應用,都希望能做到7*24小時不間斷運行。要保持如此高的可用性並非易事,比較常見的做法是將系統部署到多臺機器上,每臺機器都對外提供同樣的功能,這就是集羣。系統變爲集羣時,除了要求系統能夠支持水平伸縮外,還要解決兩個問題:

1,如何均衡地訪問到提供業務功能的機器。

2,如何保證當機器出現問題時,用戶能自動跳轉到另外的機器,不影響使用。

常用的負載均衡技術有硬件和軟件兩種,本示例常用軟件的技術實現。軟件也有很多實現技術,如基於apachemod_jk以及mod_proxy等。基於mod_jk的文章有不少,本文演示一下用mod_proxy的方式。

       實現集羣的應用最重要的是處理用戶Session的問題,一般有三種策略:

1,Session複製

2,Session Sticky

3,基於Cache的集中式Session

本文使用的是Tomcat 7.0.2應用服務器,用的方法是Session複製。

 

第二章.        配置環境

1,JDK1.6,請自行下載安裝,Java的一般都裝有的吧,哈哈。

2,Apache 2.2.16, (released 2010-07-25),現在爲止應該是最新的穩定版本,下載地址: http://httpd.apache.org/download.cgi

3,Tomcat 7.0.2,目前也是最新的版本。Minimum Java Version1.6.下載地址:http://tomcat.apache.org/download-70.cgi

4,安裝過程略

 

第三章.        部署圖

 

第四章.        Tomcat7集羣配置

一、              就地取材,複製tomcat7/webapps下的examples,重命名爲cluster應用,以後就用cluster做測試。

二、              詳細配置參照tomcat7 /webapps/docs/cluster-howto.html 或者http://tomcat.apache.org/tomcat-7.0-doc/cluster-howto.html

三、              爲了在Tomcat7中實現session複製,以下必需完成:

·   所有session屬性必需實現 java.io.Serializable

·   Uncomment the Cluster element in server.xml。把Cluster元素的註釋去掉。參照四

·   If you have defined custom cluster valves, make sure you have the ReplicationValve defined as well under the Cluster element in server.xml 。參照四

·   If your Tomcat instances are running on the same machine, make sure the tcpListenPort attribute is unique for each instance, in most cases Tomcat is smart enough to resolve this on it's own by autodetecting available ports in the range 4000-4100。參照四< Receiver>中的註釋

·   Make sure your web.xml has the <distributable/> element or set at your <Context distributable="true" /> 參照四.2

·   If you are using mod_jk, make sure that jvmRoute attribute is set at your Engine <Engine name="Catalina" jvmRoute="node01" > and that the jvmRoute attribute value matches your worker name in workers.properties .mod_jk的情況,我們可以不管。

·   Make sure that all nodes have the same time and sync with NTP service! 當使用多臺機器時,要保證不同機器時間的同步。原因爲tomcat session複製的一些機制。具體原因看文檔。

·   Make sure that your loadbalancer is configured for sticky session mode. 保證負載均衡軟件設置爲session sticky模式。

四、            詳細配置:

1.      修改tomcat7_a/conf/server.xml, 我們採用的是默認的配置,在<Engine>節點下添加:

 

<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"

<!—tcpListenPort如果是同一機器部署兩個tomcat7應用,則修改tomcat7_b4001,以免衝突. 不同機器下,不用更改此項。—>

                      port="4000"

                      autoBind="100"

                      selectorTimeout="5000"

                      maxThreads="6"/>

 

            <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"/>

          </Channel>

 

          <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"

                 filter=""/>

          <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>

 

          <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"

                    tempDir="/tmp/war-temp/"

                    deployDir="/tmp/war-deploy/"

                    watchDir="/tmp/war-listen/"

                    watchEnabled="false"/>

 

          <ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>

          <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>

        </Cluster>

2.      <Connector port="8081" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> 修改,僅爲了調試方便。

3.      tomcat7_a/webapps/cluster/WEB-INF/web.xml中加入<distributable/>

4.      <Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat7_a">,添加jvmRoute屬性,此項爲後面apache負載均衡用到。

 

五、            複製一份tomcat7_a應用,改名爲tomcat7_b.只是爲了圖方便,實際應該複製的是前面的cluster工程。注意以下幾點配置就ok.

1.      修改tomcat7_a/conf/server.xml 中的Server port屬性<Server port="8006" shutdown="SHUTDOWN">,因爲是同一臺機器兩個tomcat應用,所以改一下。

2.      修改<connector port="8082" protocol="HTTP/1.1" onnectionTimeout="20000" edirectPort="8443" />,同理,爲了避免同一臺機器端口號衝突。部置在不同的機器是不用管的。

3.      修改<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat7_b">此項爲後面apache負載均衡用到。

4.      修改<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="auto" port="4001" autoBind="100" selectorTimeout="5000" maxThreads="6"/>

5.     tomcat7_b/ebapps/cluster/WEB-INF/web.xml中加入<distributable/>

 

到此集羣配置完成.

第五章.        集羣測試

1.      tomcat7_atomcat7_bcluster工程中分別添加測試文件:testCluster.jsp

<%@ page contentType="text/html; charset=GBK" %>

<%@ page import="java.util.*" %>

<html><head><title>Cluster Test</title></head>

<body>

<%

  //HttpSession session = request.getSession(true);

  System.out.println(session.getId());

  out.println("<br> SESSION ID:" + session.getId()+"<br>"); 

  // 如果有新的請求,則添加session屬性

  String name = request.getParameter("name");

  if (name != null && name.length() > 0) {

     String value = request.getParameter("value");

     session.setAttribute(name, value);

  } 

       out.print("<b>Session List:</b>"); 

       Enumeration<String> names = session.getAttributeNames();

       while (names.hasMoreElements()) {

              String sname = names.nextElement();

              String value = session.getAttribute(sname).toString();

              out.println( sname + " = " + value+"<br>");

        System.out.println( sname + " = " + value);

   }

%>

  <form action="testCluster.jsp" method="post">

    名稱:<input type=text size=20 name="name">

     <br>

    :<input type=text size=20 name="value">

     <br>

    <input type=submit value="提交">

   </form>

</body>

</html>

2.      啓動tomcat7_a,啓動完畢後,啓動tomcat7_b

3.      進入http://localhost:8081/cluster/testCluster.jsp 對應tomcat7_a(8081),登錄幾次,可看到

 

4.      另外打開一個瀏覽器,進入http://localhost:8082/cluster/testCluster.jsp對應tomcat7_b(8082),登錄name:tomcat_bvalue:b value可看到

 

 

5.      刷新tomcat7_a(8081)相關頁面,可以看到從tomcat7_b提交的值session同步過來了,說明集羣成功。

 

 

 

第六章.        Session集羣工作步驟

參照tomcat7 doc:

To make it easy to understand how clustering works, We are gonna take you through a series of scenarios. In the scenario we only plan to use two tomcat instances TomcatA and TomcatB. We will cover the following sequence of events:

1.    TomcatA starts up

2.    TomcatB starts up (Wait that TomcatA start is complete)

3.    TomcatA receives a request, a session S1 is created.

4.    TomcatA crashes

5.    TomcatB receives a request for session S1

6.    TomcatA starts up

7.    TomcatA receives a request, invalidate is called on the session (S1)

8.    TomcatB receives a request, for a new session (S2)

9.    TomcatA The session S2 expires due to inactivity.

 

第七章.        負載均衡配置

Tomcat有兩種負載均衡的方式:

1.      使用 JK1.2.x native connector

2.      使用Apache HTTP Server 2.x with mod_proxy

我們使用的是mod_proxy,Apache Http Server2.2以上版本已經自動帶有:

Mod_proxy supports either HTTP or AJP load balancing. 我們通過ajp方式。

 

 

 

詳細查看:tomcat7/webapps/docs/balancer-howto.html

1.      首先,監聽8000端口, Apache安裝目錄下找到conf/httpd.conf文件

稍前面加上

# 監聽端口和監聽地址

Listen 8000

2.      conf/httpd.conf,去掉以下文本前的註釋符(#)以便讓Apache在啓動時自動加載代理(proxy)模塊。

LoadModule proxy_module modules/mod_proxy.so  

LoadModule proxy_ajp_module modules/mod_proxy_ajp.so  

LoadModule proxy_balancer_module modules/mod_proxy_balancer.so  

LoadModule proxy_connect_module modules/mod_proxy_connect.so  

LoadModule proxy_ftp_module modules/mod_proxy_ftp.so  

LoadModule proxy_http_module modules/mod_proxy_http.so 

 

3.      conf/httpd.conf文件最後加上:

#虛擬機配置,負載均衡配置

<VirtualHost *:8000>

       ServerAdmin [email protected]

       ServerName localhost

       ServerAlias localhost

       #小心,有些地方要有空格,要不然會出錯哈哈。

       ProxyPass / balancer://cluster/ stickysession=JSESSIONID|jsessionid nofailover=On

       ProxyPassReverse / balancer://cluster/

       #ErrorLog "logs/error.log"

       #CustomLog "logs/access.log" common

</VirtualHost>

 

#The ProxyRequests directive should usually be set off when using ProxyPass.

ProxyRequests Off

<proxy balancer://cluster>

       BalancerMember ajp://localhost:8009 loadfactor=1 route=tomcat7_a  smax=5 max=20 ttl=120 retry=300 timeout=15

       BalancerMember ajp://localhost:9009 loadfactor=1 route=tomcat7_b  smax=5 max=20 ttl=120 retry=300 timeout=15

       # status=+H爲配置熱備,當所有機器都over時,纔會請求該機器

       #BalancerMember http://192.168.1.218:8009 status=+H

       ProxySet lbmethod=bytraffic

</proxy>

4.      Tomcat7配置(server.xml):

因爲是同一機器,兩個應用,所以配不同的端口,不同機器則不用配,要和前面的ajp對應上。

<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

<Connector port="9009" protocol="AJP/1.3" redirectPort="8443" />

 

第八章.        負載均衡測試

Tomcat7_acluster工程的測試文件:testCluster.jsp加上html代碼:

<b>負載均衡測試:此爲:Tomcat7_a上的文件,<font color=red>aaaaaaaaaaaaaaaaaa</font><b>

 

Tomcat7_bcluster工程的測試文件:testCluster.jsp加上html代碼

<b>負載均衡測試:此爲:Tomcat7_b上的文件,<font color=red>bbbbbbbbbbbbbbbbbb</font><b>

 

打開瀏覽器,進入地址:http://localhost:8000/cluster/testCluster.jsp

多刷新幾次,會看到頁面值會在aaaaabbbbb間切換,說明負載均衡配置成功。如圖:

 

 

 

第九章.        Mod_proxy負載均衡算法

目前mod_proxy3種負載均衡算法:

1.       Request Counting(我猜是Round-robin), lbmethod=byrequests

2.       Weighted Traffic Counting(這個是按權重,此例也是用此算法), lbmethod=bytraffic

3.       Pending Request Counting(apche文檔來看,應該是按負載量,也就是往負載少的派發新請求). lbmethod=bybusyness

它們通過lbmethod值設置。

第十章.        參考文檔:

Tomcat 7 doc文檔

http://httpd.apache.org/docs/2.2/mod/mod_proxy_balancer.html

http://httpd.apache.org/docs/2.2/mod/mod_proxy.html

 

第十一章.        補充內容:負載均衡管理器

負載均衡管理器可以動態更新負載均衡的應用,你可以用管理器更改負載因子或者特定的應用,還可以把應用設爲off模式。

爲了使用balancer management, mod_statusmod_proxy_balancer 必需要加載到apache.

設置:

#此項爲mod_proxy_balancer管理器需要

LoadModule status_module modules/mod_status.so

 

在負載均衡項前加上:

#mod_balancer管理應用

<Location /balancer-manager>  

     SetHandler balancer-manager

     Order Allow,Deny

     Allow from all

</Location>

 

可以通過以下地址訪問:http://localhost:8000/balancer-manager

 

 

 

發佈了29 篇原創文章 · 獲贊 6 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章