在 Apache HTTP Server 2.2.21 和 Tomcat 7.0.23 上使用 mod_proxy_ajp 進行負載平衡和集群
我一直在努力使用這些組合使負載平衡和集群工作:
- Apache HTTP Server 2.2.21 (httpd-2.2.21-win32-x86-openssl-0.9.8r) 使用 mod_proxy_ajp 並啟用粘性會話。
- Apache Tomcat 7.0.23 (apache-tomcat-7.0.23-windows-x64)
- JDK 7 更新 2 (jdk-7u2-windows-x64)
- 視窗 7 64 位
- 春天 3.1
我讀過的一些連結:
這是我的配置:
httpd.conf
# Required Modules 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 status_module modules/mod_status.so # Reverse Proxy <Proxy balancer://mybalancer> BalancerMember ajp://localhost:8301 route=s1 BalancerMember ajp://localhost:8302 route=s2 BalancerMember ajp://localhost:8303 route=s3 </Proxy> ProxyPass / balancer://mybalancer/ stickysession=JSESSIONID|jsessionid # Forward Proxy ProxyRequests Off <Proxy *> Order deny,allow Deny from none Allow from localhost </Proxy> # Balancer-manager, for monitoring <Location /balancer-manager> SetHandler balancer-manager Order deny,allow Deny from none Allow from localhost </Location>
每個 tomcat 的 server.xml(僅埠號不同)
<Server port="8001" shutdown="SHUTDOWN"> <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" /> <Listener className="org.apache.catalina.core.JasperListener" /> <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" /> <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" /> <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" /> <GlobalNamingResources> <Resource name="UserDatabase" auth="Container" type="org.apache.catalina.UserDatabase" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" pathname="conf/tomcat-users.xml" /> </GlobalNamingResources> <Service name="Catalina"> <Connector port="8101" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8201" /> <Connector port="8301" protocol="AJP/1.3" redirectPort="8201" /> <Engine name="Catalina" defaultHost="localhost" jvmRoute="s1"> <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" /> <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter"> <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender" /> </Sender> <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="auto" port="4000" autoBind="100" selectorTimeout="5000" maxThreads="6" /> <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" /> <ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener" /> <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener" /> </Cluster> <Realm className="org.apache.catalina.realm.LockOutRealm"> <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase" /> </Realm> <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log." suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> </Host> </Engine> </Service> </Server>
埠編號(如果部署在同一伺服器中,請確保沒有實例使用相同的埠)
- 80 -> Apache HTTP 伺服器埠
- 80xx -> Tomcat 伺服器關閉埠
- 81xx -> Tomcat 連接器埠 (HTTP)
- 82xx -> Tomcat SSL 重定向埠
- 83xx -> Tomcat AJP 埠
- 40xx -> NioReceiver 的 Tomcat tcp 接收埠
彈簧控制器
@Controller @RequestMapping("/login") public class LoginController { @RequestMapping(method=RequestMethod.GET) public String show(@ModelAttribute("user") User user, HttpServletRequest request) { user.setUsername("YUSUF"); HttpSession session = request.getSession(); Integer tambah = (Integer) session.getAttribute("tambah"); if(tambah == null) tambah = new Integer(1); else tambah = new Integer(tambah.intValue() + 1); session.setAttribute("tambah", tambah); return "login"; } }
登錄.jsp
<div class="mainFooter"> Tambah = ${sessionScope.tambah} <br> ID = ${pageContext.session.id} </div>
到目前為止,負載平衡部分正在工作,但會話複製卻沒有。
基本上我想要的是,如果我在登錄頁面上繼續按刷新,變數“tambah”將增加並保留在會話中。並且如果目前tomcat節點宕機了,session會被複製到下一個tomcat節點,數據不會走。但這就是正在發生的事情:
登錄螢幕:
Tambah = 39 ID = C1D59C8CA5D10EB98C1DE08AC618204D.s1
我把 tomcat1 取下來,讓 tomcat2 和 tomcat3 繼續執行,這裡是登錄螢幕:
Tambah = 1 ID = A83KJFO38FK30FJDL40FLREI39FKDKGD.s2
似乎故障轉移不起作用,會話沒有被複製,並且應用程序創建了一個新會話。有人可以幫我指出正確的方向嗎?
謝謝
編輯:感謝@Shane Madden,我已經解決了這個問題,這是我所做的更改:
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="auto" port="4000" autoBind="100" selectorTimeout="5000" maxThreads="6" />
對於每個 Tomcat,tcp 接收埠必須不同(如果執行在同一台伺服器上),例如使用 4001、4002、4003 等。
感謝@Shane Madden 的評論,我重新閱讀了http://tomcat.apache.org/tomcat-7.0-doc/cluster-howto.html中的 tomcat 集群文件,尤其是在這部分 ->“如果您的 Tomcat 實例是在同一台機器上執行,確保每個實例的 tcpListenPort 屬性是唯一的,在大多數情況下,Tomcat 足夠聰明,可以通過自動檢測 4000-4100 範圍內的可用埠來自行解決這個問題。
我所做的更改是在每個 Tomcat 實例的 server.xml 中,我確保每個埠都不同(例如 4001、4002、4003):
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="auto" port="4001" autoBind="100" selectorTimeout="5000" maxThreads="6" />
瞧!負載平衡和集群正在工作(當然是最基本的配置)。我希望這篇文章可以幫助其他人進行初始設置。