Apache-2.2

在 Apache HTTP Server 2.2.21 和 Tomcat 7.0.23 上使用 mod_proxy_ajp 進行負載平衡和集群

  • June 16, 2016

我一直在努力使用這些組合使負載平衡和集群工作:

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

瞧!負載平衡和集群正在工作(當然是最基本的配置)。我希望這篇文章可以幫助其他人進行初始設置。

引用自:https://serverfault.com/questions/344884