只需將下列信息放入 或 元素即可實(shí)現(xiàn)集群:
上述配置啟用了全局(all-to-all)會話復(fù)制功能,全局會話復(fù)制是指利用 DeltaManager 來只復(fù)制會話中的變更(Session Delta,也譯作“會話增量”)。這里說的“全局”是指:會話變更會被復(fù)制到集群中的所有其他節(jié)點(diǎn)(指 Tomcat 實(shí)例)中。全局復(fù)制非常適于小集群,但不建議在大集群(包含很多 Tomcat 節(jié)點(diǎn))上采用這種方法。另外,值得注意的是,當(dāng)使用 delta manager 時,它會將變更復(fù)制到所有的節(jié)點(diǎn)上,甚至包括那些根本沒有部署該應(yīng)用的節(jié)點(diǎn)。
為了解決這個問題,你就得使用 BackupManager。它會把會話數(shù)據(jù)復(fù)制給一個指定的備份節(jié)點(diǎn)(這種復(fù)制也被稱為“配對復(fù)制”),而且該備份節(jié)點(diǎn)也一定要部署了相關(guān)應(yīng)用。BackupManager 的缺點(diǎn)在于:不像 DeltaManager 那樣久經(jīng)實(shí)踐考驗(yàn)。
下面是一些重要的默認(rèn)值。
下面是默認(rèn)的集群配置:
<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.ClusterSessionListener"/>
</Cluster>
稍后,本文檔將更詳細(xì)地闡述這部分的內(nèi)容。
要想在 Tomcat 8 上運(yùn)行會話復(fù)制,需要執(zhí)行以下步驟:
負(fù)載均衡可以通過多種技術(shù)來實(shí)現(xiàn),參看負(fù)載均衡部分。
注意:會話狀態(tài)是通過 cookie 來記錄的,所以你的 URL 必須保持一致,否則就會創(chuàng)建一個新會話。
注意:當(dāng)前如要支持集群,需要 JDK 1.5 或更新版本。
集群模塊使用 Tomcat 的 JULI 日志框架,所以可以通過 logging.properties 文件來配置日志。為了跟蹤消息,你可以啟用 org.apache.catalina.tribes.MESSAGES 鍵上的日志。
在 Tomcat 中,可以使用以下方法中的一種啟用會話復(fù)制:
在這一版本的 Tomcat 中,可以使用 DeltaManager 執(zhí)行全局式會話狀態(tài)復(fù)制,或者使用 BackupManager 執(zhí)行備份復(fù)制,將會話復(fù)制到一個節(jié)點(diǎn)上。全局式會話復(fù)制這種算法只有在集群較小時才比較有效。對于大型集群,更多使用主從會話復(fù)制,將會話存儲到一臺配置了 BackupManager 的備份服務(wù)器上。
當(dāng)前可以使用域名 worker 屬性(mod_jk 版本 > 1.2.8)來構(gòu)建集群分區(qū),從而有可能利用 DeltaManager 實(shí)現(xiàn)更具有可擴(kuò)展性的集群方案(需要為此配置域的攔截器)。為了在全局性環(huán)境中降低網(wǎng)絡(luò)流量,可以將集群分成幾個較小的分組。為不同的分組使用不同的組播地址即能實(shí)現(xiàn)這種方案。下圖展示的是一種簡單的配置方案。
DNS 輪詢
|
負(fù) 載 均 衡 器
/ \
集群 1 集群 2
/ \ / \
Tomcat 1 Tomcat 2 Tomcat 3 Tomcat 4
Tomcat集群信息
值得注意的是,使用會話復(fù)制僅僅是集群化的一個基礎(chǔ)方案。關(guān)于集群的實(shí)現(xiàn),另一個常用的概念是耕種(farming),比如:只需將應(yīng)用部署到一個服務(wù)器上,集群就會將部署分發(fā)到整個集群的各個節(jié)點(diǎn)中。這都是 FarmWarDeployer 所具有的功能(參看 server.xml 中的集群范例)。
下一節(jié)將深入介紹會話復(fù)制的工作原理以及配置方式。
通過組播心跳包(heartbeat)建立起成員(Membership)關(guān)系,因此,如果希望細(xì)分集群,可以改變 <Membership> 元素中的組播 IP 地址或端口。
心跳包中含有 Tomcat 節(jié)點(diǎn)的 IP 地址,以及 Tomcat 用來偵聽會話復(fù)制流量的 TCP 端口。所有的數(shù)據(jù)通信都使用了 TCP 協(xié)議。
ReplicationValve 用于查找請求結(jié)束的時間,如果存在會話復(fù)制,就對該復(fù)制進(jìn)行初始化。只復(fù)制會話變更的數(shù)據(jù)(通過在會話上調(diào)用 setAttribute 或 removeAttribute 來完成)。
復(fù)制的異步與同步模式應(yīng)該是最值得我們注意的一個特點(diǎn)了。在同步復(fù)制模式下,復(fù)制的會話通過線纜傳送,重新在所有集群節(jié)點(diǎn)上實(shí)例化,這樣才會返回請求。同步和異步是通過 channelSendOptions 標(biāo)志(整型值)來配置的。SimpleTcpCluster/DeltaManager 組合的默認(rèn)值是 8,從而是異步。詳情可以參考一下 send flag(overview) 或 send flag(javadoc)。在異步復(fù)制過程中,請求不必等到數(shù)據(jù)被復(fù)制完畢即可返回。異步復(fù)制縮短了請求時間,而同步復(fù)制則保證了能在請求返回之前復(fù)制完會話。
如果你使用了 mod_jk 而沒有使用粘性會話(sticky session),或者粘性會話由于某種原因而不起作用,或者僅是故障轉(zhuǎn)移,會話 id 需要修改,因?yàn)樗昂兄?Tomcat 的 worker id(通過 Engine 元素中的 jvmRoute 定義)。為了解決這個問題,就要用到 JvmRouteBinderValve。
JvmRouteBinderValve 將重寫會話 id,以便確保下一個請求在故障轉(zhuǎn)移后依然能保持粘性(不會因?yàn)?worker 不再可用而回滾到某個隨機(jī)的節(jié)點(diǎn)中)。利用同樣的名字,該值重寫了 cookie 中的 JSESSIONID 值。假如沒有正確地設(shè)置 valve,將使 mod_jk 模塊在失敗后很難保持會話的粘性。
記住,如果在 server.xml 中自定義值,那么默認(rèn)值將不再有效,所以一定要確保添加了默認(rèn)所定義的值。
提示:
利用屬性 sessionIdAttribute 可以改變包含舊會話 id 的請求屬性名。默認(rèn)的請求屬性名是:org.apache.catalina.ha.session.JvmRouteOrignalSessionID。
技巧:
可以啟用 mod_jk 翻轉(zhuǎn)模式在刪除一個節(jié)點(diǎn), 然后啟用了 mod_jk Worker 禁用 JvmRouteBinderValves 。這種用例意味著只有請求的會話才能得到遷移。