Windows下搭建Tomcat集群的配置详解
《 Windows下搭建Tomcat集群基礎入門詳解?》
前言
在搭建 《 Apache + Tomcat 實現Web服務器集群 》 前我們還需要實現 Tomcat集群實現Session復制 ,這樣用戶只需要登錄一次即可,就不用每次請求都需要登錄了,這兒使用的是兩個 Tomcat 節點實現集群及節點間 Session 的復制。
首先我們需要找到 Tomcat 的配置文件 “ server.xml ?” ,在其中找到 <Engine> 節點,在該節點下添加一個 <Cluster className =“org.apache.catalina.ha.tcp.SimpleTcpCluster”/> 節點,
關于 Tomcat 集群的默認配置如下:
配置簡述:
1、組播地址為 228.0.0.4 。
2、組播端口為 45564(端口和地址共同決定了集群成員 status)。
3、廣播的 IP 是 java.net.InetAddress.getLocalHost().getHostAddress()(請確保沒有廣播127.0.0.1,這是一個常見錯誤,如果廣播為 127.0.0.1,集群會創建失敗喲!)。
4、該 TCP 端口監聽復制消息是在第一個可用的 socket 服務器 4000-4100 范圍中。
5、兩個偵聽配置 ClusterSessionListener 和 JvmRouteSessionIDBinderListener ,在這兒我只使用了 ClusterSessionListener 即可。
6、兩個攔截器配置為 TcpFailureDetector 和 MessageDispatch15Interceptor。
注意事項:
使用上述配置將使用 DeltaManager 復制 DeltaSession 來啟用 Tomcat 節點間全部會話的復制。也就是將會話復制到集群中的所有其他 Tomcat 節點。
關于這個 Tomcat 集群配置只使用于較小的群集非常適用,但我們不建議將它用于較大的群集(多個 Tomcat 節點)。
另外,在使用 DeltaManager 時,它將復制到所有節點,只要在集群的 Tomcat 節點中配置了集群即使沒有部署應用程序的節點也是復制/廣播到該節點。
為了解決這個問題,需要使用備份管理器。此管理器僅將會話數據復制到一個備份節點,并且僅復制到已部署應用程序的節點。使用備份管理器的缺點:和 DeltaManager 的測試不一樣。?
實現 Tomcat 集群需要滿足基本要求
1、所有的會話屬性都必須實現 java.io.Serializable 接口。
2、取消 server.xml中 Cluster 元素注釋。
3、如果在集群中自定了 Valve,則請確保該在 server.xml 中定義了 ReplicationValve 元素。
4、如果一個集群中所有的 Tomcat 實例在同一臺服務器上運行,??請確保 server.xml 中 TcpListenPort 屬性對于每個實例都是唯一的,但是在大多數情況下,Tomcat 可通過自動檢測 4000-4100 范圍內的可用端口來解決此問題。
5、必須確保在應用程序 web.xml 配置文件中存在 <distributable/> 元素。
6、如果您使用的是 mod_jk 連接器,請確保在引擎中設置了 jvmRoute 屬性 ( <Engine name="Catalina" jvmRoute="node01" > ),并且 jvmRoute 屬性值與 workers.properties 中所配置 workers 的名稱相同。
7、確保所有節點具有相同的時間(如果時間不一致,這兒有個代名詞叫時間戳問題)并與NTP服務同步。
8、確保您的負載均衡器配置為具有粘性的會話模式。
在 Tomcat 中啟用會話復制,三種方法實現會話相同
1、使用會話持久性,并將會話保存到共享文件系統(PersistenceManager + FileStore)
2、使用會話持久性,并將會話保存到共享數據庫(PersistenceManager + JDBCStore)
3、使用內存復制,使用 Tomcat 附帶的 SimpleTcpCluster(lib / catalina-tribes.jar + lib / catalina-ha.jar)
集群描述
Membership 是使用組播心跳建立的。因此,如果希望細分 Tomcat 群集,可以通過修改 <Membership> 元素中的多播IP地址或端口來實現。
心跳包含 Tomcat節點的IP地址和 Tomcat 監聽復制流量的 TCP 端口。所有數據通信都通過 TCP 進行的。
ReplicationValve 主要被用來找出當請求已經完成并開始復制的會話,如果有,則只有在會話發生改變時才會復制 session 數據(主要通過在會話上調用 setAttribute 或 removeAttribute 實現)。
關于 Tomcat 中 session 數據復制分為同步復制和異步復制,這個會直接影響集群性能。
在同步復制模式下,請求不會返回,直到復制的會話通過線路發送并重新實例化所有其他群集節點。
同步與異步配置使用該 channelSendOptions 標志并且是一個整數值。SimpleTcpCluster/DeltaManager 組合的默認值是 “ 8 ”,這個是異步的。
為了更加方便,channelSendOptions 還可以通過別名來設置,然后在啟動時將其轉換為整數值。
別名包括:“異步”(別名為“async”),“byte_message”(別名為“字節”),“多播”,“安全”,“synchronized_ack”(別名為“同步”),“udp” ”。
使用逗號分隔多個名稱,例如通過選項的“異步,多播” SEND_OPTIONS_ASYNCHRONOUS | SEND_OPTIONS_MULTICAST。
將崩潰后的會話綁定到故障轉移節點
如果在集群中使用的是 mod_jk 而不是使用 “ 粘性會話 ”,或者由于某些原因,粘性會話不起作用,或者您只是簡單地進行故障轉移,則需要修改會話標識即可,因為它之前包含上一個 Tomcat 的 ?worker ?標識(由 jvmRoute 在 <Engine/> 元素中定義)。
為了解決故障轉移的問題,需要使用 JvmRouteBinderValve。
使用 JvmRouteBinderValve 重會話 ID 以確保在故障切換后下一個請求將保持粘滯狀態(并且不會退回到隨機節點,因為該 worker 不再可用)。Valve 重寫同名的 cookie 中的 JSESSIONID 值。如果沒有這個 Valve,在 mod_jk 模塊發生故障時將難以確保粘性。
注意:
需要注意的是如果要在 server.xml 中添加自己的 Valve,那么缺省的值不再有效,請確保添加默認定義的所有適當的 Valve。
提示:
通過屬性 sessionIdAttribute,可以更改包含舊會話標識的請求屬性名稱。
默認屬性名稱是 org.apache.catalina.ha.session.JvmRouteOrignalSessionID。
技巧:
在將節點終止時,您可以通過 JMX 啟用 mod_jk 轉換模式!在所有 JvmRouteBinderValve 備份上設置為 true,在 mod_jk 上禁用 worker,然后終止該節點并重新啟動它!然后啟用 mod_jk Worker 并再次禁用 JvmRouteBinderValves。這個用例意味著只有被請求的會話被遷移。
配置實例
<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.MessageDispatchInterceptor"/><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>
將其進行分解:
主元素:
在這個元素中所有的集群細節都可以配置。其中 channelSendOptions 是連接到 SimpleTcpCluster 類或調用 SimpleTcpCluster 的任何對象所發送的每個消息的標志。
在 java 文檔中可以查看到發送標志的具體描述,DeltaManager 使用 SimpleTcpCluster 發送信息。而備份管理器則直接通過通道發送消息。
管理器配置模板:
<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"/> -->
如果 <Context/> 元素中沒有定義管理器,將使用該管理器模板。在 Tomcat 5.x 中,每個 webapp 的標記分布必須使用相同的管理器,因為在 Tomcat 中可以為每個 webapp 定義一個管理器類,
所以可以在一個集群中使用混合管理器。很顯然,一個節點上的應用程序的管理器與另一個節點上的同一個應用程序的的管理器相對應。
如果沒有為 webapp 指定管理器,并且 webapp 被標記為 <distributable /> Tomcat將采用此管理器配置并創建克隆此配置的管理器實例。?
通信:
<Channel className="org.apache.catalina.tribes.group.GroupChannel">
在 Tomcat 中使用的組通信框架。該元素封裝了與通信和成員邏輯相關的所有內容。
節點間的組播:
<Membership className="org.apache.catalina.tribes.membership.McastService"address="228.0.0.4"port="45564"frequency="500"dropTime="3000"/>
集群中節點通過多播的方式完成的。在節點中還支持靜態成員使用 StaticMembershipInterceptor,如果想延長加入的節點超出多播,
那么必須地址屬性是使用的組播地址,端口是組播端口。這兩者一起創建集群分離。如果想要保證群集和生產群集的高性能,最簡單的配置是使群集位于與生產群集不同的多播地址/端口組合之上。
成員組通過廣播其自身的 TCP地址/端口 到其他節點,以便節點之間的通信可以通過TCP完成。
消息接收:
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"address="auto"port="5000"selectorTimeout="100"maxThreads="6"/>
在一個節點中,發送和接收數據的邏輯已被分解為兩個功能組件。
該 Receiver 顧名思義就是負責接消息的接收。由于節點的堆棧線程少(其他框架也采用了一種流行的改進方法),此組件中只有一個線程池,它具有 maxThreads 和 minThreads 設置。
其中 address 屬性是由成員組件向其他節點廣播的主機地址。
消息發送:
該 Sender 顧名思義就是負責接消息的發送,Sender 有一個shell組件ReplicationTransmitter,但是在子組件 Transport 中完成工作的。一個節點中支持 Sender pool,以便消息的并行發送,使用 NioSender ,也可以實現消息的濱興發送。
同時:同時向多個 Sender 發送一條消息。
并行:并行向多個 Sender 同時發送多條消息。
攔截器:
在節點中使用堆棧進行消息的發送。在堆棧中的每個元素都稱為攔截器,其工作方式與 Tomcat servlet 容器中的 Valve 非常相似。
使用攔截器后,其業務邏輯可以分解為更易于管理的代碼片斷。常用的三種攔截器:
1、TcpFailureDetector - 通過 TCP 驗證集群中的節點是否掛掉,如果組播中的數據包被丟棄,這個攔截器作用是防止被誤報(即使該節點仍然活著并且正在運行,但是被誤標記為崩潰的節點)。
2、MessageDispatchInterceptor - 將消息分派給線程(thread pool)以便異步消息發送。
3、ThroughputInterceptor - 輸出簡單消息流量統計信息。
注意:攔截器的順序很重要。在 server.xml 中是以堆棧表示的方式。把它們想象成一個鏈表的形式,頭部是第一個攔截器,尾部是最后一個。
集群請求跟蹤:
<Valve className="org.apache.catalina.ha.tcp.ReplicationValve"filter=".*\.gif|.*\.js|.*\.jpeg|.*\.jpg|.*\.png|.*\.htm|.*\.html|.*\.css|.*\.txt"/>
在集群中配置 Valve 來跟蹤對 Web 應用程序的請求,在上面已經提到了 ReplicationValve 和 JvmRouteBinderValve。
<Cluster> 元素本身不是 Tomcat 中管道的一部分,而是集群將 Valve 添加到其父容器。如果在 <Engine> 元素中配置了 <Cluster> 元素,則需要將 Valve 添加到 Engine 下。?
支持遠程部署:
<Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"tempDir="/tmp/war-temp/"deployDir="/tmp/war-deploy/"watchDir="/tmp/war-listen/"watchEnabled="false"/>
Tomcat集群默認支持遠程部署,即可以在其他集群節點上部署和取消部署應用程序。
這個組件的狀態處于不斷變化之中,但很快就解決了。Tomcat 5.0 和 5.5 之間的部署方法發生了變化,此時該組件的邏輯已更改為部署目錄必須與 webapps 目錄匹配的位置。?
監聽器:
<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
由于 SimpleTcpCluster 本身是 Channel 對象的“ 發送者 ” 和 “ 接收者 ”,因此組件可以將自己注冊為 SimpleTcpCluster 的監聽器。
上面的 ClusterSessionListener 監聽器監聽 DeltaManager 復制消息,并將 Delta 應用于 Manager,然后將其應用于 Session。
理解 Tomcat 集群如何運行的
為了便于理解群集如何工作的,這兒使用兩個 Tomcat 實例 ,即 TomcatA 和 TomcatB 。操作內容如下:
1、TomcatA 啟動
2、TomcatB 啟動(等待 TomcatA 啟動完成)
3、TomcatA 收到一個請求,會話 S1 被創建
4、TomcatA 崩潰
5、TomcatB 收到會話請求 S1
6、TomcatA 啟動
7、TomcatA 接收到一個請求,在會話(S1)上調用 invalidate
8、TomcatB 接收請求,進行新會話(S2)
9、TomcatA 會話 S2 由于不活動而過期(這兒就需要重新登錄了)
有了一個大致的提綱后,下面我們進行詳細的介紹:
1、TomcatA 啟動
Tomcat 使用標準啟動序列啟動。當創建 Host 對象時,將與它關聯一個集群對象。在解析上下文時,如果 web.xml 中定義了 distributable 元素,Tomcat 會詢問 Cluster 類(在本例中 SimpleTcpCluster )為復制的 <Context/> 中創建 Manager。
因此,啟用集群后,可以在 web.xml 中設置可分發的數據集, Tomcat 將為該 <Context/> 創建一個DeltaManager,而不是一個 StandardManager。群集還將啟動 Membership ?服務(多播)和 Replication 服務(tcp單播)。
2、TomcatB 啟動
當 TomcatB 啟動時,它遵循與TomcatA相同的序列。該集群已啟動并將建立 membership(TomcatA,TomcatB)。
TomcatB 現在將從群集中已存在的服務器(在本例中 為TomcatA )請求會話狀態。TomcatA 響應請求,并且在 TomcatB 開始監聽 HTTP 請求之前,status 已從 TomcatA 轉移到 TomcatB。
如果 TomcatA 沒有響應,TomcatB 將在60秒后超時,并發出日志通知。每個 web 應用程序的會話狀態都被轉移到它的 web.xml 中。
注意:為了使會話有效的復制,所有的 Tomcat實例都應該配置相同。
3、TomcatA 收到一個請求,會話 S1 被創建
對 TomcatA 的請求與沒有會話復制的處理方式完全相同。當請求完成時,ReplicationValve 會在將響應返回給用戶之前攔截請求。
此時 TomcatA 發現會話已被修改,并且它使用 TCP 將會話復制到 TomcatB。一旦序列化的數據被傳遞到 TCP 邏輯,請求就會通過 Valve 管道返回給用戶。
對于每個請求,整個會話都被復制,這允許在會話中修改屬性的代碼,而不需要復制 setAttribute 或 removeAttribute。可以使用 useDirtyFlag 配置參數來優化會話復制的次數。
4、TomcatA 崩潰
當TomcatA崩潰時,TomcatB 收到一個通知,TomcatA 已經退出集群。TomcatB 從其成員列表中刪除 TomcatA,TomcatA 將不再收到 TomcatB 發生的任何更改通知。
負載均衡器會將來自 TomcatA 的請求重定向到 TomcatB,并且所有會話都是最新的。
5、TomcatB 收到會話請求 S1
TomcatB 將處理請求作為任何其他請求。
6、TomcatA 啟動
在 TomcatA 啟動之后,在 TomcatA 開始接受新請求并使其可用之前,將遵循上述1)2)所述的啟動順序。
TomcatA 將加入集群,并與 TomcatB 聯系以獲取當前所有會話的狀態。一旦它收到會話狀態,它就完成加載并打開它的HTTP / mod_jk端口。
因此,在 TomcatB 接收到會話狀態之前,沒有任何請求會到達 TomcatA。
7、TomcatA 接收到一個請求,在會話(S1)上調用 invalidate
無效的調用被攔截,并且會話在無效會話中排隊。當請求完成時,不再發送已更改的會話,而是向 TomcatB 發送一條 “ 過期 ” 的消息,并且 TomcatB 也會使該會話失效。
8、TomcatB 接收請求,進行新會話(S2)
與步驟3中相同的場景)
9、TomcatA會話S2由于不活動而過期
無效的調用被攔截,就像用戶會話無效時一樣,會話被無效會話排隊。此時,無效會話將不會被復制,直到另一個請求通過系統并檢查無效隊列為止。
Membership : 群集 Membership 使用非常簡單的組播 ping 建立。每個 Tomcat 實例將定期發送一個多播 ping,在 ping 消息中,實例將廣泛地將其 IP 和 TCP 監聽端口進行復制。
如果在集群中一個實例在給定的時間范圍內沒有收到這樣的 ping,則該成員被認為是死的。非常簡單,而且非常有效!當然,只需要在系統上啟用多播。
TCP Replication : 一旦接收到組播 ping,member 就會被添加到集群。
在下一個請求時復制,發送實例將使用 Host 和 Port 信息并建立一個TCP Socket。使用這個 Socket,它將發送序列化后的數據。
分布式鎖定和使用框架頁面 : Tomcat 不會保持會話實例在群集中同步。這種邏輯的實現會花費很多開銷并導致各種問題。
如果在客戶端使用多個請求同時訪問同一會話,則最后一個請求將覆蓋集群中的其他會話。
Apache Tomcat 官網: https://tomcat.apache.org/tomcat-9.0-doc/cluster-howto.html
總結
以上是生活随笔為你收集整理的Windows下搭建Tomcat集群的配置详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: stm32f407igh6学习笔记
- 下一篇: 域格模块FOTA空中升级