<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
channelSendOptions="6">
<Manager className="org.apache.catalina.ha.session.BackupManager"
expireSessionsOnShutdown="false"
notifyListenersOnReplication="true"
mapSendOptions="6"/>
<!--
<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="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|.*\.jpeg|.*\.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>
下面來仔細剖析一下這段代碼。
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"channelSendOptions="6">
Cluster 是主要元素,可在該元素內配置所有的集群相關細節。 對于 SimpleTcpCluster 類或者調用 SimpleTcpCluster.send 方法的對象,它們所發出的每一個消息上都附加著一個 channelSendOptions 標志。關于發送標志的描述可參見我們的 javadoc 文檔。DeltaManager 使用 SimpleTcpCluster.send 方法發送信息,而備份管理器則直接通過 channel 來發送自身。
<Manager className="org.apache.catalina.ha.session.BackupManager"
expireSessionsOnShutdown="false"
notifyListenersOnReplication="true"
mapSendOptions="6"/>
<!--
<Manager className="org.apache.catalina.ha.session.DeltaManager"
expireSessionsOnShutdown="false"
notifyListenersOnReplication="true"/>
-->
如果在 元素中沒有定義 manager,則以上可當做 manager 的配置模板。在 Tomcat 5.x 時期,每個標識為可分發(distributable)的 Web 應用都必須使用同樣的 manager,而如今不同了,我們可以為每個應用定義一個 manager 類,從而在集群中混合多個 manager。顯然,A 節點上的某個應用的所有 manager 必須與 B 節點上的同樣應用的 manager 相同。如果沒有為應用指定 manager,而且該應用被標識為 ,Tomcat 就會采取這種 manager 配置,創建一個克隆該配置的 manager 實例。
Channel 元素是 Tribes 架構的一個重要組成部分,Tribes 是 Tomcat 內部所使用的分組通信架構。Channel 元素封裝了所有通信相關事項以及成員邏輯。
<Membership className="org.apache.catalina.tribes.membership.McastService"
address="228.0.0.4"
port="45564"
frequency="500"
dropTime="3000"/>
成員關系(Membership)是通過組播來實現的。注意,如果你想將成員擴展到組播范圍之外的某個點時,Tribes 現在已經能夠支持使用 StaticMembershipInterceptor 的靜態成員。address 屬性是所用的組播地址,port 是所用的組播端口號。這兩項組合起來將集群隔離開。如果你希望一個 QA 集群和一個生產集群,最簡單的方法就是將 QA 集群的組播地址和端口號不同于生產集群的組播地址和端口號組合。
成員組件將其自身的 TCP 地址和端口廣播到其他節點處,從而使節點間的通信都可以通過 TCP 協議來完成。請注意被廣播的 TCP 地址正是 Receiver.address 屬性值。
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver
"address="auto"port="5000"selectorTimeout="100"maxThreads="6"/>
在 Tribes 架構中,數據的發送與接收以及被拆分為兩種功能性組件了。正如其名所示,Receiver 負責接收信息。由于 Tribes 與線程無關(其他架構也開始采用這一種常見改進了),該組件內部包含一個線程池,設定有 maxThreads 和 minThreads 兩種參數。
address 參數值是主機地址,由成員組件廣播到其他節點中。
<Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
<Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
</Sender>
Sender 組件負責將消息發送給其他節點。Sender 含有一個 shell 組件 ReplicationTransmitter,但真正所要完成的任務則是通過子組件 Transport 來完成的。由于 Tribes 支持一個 Sender 池,所以消息可以做到同步;如果使用的是 NIO Sender,你也可以并發地發送消息。
并發(Concurrently)意味著將同時有多個發送者對應著一條消息,并行(Parallel)則意味著同時有多個消息對應著多個發送者。
<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>
Tribes 利用了一個堆棧傳送消息。每個堆棧內的元素都被稱為攔截器,跟 Tomcat 容器中的 valve 的作用差不多。使用攔截器,邏輯可被分成更容易管理的代碼段。上面配置中的攔截器:
請注意,攔截器的順序很重要。在 server.xml 中定義的順序正是它們出現在 channel 堆棧中的順序。這種機制就像是鏈表,最前面的是第一個攔截器,末尾的是最后一個攔截器。
<Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
filter=".*\.gif|.*\.js|.*\.jpeg|.*\.jpg|.*\.png|.*\.htm|.*\.html|.*\.css|.*\.txt"/>
集群使用 valve 來跟蹤針對 Web 應用的請求。我們之前已經提到過 ReplicationValve 和 JvmRouteBinderValve。 元素本身并不是 Tomcat 管道的一部分,集群將 valve 添加到了它的父容器上,比如說 元素被配置到 元素中,那么 valve 就會被加到 元素中。
<Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
tempDir="/tmp/war-temp/"
deployDir="/tmp/war-deploy/"
watchDir="/tmp/war-listen/"
watchEnabled="false"/>
默認的 Tomcat 集群支持耕種部署(farmed deployment),比如說集群可以在其他的節點上部署和取消部署應用。該組件的狀態目前還不穩定,但我們很快就會解決這個問題。Tomcat 5.0 和 5.5 版本相比,在部署算法上有一點變化。組件的邏輯改變到部署目錄必須與應用目錄相匹配。
<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>
因為 SimpleTcpCluster 本身既是 Channel 對象的發送者,又是接受者,所以組件可以將它們自身注冊成SimpleTcpCluster 的偵聽器。 上面這個偵聽器 ClusterSessionListener 將偵聽 DeltaManager 復制的消息,并將會話變更應用到 manager 上,反過來應用到會話上。