應用的開發 首先,我須要開發一個web應用,來測試個人集羣,因而,我建立了一個動態web項目,取名叫sessiontest. 在此項目中,只有兩個jsp文件。 第一個select.jsp. 這個文件至關於一個購物車,將用戶選中的內容提交,並展現用戶選中的物品。 01 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> 02 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 03 <html> 04 <head> 05 <title>Your selections</title> 06 </head> 07 <body> 08 <% 09 String selections = (String)session.getAttribute("selections"); 10 selections=selections==null?"":selections; 11 %> 12 <form action="successful.jsp" method="post"> 13 <p>What do you prefer?</p> 14 <p><input type="checkbox" name="car" value="car" <% 15 if(selections.indexOf("car")>-1) out.print("checked=\"checked\""); %> />Car</p> 16 <p><input type="checkbox" name="bike" value="bike" <% 17 if(selections.indexOf("bike")>-1) out.print("checked=\"checked\""); %> />Bike</p> 18 <p><input type="checkbox" name="train" value="train" <% 19 if(selections.indexOf("train")>-1) out.print("checked=\"checked\""); %> />Train</p> 20 <p><input type="checkbox" name="plane" value="plane" <% 21 if(selections.indexOf("plane")>-1) out.print("checked=\"checked\""); %> />Plane</p> 22 <input type="submit" value="Submit" /> 23 </form> 24 </body> 25 </html> 第二個文件是successful.jsp, 它將select.jsp提交的選項包存入session中。 01 <%@ page language="java" contentType="text/html; charset=UTF-8" 02 pageEncoding="UTF-8"%> 03 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 04 <html> 05 <head> 06 <title>Successful</title> 07 </head> 08 <body> 09 <% 10 StringBuffer sb = new StringBuffer(); 11 if (null !=request.getParameter("car"))sb.append("car;"); 12 if (null !=request.getParameter("bike"))sb.append("bike;"); 13 if (null !=request.getParameter("train"))sb.append("train;"); 14 if (null !=request.getParameter("plane"))sb.append("plane;"); 15 16 session.setAttribute("selections", sb.toString()); 17 %> 18 Successful, please go back to check.<br> 19 <a href="select.jsp">Back</a> 20 </body> 21 </html> 將項目導出爲sessiontest.war,並部署到tomcat中的用戶界面爲: http://localhost:8080/sessiontest/select.jsp http://localhost:8080/sessiontest/successful.jsp 接下來,我會使用這個web應用來測試個人集羣。 最簡單的集羣 以下圖所示,最簡單的集羣並非一個真正的集羣,tomcat1和tomcat2只是運行了同一個應用,好比個人sessiontest.war, 它們兩個之間並無任何通訊,共享。Apache只是根據訪問量進行負載平衡。一旦其中一個tomcat關機,全部的request都將被轉發到另外一個tomcat上去。而以前工做在第一個tomcat上的用戶會丟失信息,好比session,運行環境。 首先在本機上安裝兩個tomcat, 也就是生成2分tomcat的copy。下面將這兩個tomcat分別以tomcat1和tomcat2命名。 維持tomcat1的port的配置,但須要向其server.xml中添加一個屬性 jvmRoute="node1": 1 <Engine name="Catalina" defaultHost="localhost" jvmRoute="node1"> 修改tomcat2的port的配置,並向其server.xml中添加一個屬性 jvmRoute="node2": 1 <Server port="8006" shutdown="SHUTDOWN"> 2 <Connector port="8081" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443"/> 3 <Connector port="8010" protocol="AJP/1.3" redirectPort="8443" /> 4 <Engine name="Catalina" defaultHost="localhost" jvmRoute="node2"> 將以前的應用sessiontest.war分別部署到兩個tomcat上。測試localhost:8080/sessiontest/select.jsp和localhost:8081/sessiontest/select.jsp。這樣,集羣的兩個node就跑起來了。 配置apache httpd,開啓負載平衡。基於上一篇文章配好的 的網站,我將把集羣掛在這個網站下面,將下面的配置加入virtualhost中。不要忘記開啓proxy_balancer module。 01 <VirtualHost *:443> 02 ServerName 03 ProxyPass /sessiontest balancer://mycluster 04 <Proxy balancer://mycluster> 05 BalancerMember ajp://127.0.0.1:8009/sessiontest loadfactor=1 route=node1 06 BalancerMember ajp://127.0.0.1:8010/sessiontest loadfactor=1 route=node2 07 ProxySet stickysession=JSESSIONID 08 ProxySet lbmethod=byrequests 09 </Proxy> 10 </VirtualHost> stickysession的意義在於,一個用戶能夠根據其cookie中的jsessionid固定的訪問一個tomcat,這樣不會在兩個tomcat之間跳來跳去而丟失運行信息和session。 開啓集羣節點之間的通訊 接下來,我將開啓tomcat1和tomcat2之間的通訊,這樣它們能夠共享session和一些內存信息。一個正在tomcat1上訪問的用戶,由於tomcat1的關機而轉移到tomcat2上,也不會丟失session信息了。 修改原web應用,在sessiontest的web.xml中添加一段。代表此應用須要在cluster之間進行同步。而後從新部署此應用。 1 <distributable/> 分別修改tomcat1和tomcat2的server.xml,加入相同的一段代碼。 Tomcat使用組播技術,使得各個node之間創建鏈接,惟一須要聲明的是你的Recervier端口,在4000-4999之間任選一個。 01 <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" 02 channelSendOptions="8"> 03 04 <Manager className="org.apache.catalina.ha.session.DeltaManager" 05 expireSessionsOnShutdown="false" 06 notifyListenersOnReplication="true"/> 07 08 <Channel className="org.apache.catalina.tribes.group.GroupChannel"> 09 <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 port="4444" 17 autoBind="100" 18 selectorTimeout="5000" 19 maxThreads="6"/> 20 21 <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter"> 22 <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/> 23 </Sender> 24 <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/> 25 <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/> 26 </Channel> 27 28 <Valve className="org.apache.catalina.ha.tcp.ReplicationValve" 29 filter=""/> 30 <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/> 31 32 <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer" 33 tempDir="/tmp/war-temp/" 34 deployDir="/tmp/war-deploy/" 35 watchDir="/tmp/war-listen/" 36 watchEnabled="false"/> 37 38 <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/> 39 </Cluster> 分別啓動tomcat1和tomcat2.請等一個啓動完再啓動另外一個。集羣建立完畢。 爲了測驗集羣,我將負載平衡的stickysession關掉。請註釋掉配置中的ProxySet stickysession=JSESSIONID. 重啓apache. 這時候用戶的request會在tomcat1和tomcat2之間跳來跳去。 訪問 你會發現即便request在兩個tomcat之間跳來跳去,但購物車裏的信息永遠不會丟失。