apache+tomcat集羣配置

基礎知識

       先學習下Apache和Tomcat的區別及Web服務器,容器和應用服務器區別

tomcat最主要的功能是提供Servlet/JSP容器,儘管它也可以作爲獨立的Java Web服務器,它在對靜態資源(如HTML文件或圖像文件)的處理速度,以及提供的Web服務器管理功能方面都不如其他專業的HTTP服務器,如IIS、Apache、nginx等web服務器。

  •        因此在實際應用中,常常把Tomcat與其他HTTP服務器集成。對於不支持Servlet/JSP的web服務器,可以通過Tomcat服務器來運行Servlet/JSP組件。
  •        當Tomcat與其他web服務器集成時,Tomcat服務器的工作模式通常爲進程外的Servlet容器,Tomcat服務器與其他HTTP服務器之間通過專門的插件來通信。

Tomcat與HTTP服務器集成的原理Tomcat服務器通過Connector連接器組件與客戶程序建立連接,Connector組件負責接收客戶的請求,以及把Tomcat服務器的響應結果發送給客戶。默認情況下,Tomcat在server.xml中配置了兩種連接器:

<!-- A "Connector" represents an endpoint by which requests are received
         and responses are returned. Documentation at :
         Java HTTP Connector: /docs/config/http.html (blocking & non-blocking)
         Java AJP  Connector: /docs/config/ajp.html
         APR (HTTP/AJP) Connector: /docs/apr.html
         Define a non-SSL HTTP/1.1 Connector on port 8080
    -->
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443"
               URIEncoding="UTF-8"    
               useBodyEncodingForURI="true"/>
<!-- Define an AJP 1.3 Connector on port 8009 -->
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /><span style="font-family: Arial; background-color: rgb(255, 255, 255);">      </span>

    • 第一個連接器監聽8080端口,負責建立HTTP連接。在通過瀏覽器訪問Tomcat服務器的Web應用時,使用的就是這個連接器。
      第二個連接器監聽8009端口,負責和其他的HTTP服務器建立連接。在把Tomcat與其他HTTP服務器集成時,就需要用到這個連接器。
      Web客戶訪問Tomcat服務器上JSP組件的兩種方式如圖下圖所示:

  • 圖1

  • 圖1

Web客戶1直接訪問Tomcat服務器上的JSP組件,他訪問的URL爲http://localhost:8080 /index.jsp。
Web客戶2通過HTTP服務器(apache、iis、nginx等)訪問Tomcat服務器上的JSP組件。假定web服務器使用的HTTP端口爲默認的80端口,那麼Web客戶2訪問的URL爲http://localhost:80/index.jsp 或者 http://localhost/index.jsp。

Tomcat與web服務器之間通信

1、JK插件

Tomcat提供了專門的JK插件來負責Tomcat和web服務器的通信。應該把JK插件安置在對方的web服務器上。當web服務器接收到客戶請求時,它會通過JK插件來過濾URL,JK插件根據預先配置好的URL映射信息,決定是否要把客戶請求轉發給Tomcat服務器處理。(有點類似一個攔截器,將*.jsp的請求都交給tomcat處理,讓後將tomcat返回的結果再放回給客戶  
  假定在預先配置好的URL映射信息中,所有"/*.jsp"形式的URL都由Tomcat服務器來處理,那麼在圖1的例子中,客戶2訪問服務器時,web服務器中的JK插件將把客戶請求轉發給Tomcat服務器,Tomcat服務器於是運行index.jsp,然後把響應結果傳給web服務器,web服務器再把響應結果傳給Web 客戶2。  
  對於不同的web服務器,Tomcat提供了不同的JK插件的實現模塊。本章將用到以下JK插件:  
  與Windows下的Apache HTTP服務器集成:mod_jk_2.0.46.dll  
  與Linux(RedHet)下的Apache HTTP服務器集成:mod_jk.so-ap2.0.46-rh72..46-rh72  
  與IIS服務器集成:isapi_redirect.dll

2、AJP協議

  AJP是爲Tomcat與web服務器之間通信而定製的協議,能提供較高的通信速度和效率。在配置Tomcat與web服務器集成中,讀者可以不必關心AJP協議的細節。關於AJP的知識也可以參考網址:  
  http://jakarta.apache.org/builds/jakarta-tomcat-connectors/jk2/doc/common/AJPv13.html


Session共享

對於WEB應用集羣的技術實現而言,最大的難點就是如何能在集羣中的多個節點之間保持數據的一致性,會話(Session)信息是這些數據中最重要的一塊。要實現這一點,大體上有兩種方式,一種是把所有Session數據放到一臺服務器上或者數據庫中,集羣中的所有節點通過訪問這臺Session服務器來獲取數據;另一種就是在集羣中的所有節點間進行Session數據的同步拷貝,任何一個節點均保存了所有的Session數據。兩種方式都各有優點,第一種方式簡單、易於實現,但是存在着Session服務器發生故障會導致全系統不能正常工作的風險;第二種方式可靠性更高,任一節點的故障不會對整個系統對客戶訪問的響應產生影響,但是技術實現上更復雜一些。常見的平臺或中間件如microsoft asp.net和IBM WAS都會提供對兩種共享方式的支持,tomcat也是這樣,但是一般採用第二種方式。 

當採用tomcat默認集羣配置(<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>)時,配置的細節實際上被省略了,對於大多數應用而言,使用默認配置已經足夠。完整的默認配置應該是這樣:


 <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> 


tomcat集羣各節點通過建立tcp鏈接來完成Session的拷貝,拷貝有同步和異步兩種模式。在同步模式下,對客戶端的響應必須在Session拷貝到其他節點完成後進行;異步模式無需等待Session拷貝完成就可響應。異步模式更高效,但是同步模式可靠性更高。同步異步模式由channelSendOptions參數控制,默認值是8,爲異步模式,4是同步模式。在異步模式下,可以通過加上拷貝確認(Acknowledge)來提高可靠性,此時channelSendOptions設爲10。

 

Manager用來在節點間拷貝Session,默認使用DeltaManager,DeltaManager採用的一種all-to-all的工作方式,即集羣中的節點會把Session數據向所有其他節點拷貝,而不管其他節點是否部署了當前應用。當集羣中的節點數量很多並且部署着不同應用時,可以使用BackupManager,BackManager僅向部署了當前應用的節點拷貝Session。但是到目前爲止BackupManager並未經過大規模測試,可靠性不及DeltaManager。 


Channel負責對tomcat集羣的IO層進行配置。Membership用於發現集羣中的其他節點,這裏的address用的是組播地址(Multicast address,瞭解更多組播地址詳情請參見http://zyycaesar.iteye.com/admin/blogs/296501),使用同一個組播地址和端口的多個節點同屬一個子集羣,因此通過自定義組播地址和端口就可將一個大的tomcat集羣分成多個子集羣。Receiver用於各個節點接收其他節點發送的數據,在默認配置下tomcat會從4000-4100間依次選取一個可用的端口進行接收,自定義配置時,如果多個tomcat節點在一臺物理服務器上注意要使用不同的端口。Sender用於向其他節點發送數據,具體實現通過Transport配置,PooledParallelSender是從tcp連接池中獲取連接,可以實現並行發送,即集羣中的多個節點可以同時向其他所有節點發送數據而互不影響。Interceptor有點類似下面將要解釋的Valve,起到一個閥門的作用,在數據到達目的節點前進行檢測或其他操作,如TcpFailureDetector用於檢測在數據的傳輸過程中是否發生了tcp錯誤。關於Channel的編程模型,請參見http://tomcat.apache.org/tomcat-6.0-doc/api/org/apache/catalina/tribes/Channel.html 


Valve用於在節點向客戶端響應前進行檢測或進行某些操作,ReplicationValve就是用於用於檢測當前的響應是否涉及Session數據的更新,如果是則啓動Session拷貝操作,filter用於過濾請求,如客戶端對圖片,css,js的請求就不會涉及Session,因此不需檢測,默認狀態下不進行過濾,監測所有的響應。JvmRouteBinderValve會在前端的Apache mod_jk發生錯誤時保證同一客戶端的請求發送到集羣的同一個節點,tomcat官方文檔並未解釋如何實現這一點,而且筆者認爲這一設置似乎並無多大實用性。 

Deployer用於集羣的farm功能,監控應用中文件的更新,以保證集羣中所有節點應用的一致性,如某個用戶上傳文件到集羣中某個節點的應用程序目錄下,Deployer會監測到這一操作並把這一文件拷貝到集羣中其他節點相同應用的對應目錄下以保持所有應用的一致。這是一個相當強大的功能,不過很遺憾,tomcat集羣目前並不能做到這一點,開發人員正在努力實現它,這裏的配置只是預留了一個接口。 

Listener用於跟蹤集羣中節點發出和收到的數據,也有點類似Valve的功能。 


在大體瞭解了tomcat集羣實現模型後,就可以對集羣作出更優化的配置了,tomcat推薦了一套配置,使用了比DeltaManager更高效的BackupManager,並且對ReplicationValve設置了請求過濾,注意在一臺服務器部署多個節點時需要修改Receiver的偵聽端口,另外,爲了更高效的在節點間拷貝數據,所有tomcat節點最好採用相同的配置,具體配置如下:

 

     <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"   channelSendOptions="6">
          <Manager className="org.apache.catalina.ha.session.BackupManager"   expireSessionsOnShutdown="false"   notifyListenersOnReplication="true"    mapSendOptions="6"/>

          <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="5000"     selectorTimeout="100"      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"/>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.ThroughputInterceptor"/>
          </Channel>
          <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"   filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;"/>
          <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.ClusterSessionListener"/>
    </Cluster>

    

Tomcat集羣除了可以進行Session數據的拷貝,還可進行Context屬性的拷貝,通過修改context.xml的Context配置可以實現,使用<Context className="org.apache.catalina.ha.context.ReplicatedContext"/>替換默認Context即可,當然也可再加上distributable="true"屬性。


總結


1、只實際動手實現了DeltaManager控制的Session共享,在實際配置時多看看tomcat的document,其實上面的大多數都是根據tomcat的document來配置的。
2、在使用開源軟件時多看官方的文檔。(\tomcat7\webapps\docs\config)


參考資料:

1、http://www.iteye.com/topic/1017961/ (實際配置)

2、http://blog.csdn.net/huzia/article/details/19193445 (相關理論)

3、http://zyycaesar.iteye.com/blog/296606 (session共享)



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章