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

分類  >  Apache >
tags:    時間:2013-12-25 17:59:57
基於mod_proxy+Apache 2.2.16+Tomcat 七的負載均衡與集群配置簡介
基於mod_proxy+Apache 2.2.16+Tomcat 7的負載均衡與集群配置 基於mod_proxy+Apache 2.2.16+Tomcat 7的負載均衡與集群配置 Peter……
基於mod_proxy+Apache 2.2.16+Tomcat 七的負載均衡與集群配置正文
    基於mod_proxy+Apache 2.2.16+Tomcat 7的負載均衡與集群配置
    基於mod_proxy+Apache 2.2.16+Tomcat 7的負載均衡與集群配置
    Peter Wei



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

    第一章. 背景簡介
    對於大多數企業應用,都希望能做到7*24小時不間斷運行。要保持如此高的可用性並非易事,比較常見的做法是將系統部署到多台機器上,每台機器都對外提供同樣的功能,這就是集群。系統變為集群時,除了要求系統能夠支持水平伸縮外,還要解決兩個問題:
    1, 如何均衡地訪問到提供業務功能的機器。
    2, 如何保證當機器出現問題時,用戶能自動跳轉到另外的機器,不影響使用。

    常用的負載均衡技術有硬體和軟體兩種,本示例常用軟體的技術實現。軟體也有很多實現技術,如基於apache的mod_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" /> 參照四
    • 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>節點下添加:

    Java代碼
    1. <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"  
    2.                  channelSendOptions="8">   
    3.   
    4.           <Manager className="org.apache.catalina.ha.session.DeltaManager"  
    5.                    expireSessionsOnShutdown="false"  
    6.                    notifyListenersOnReplication="true"/>   
    7.   
    8.           <Channel className="org.apache.catalina.tribes.group.GroupChannel">   
    9.             <Membership className="org.apache.catalina.tribes.membership.McastService"  
    10.                         address="228.0.0.4"  
    11.                         port="45564"  
    12.                         frequency="500"  
    13.                         dropTime="3000"/>   
    14.             <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"  
    15.                       address="auto"  
    16. <!—tcpListenPort如果是同一機器部署兩個tomcat7應用,則修改tomcat7_b為4001,以免衝突. 不同機器下,不用更改此項。—>   
    17.                       [color=red]port="4000"[/color]   
    18.                       autoBind="100"  
    19.                       selectorTimeout="5000"  
    20.                       maxThreads="6"/>   
    21.   
    22.             <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">   
    23.               <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>   
    24.             </Sender>   
    25.             <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>   
    26.             <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>   
    27.           </Channel>   
    28.   
    29.           <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"  
    30.                  filter=""/>   
    31.           <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>   
    32.   
    33.           <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"  
    34.                     tempDir="/tmp/war-temp/"  
    35.                     deployDir="/tmp/war-deploy/"  
    36.                     watchDir="/tmp/war-listen/"  
    37.                     watchEnabled="false"/>   
    38.   
    39.           <ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>   
    40.           <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>   
    41.         </Cluster>  
    <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_b為4001,以免衝突. 不同機器下,不用更改此項。—>                       [color=red]port="4000"[/color]                       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_a和tomcat7_b的cluster工程中分別添加測試文件:testCluster.jsp

    Java代碼
    1. <%@ page contentType="text/html; charset=GBK" %>   
    2. <%@ page import="java.util.*" %>   
    3. <html><head><title>Cluster Test</title></head>   
    4. <body>   
    5. <%   
    6.   //HttpSession session = request.getSession(true);   
    7.   System.out.println(session.getId());   
    8.   out.println("<br> SESSION ID:" + session.getId()+"<br>");     
    9.   // 如果有新的請求,則添加session屬性   
    10.   String name = request.getParameter("name");   
    11.   if (name != null && name.length() > 0) {   
    12.      String value = request.getParameter("value");   
    13.      session.setAttribute(name, value);   
    14.   }     
    15.     out.print("<b>Session List:</b>");     
    16.     Enumeration<String> names = session.getAttributeNames();   
    17.     while (names.hasMoreElements()) {   
    18.         String sname = names.nextElement();    
    19.         String value = session.getAttribute(sname).toString();   
    20.         out.println( sname + " = " + value+"<br>");   
    21.         System.out.println( sname + " = " + value);   
    22.    }   
    23. %>   
    24.   <form action="testCluster.jsp" method="post">   
    25.     名稱:<input type=text size=20 name="name">   
    26.      <br>   
    27.     值:<input type=text size=20 name="value">   
    28.      <br>   
    29.     <input type=submit value="提交">   
    30.    </form>   
    31. </body>   
    32. </html>  
    <%@ 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_b,value: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文件
    稍前面加上

    Java代碼
    1. # 監聽埠和監聽地址   
    2. Listen 8000  
    # 監聽埠和監聽地址 Listen 8000


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

    Java代碼
    1. LoadModule proxy_module modules/mod_proxy.so     
    2. LoadModule proxy_ajp_module modules/mod_proxy_ajp.so     
    3. LoadModule proxy_balancer_module modules/mod_proxy_balancer.so     
    4. LoadModule proxy_connect_module modules/mod_proxy_connect.so     
    5. LoadModule proxy_ftp_module modules/mod_proxy_ftp.so     
    6. LoadModule proxy_http_module modules/mod_proxy_http.so   
    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文件最後加上:

    Java代碼
    1. #虛擬機配置,負載均衡配置   
    2. <VirtualHost *:8000>   
    3.     ServerAdmin weigbo@163.com   
    4.     ServerName localhost   
    5.     ServerAlias localhost   
    6.     #小心,有些地方要有空格,要不然會出錯哈哈。   
    7.     ProxyPass / balancer://cluster/ stickysession=JSESSIONID|jsessionid nofailover=On   
    8.     ProxyPassReverse / balancer://cluster/   
    9.     #ErrorLog "logs/error.log"  
    10.     #CustomLog "logs/access.log" common   
    11. </VirtualHost>    
    12.   
    13. #The ProxyRequests directive should usually be set off when using ProxyPass.   
    14. ProxyRequests Off   
    15. <proxy balancer://cluster>   
    16.     BalancerMember ajp://localhost:8009 loadfactor=1 route=tomcat7_a  smax=5 max=20 ttl=120 retry=300 timeout=15   
    17.     BalancerMember ajp://localhost:9009 loadfactor=1 route=tomcat7_b  smax=5 max=20 ttl=120 retry=300 timeout=15   
    18.     # status=+H為配置熱備,當所有機器都over時,才會請求該機器   
    19.     #BalancerMember http://192.168.1.218:8009 status=+H   
    20.     ProxySet lbmethod=bytraffic   
    21. </proxy>  
    #虛擬機配置,負載均衡配置 <VirtualHost *:8000> 	ServerAdmin weigbo@163.com 	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_a的cluster工程的測試文件:testCluster.jsp加上html代碼:
    <b>負載均衡測試:此為:Tomcat7_a上的文件,<font color=red>aaaaaaaaaaaaaaaaaa</font><b>

    Tomcat7_b的cluster工程的測試文件:testCluster.jsp加上html代碼
    <b>負載均衡測試:此為:Tomcat7_b上的文件,<font color=red>bbbbbbbbbbbbbbbbbb</font><b>

    打開瀏覽器,進入地址:http://localhost:8000/cluster/testCluster.jsp
    多刷新幾次,會看到頁面值會在aaaaa和bbbbb間切換,說明負載均衡配置成功。如圖:








    第九章. Mod_proxy負載均衡演算法
    目前mod_proxy有3種負載均衡演算法:
    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_status和mod_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




    附件中是一些相關的配置文件,大家可以參考:

    Bookmark the permalink ,來源:互聯網
    One thought on “基於mod_proxy+Apache 2.2.16+Tomcat 七的負載均衡與集群配置