CentOS-6.4-minimal版中Apache-2.2.29與Tomcat-6.0.41實現集群
來源:程序員人生 發布時間:2014-10-08 18:16:08 閱讀次數:3821次
/**
* CentOS-6.4-minimal版中Apache-2.2.29與Tomcat-6.0.41實現集群
* ----------------------------------------------------------------------------------------------------------------------
* 本文建立在Apache-2.2.29與Tomcat-6.0.41實現負載均衡的基礎上,實現過程詳見http://blog.csdn.net/jadyer/article/details/39617801
* ----------------------------------------------------------------------------------------------------------------------
* 幾個術語
* 1)負載均衡
* 前端服務器(常常名為"負載均衡器","代理均衡器"或"反向代理")收到HTTP請求后,將請求分發到后端的不止一個"worker"的web服務器,由它們實際處理請求
* 2)會話復制
* 會話復制(即常說的Session共享)是一種機制,將客戶端會話的整個狀態原原本本復制到集群中的兩個或多個服務器實例,以實現容錯和故障切換功能
* 3)集群
* 集群由兩個或多個Web服務器實例組成,這些服務器實例步調一致地工作,透明地處理客戶端請求,客戶端將一組服務器實例認為是單一實體服務
* ----------------------------------------------------------------------------------------------------------------------
* 幾個區別
* 1)集群有別于分布式的解決方案,它采用的是每臺服務器運行相同應用的策略,由負責均衡的服務器進行分流,這可以提高整個系統的并發量及吞吐量
* 2)由于集群服務需要在處理請求之間不斷地進行會話復制,復制后的會話將會慢慢變得龐大,因此它的資源占用率是非常高的
* 如果在并發量大的應用中,復制的會話大小會變得相當大,而使用的總內存更是會迅速升高
* 3)集群的會話復制,增加了系統的高可用性,由于在每臺服務器都保存有用戶的Session信息
* 如果服務器群中某臺宕機,應用可以自動切換到其它服務器上繼續運行,而用戶的信息不會丟失,這提高了應用的冗錯性
* 4)實踐證明,在各應用服務器之間不需要狀態復制的情況下,負載均衡可以達到性能的線性增長及更高的并發需求
* ----------------------------------------------------------------------------------------------------------------------
* 配置集群的Tomcat實例的名稱
* 這里jvmRoute屬性值要與workers.properties中設置的節點名相同,該值將做為后綴添加在每個由該結點生成的jsessionid后面
* 而mod_jk正是根據jsessionid后面的后綴來確定一個請求應由哪一個結點來處理,這也是實現session_sticky的基本保證
* [root@CentOS64 app]# vi /app/tomcat1/conf/server.xml (為<Engine/>節點增加jvmRoute屬性,屬性值為tomcat1)
* [root@CentOS64 app]# vi /app/tomcat2/conf/server.xml (為<Engine/>節點增加jvmRoute屬性,屬性值為tomcat2)
* [root@CentOS64 app]# vi /app/tomcat3/conf/server.xml (為<Engine/>節點增加jvmRoute屬性,屬性值為tomcat3)
* ----------------------------------------------------------------------------------------------------------------------
* 配置集群參數
* 0)如果tomcat是放在不同機器上面的
* 那么直接取消注釋tomcat/conf/server.xml中的<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>即可
* 1)如果tomcat是放在同一機器上面的(參考http://tomcat.apache.org/tomcat-6.0-doc/cluster-howto.html)
* 此時就要修改<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"
* 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>
* 我們要做的就是顯式添加此默認配置,并修改上面的Receiver port,由于我們這里有三個tomcat節點,故這個端口就依次修改為4001,4002,4003
* 之所以沒有修改為4100,4200,4300,是由于Tomcat官方建議此端口范圍在4000~4100之間
* ----------------------------------------------------------------------------------------------------------------------
* 應用程序為集群做的準備
* 1)Session中存放的數據必須實現序列化
* 2)在應用程序的web.xml中加入<distributable/>元素
* ----------------------------------------------------------------------------------------------------------------------
* 測試集群
* 啟動apache和3個tomcat后,測試方法如下(測試代碼已在下方列出)
* 1)訪問測試頁面,會看到頁面打印SessionID后面多出了".tomcat2",這就是上文說到的jsessionid后面會加上.jvmRoute為后綴,表明tomcat2在處理此請求
* 2)刷新測試頁面,會看到打印的SessionID沒有變化(與負載均衡后的效果有明顯不同,詳見http://blog.csdn.net/jadyer/article/details/39617801)
* 3)添加新的屬性,提交表單后會發現打印出了新添加的屬性名和屬性值,接著刷新頁面會發現添加的屬性依然存在
* 4)最關鍵的一步,關閉tomcat2服務器,再刷新頁面,會發現請求交由"tomcat1"來處理了,并且之前添加的屬性依然存在..至此,Session共享成功,集群成功
* ----------------------------------------------------------------------------------------------------------------------
* 注意事項
* 1)java.net.BindException: Cannot assign requested address; No faulty members identified
* 啟動tomcat時報告上面的異常,猜測可能是由于tomcat安裝在我的虛擬機中,該屬性導致其與我的主機(Thinkpad筆記本)的IP產生沖突
* 此時修改[address="auto"]中auto為192.168.0.103(即tomcat服務器的IP)即可..如果還報這個異常,可以試一下127.0.0.1
* 2)如果仍然啟動失敗,或者啟動成功,但無法實現session共享,那么有可能是組播出現了問題
* 因為tomcat中的集群原理是通過組播的方式進行節點的查找并使用TCP連接進行會話的復制的,即tomcat的session同步功能需要用到組播服務
* 可以通過[route add -net 224.0.0.0 netmask 240.0.0.0 dev eth0]命令開通Linux組播服務
* 如果需要服務器啟動時即開通組播,則需/etc/sysconfig/static-routes文件中加入[eht0 net 224.0.0.0 netmask 240.0.0.0]
* 另外,可以通過[netstat -g]或者[route -e]命令來查看組播狀態
* ----------------------------------------------------------------------------------------------------------------------
* @create Sep 27, 2014 7:59:32 PM
* @author 玄玉<http://blog.csdn.net/jadyer>
*/
<%@ page language="java" pageEncoding="UTF-8"%>
<%
out.println("<br>Session ID : " + session.getId() + "<br>");
session.setAttribute("myname", "session");
String dataName = request.getParameter("dataName");
if(null!=dataName && dataName.length()>0){
String dataValue = request.getParameter("dataValue");
session.setAttribute(dataName, dataValue);
}
out.print("<b>Session 列表</b><br>");
java.util.Enumeration e = session.getAttributeNames();
while(e.hasMoreElements()){
String name = (String)e.nextElement();
String value = session.getAttribute(name).toString();
out.println( name + " = " + value+"<br>");
}
%>
<form action="demo.jsp" method="POST">
屬性名:<input type=text size=20 name="dataName"><br>
屬性值:<input type=text size=20 name="dataValue"><br>
<input type=submit>
</form>
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈