1 概述
集群允許一個應用同時運行在多個并發的服務器。負載分布在不同的服務器,即使有個別服務器崩潰,應用程序還可以通過別的服務器節點訪問。集群是企業級應用的關鍵技術,可以通過簡單地增加節點來提升性能。
JBoss支持集群,啟動一個JBoss集群的最簡單的方式是,使用run -c all命令在局域網內啟動多個JBoss實例。這些服務器實例,都使用all配置集,自動地構建一個集群。
1.1 定義
一個集群是由一系列節點組成。在一個JBoss集群中,一個節點是一個JBoss服務器實例,要構建一個集群,必須將幾個JBoss服務器實例組合在一起。在一個局域網可能有多個集群,為了區分他們,每個集群必須有唯一的名稱。
下圖構建一個網絡,包含三個集群。節點可以在任何時候添加到集群或者從集群中

注意:
一個JBoss服務器實例可以同時在多個集群,但是不推薦這樣做,因為會增加管理復雜性。
JBoss服務器實例通過deploy/cluster-service.xml 文件中的ClusterPartition MBean指定屬于哪一個集群。所有有同樣的ClusterPartition MBean配置的節點屬性同一個集群。因此,如果想在同一個局域網構建兩個集群,只需要創建兩個不同的ClusterPartition配置即可。如果某一個節點啟動時,集群還不存在,會創建這個集群,同時當屬于一個集群的所有節點移除時,集群也會被移除。
下面的示例是JBoss發布包的缺省定義,通過使用此缺省集群設置啟動服務器,將可以構建一個缺省集群名稱為DefaultPartition的集群。
- <mbean code="org.jboss.ha.framework.server.ClusterPartition"
- name="jboss:service=DefaultPartition">
- >
- <attribute name="PartitionName">
- ${jboss.partition.name:DefaultPartition}
- attribute>
- >
- <attribute name="NodeAddress">${jboss.bind.address}attribute>
- >
- <attribute name="DeadlockDetection">Falseattribute>
- Increase for large states -->
- <attribute name="StateTransferTimeout">30000attribute>
- >
- <attribute name="PartitionConfig">
- ... ...
- attribute>
- mbean>
這里省略了詳細的JGroups協議配置,JGoups處理底層的節點之間的點對點通信,稍后將討論其具體配置。ClusterPartition MBean可配置的屬性包括:
-
PartitionName 缺省值是DefaultPartition,可選屬性,用來指定集群的名稱。
-
NodeAddress 設置節點的IP地址。
-
DeadlockDetection 缺省值為false,設置JGroups是否基于每個請求都運行消息死鎖檢測算法。
-
StateTransferTimeout 缺省值是30000,設置集群之間的狀態復制的超時值。
-
PartitionConfig 指定JGourp配置選項。
一個集群包含的所有節點,必須有同樣的 PartitionName 和 ParitionConfig 元素。改變某些節點的這兩個元素將導致集群分離,通過改變ParitionConfig 是更容易一些。
可以通過集群中的任何一個節點的JMX控制臺查看當前集群信息(比如:http://hostname:8080/jmx-console),然后點擊 jboss:service=DefaultPartition MBean,將可以看到當前集群的所有節點的IP地址列表。
注意
A cluster (partition) contains a set of nodes that work toward a same goal. Some clustering features require to sub-partition the cluster to achieve a better scalability. For example, let's imagine that we have a 10-node cluster and we want to replicate in memory the state of stateful session beans on all 10 different nodes to provide for fault-tolerant behaviour. It would mean that each node has to store a backup of the 9 other nodes. This would not scale at all (each node would need to carry the whole state cluster load). It is probably much better to have some kind of sub-partitions inside a cluster and have beans state exchanged only between nodes that are part of the same sub-partition. The future JBoss clustering implementation will support sub-partitions and it will allow the cluster administrator to determine the optimal size of a sub-partition. The sub-partition topology computation will be done dynamically by the cluster.
1.2 服務架構
對于應用程序開發人員來講,可能更關心集群的架構,JBoss支持兩種類型的集群架構,一種是客戶端的攔截器架構,比如代理和存根,還有一種是負載平衡器。
1.2.1 客戶端攔截器架構
JBoss應用服務器提供的大多數遠程服務,包括JNDI,EJB,RMI等都要求客戶端獲取一個存根對象。存根對象由服務器生成,實現服務接口。客戶端在本地調用存根對象,這些調用自動進行網絡路由,激活服務器管理的服務對象。在一個集群環境中,服務器生成的存根對象也是一個攔截器實現,知道如何在集群包含的節點中路由請求。存根對象知道如何查找合適的服務器節點,編碼調用參數,解碼調用結果,并返回結果給客戶端。
存根攔截器包含集群的相關信息,比如,所有可用的服務器節點的IP地址,負載平衡算法,以及當某個目標節點不可用時如何處理請求。每個請求中,服務器節點將用集群的最近的改變信息更新存根攔截器。比如,一個節點從集群中移除,當每個存根攔截器連接到任何一個激活的節點時,都將更新最新的配置信息。所有基于存根的操作對于客戶來講都是透明的,客戶端攔截器集群架構如下圖所示:

1.2.2 負載平衡器
別的JBoss服務,特別是HTTP WEB服務,不要求客戶端下載任何東西。客戶直接通過某個通信協議發送請求并接受響應,比如HTTP協議。這種情況下,一個負載平衡器用來處理所有的請求并將這些請求派發給集群中的節點。負載平衡器通常是集群的一部分,它知道集群配置和恢復策略,客戶端只需要知道負載平衡器。負載平衡器架構如下圖所示:
負載平衡器架構的一個潛在的問題是負載平衡器是所有請求的唯一入口,必須保證高的可用性。
1.2.3 負載平衡策略
客戶攔截器架構和負載平衡器架構都使用負載平衡策略確定由哪一個服務器節點發送一個新的請求。下面描述JBoss AS的負載平衡策略。
1.2.3.1 JBoss AS 3.0.x
JBoss 3.0.x 中有如下兩個負載平衡選項可用:
-
Round-Robin (org.jboss.ha.framework.interfaces.RoundRobin):每次調用被派發給一個新的節點,第一個節點是隨機選擇的。
-
First Available (org.jboss.ha.framework.interfaces.FirstAvailable)::第一個可用的節點選為主節點,服務于隨后每一個調用,主節點的選擇是隨機的。當集群中的節點發生變化時(因為節點啟動或者停止),除非當前主節點依然可用,將重新選擇一個可用的節點作為主節點。每個客戶端攔截器或負載平衡器獨立選擇自己的主節點。
1.2.3.2 JBoss AS 3.2+
JBoss 3.2+ 中增加了一個新的負載平衡選項 "First AvailableIdenticalAllProxies" (org.jboss.ha.framework.interfaces.FirstAvailableIdenticalAllProxies),此選項和 "First Available" 策略有類似的策略,唯一的區別是選擇的主節點被所有的客戶端攔截器共享。
JBoss 3.2 以后的版本中, 定義了"Proxy Family"術語。is defined. A Proxy Family is a set of stub interceptors that all make invocations against the same replicated target. For EJBs for example, all stubs targeting the same EJB in a given cluster belong to the same proxy family. All interceptors of a given family share the same list of target nodes. Each interceptor also has the ability to share arbitrary information with other interceptors of the same family. A use case for the proxy family is give in Section 1.3.1, “Stateless Session Bean in EJB 2.x”.
1.2.4 布署
在一個集群中布署應用程序最容易的方式是使用farming服務,就是將一個應用程序壓縮文件(EAR,WAR或SAR)熱布署到任一個節點的 all/farm/ 目錄,應用程序會自動地復制到集群中的其他節點。如果稍后有新的節點加入,新節點啟動時也會自動從集群中復制應用程序并布署到本地。在集群運行的過程中,如果從任一節點的farm目錄移除應用程序,這個應用程序將首先從本地卸載,然后再從集群的其他節點中卸載。應該手動從當前沒有連接到集群的服務器節點中刪除應用程序。
注意
當前存在一個Bug,Farm布署服務只能在熱布署壓縮文件的方式中才能生效。如果你首先放一個應用程序在farm目錄,然后啟動服務器,這個應用程序將不會被檢測并布署到集群中。
注意
在farm目錄中只能使用壓縮文件,而不能使用展開的目錄。
Farming 服務在JBoss AS發布版的all配置集中是缺省啟用的,不需要手動設置。配置文件保存在deploy/deploy.last目錄,如果需要在集群配置中啟用farming服務,創建farm-service.xml文件如下,并拷貝到JBoss布署目錄$JBOSS_HOME/server/your_own_config/deploy,確保在配置中已經啟用集群服務。
- xml version="1.0" encoding="UTF-8"?>
- <server>
- <mbean code="org.jboss.ha.framework.server.FarmMemberService"
- name="jboss:service=FarmMember,partition=DefaultPartition">
- ...
- <attribute name="PartitionName">DefaultPartitionattribute>
- <attribute name="ScanPeriod">5000attribute>
- <attribute name="URLs">farm/attribute>
- mbean>
- server>
FarmMemberService MBean 可用的屬性如下:
-
PartitionName 指定集群名字,缺省值為 DefaultPartition.
-
URLs 指定布署器監控布署文件的目錄,如果不存在,MBean將創建。 "." 表示配置目錄(比如 $JBOSS_HOME/server/all/)。
-
ScanPeriod 指定文件夾的掃描周期,缺省值為5000。
Farming 服務是URLDeploymentScanner的擴展,用來掃描deploy目錄,因此在FarmMemberService MBean中可以使用URLDeploymentScanner MBean 中定義的所有屬性。
1.2.4 分布式狀態復制服務
集群環境中,分布式狀態管理是集群必須提供的一個關鍵服務。比如一個有狀態的會話Bean應用程序,會話狀態必須在所有節點的Bean實例中保持同步,因此不管哪個節點服務請求,客戶端應該得到同樣的會話狀態。實體Bean應用程序中,Bean實例必須在集群中進行緩存以減輕數據庫負載。目前JBoss AS中的狀態復制和分布式緩存由兩種方式提供: HASessionState MBean 和 JBoss Cache 框架。
-
HASessionState MBean 基于EJB2.X有狀態會話Bean和JBoss3.x和4.x的HTTP負載平衡器提供會話復制和分布式緩存服務。MBean相關定義在 all/deploy/cluster-service.xml 文件中。
-
JBoss Cache 是一個分布式緩存框架,可以用在任何應用程序服務器環境,也可以獨立使用,已經逐漸替換 HASessionState 服務。JBoss AS 整合JBoss Cache 為HTTP會話, EJB 3.0 會話和實體Bean,Hibernate持久對象提供緩存服務。這些緩存服務都在獨立的MBean中定義。
1.5 HTTP服務
HTTP會話復制用來在你的WEB客戶端和集群的節點之間復制狀態,那么當某一個節點崩潰時,集群中的其他節點可以恢復。要實現這個目的,必須執行兩個步驟:
-
會話狀態復制
-
請求負載平衡
如果使用all配置集啟動JBoss,缺省會啟用會話狀態復制功能,只需要布署你的應用程序,會話狀態就已經可以在集群中進行復制。
但是負載平衡需要額外的軟件支持,作為一個常用的場景,我們將描述如何設置Apache和mod_jk。這個功能也可以通過專門的硬件或者其他軟件來實現。
注意
一個負載平衡器跟蹤HTTP請求,根據和請求關聯的會話,決定派發請求到合適的節點。這被稱作使用sticky-sessions的負載平衡器:一 旦在某個節點創建了會話,隨后的請求將由同一個節點進行處理。使用一個支持sticky-sessions的負載平衡器可以不用復制會話,沒有會話狀態復 制的花銷,每個請求將是被同一個節點處理。但是一旦這個節點崩潰,保存在這個節點的所有客戶會話都將丟失,客戶必須登錄進另一個節點,重新啟動一個新的會 話。在某些情況,不復制HTTP會話是可以接受的,因為比較關鍵的狀態都保存在數據庫中,但是也有些情況下,丟失會話狀態是無法接受的,這種情況下,會話 狀態復制的花銷是必須承受的。
Apache 是一個可以通過插入模塊擴展功能的WEB服務器,mod_jk(最新的mod_jk2)模塊的主要功能就是允許從Apache分發請求到一個 Servlet容器,還可以支持在多個Servlet容器中負載平衡HTTP調用(遵循sticky-sessions)。
1.5.1. 下載軟件
從http://httpd.apache.org/ 下載Apache,安裝是非常直白的,不需要特別的配置,推薦使用2.0.x版本,這里假定Apache安裝目錄為APACHE_HOME。
然后從www.apache.org/dist/jakarta/tomcat-connectors/jk/binaries/. 下載mod_jk模塊,建議使用mod_jk 1.2.x版本。重命名下載的文件為mod_jk.so,拷貝到APACHE_HOME/modules/目錄下。
1.5.2. 配置Apache使用mod_jk
更改APACHE_HOME/conf/httpd.conf 文件,在文件尾部添加一行:
- # Include mod_jk's specific configuration file
- Include conf/mod-jk.conf
創建文件APACHE_HOME/conf/mod-jk.conf:
java 代碼
- # Load mod_jk module
- # Specify the filename of the mod_jk lib
- LoadModule jk_module modules/mod_jk.so
- # Where to find workers.properties
- JkWorkersFile conf/workers.properties
- # Where to put jk logs
- JkLogFile logs/mod_jk.log
- # Set the jk log level [debug/error/info]
- JkLogLevel info
- # Select the log format
- JkLogStampFormat "[%a %b %d %H:%M:%S %Y]"
- # JkOptions indicates to send SSK KEY SIZE
- JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
- # JkRequestLogFormat
- JkRequestLogFormat "%w %V %T"
- # Mount your applications
- JkMount /application/* loadbalancer
- # You can use external file for mount points.
- # It will be checked for updates each 60 seconds.
- # The format of the file is: /url=worker
- # /examples/*=loadbalancer
- JkMountFile conf/uriworkermap.properties
- # Add shared memory.
- # This directive is present with 1.2.10 and
- # later versions of mod_jk, and is needed for
- # for load balancing to work properly
- JkShmFile logs/jk.shm
- # Add jkstatus for managing runtime data
- JkMount status
- Order deny,allow
- Deny from all
- Allow from 127.0.0.1
其中有兩個設置是非常重要的:
-
LoadModule 指令必須引用下載的mod_jk庫,路徑中必須包括modules前綴。
-
JkMount 指令通知Apache哪些URL應該被派發給mod_jk模塊(也就是派發給Servlet容器)。上面的配置中,所有基于/application/* 的請求都會派發給mod_jk負載平衡器。如果使用mod_jk作為一個專門的負載平衡器,可以將所有的請求(/*)派發給mod_jk。
除了使用 JkMount 指令,也可以使用JkMountFile 指令指定一個配置文件,包含多個URL映射配置。你只需要在APACHE_HOME/conf 目錄下創建一個uriworkermap.properties 文件。文件格式為/url=worker_name,示例文件如下:
java 代碼
- # Simple worker configuration file
- # Mount the Servlet context to the ajp13 worker
- /jmx-console=loadbalancer
- /jmx-console/*=loadbalancer
- /web-console=loadbalancer
- /web-console/*=loadbalancer
如上示例將配置 mod_jk 派發請求 /jmx-console 和/web-console 給Tomcat。
1.5.3. 在mod_jk中配置工作者節點
接著需要創建conf/workers.properties文件,這個文件用來指定名個不同的Servlet容器的位置以及調用如何在這些容器之間進行平衡。針對一個兩個節點的設置,示例文件如下:
java 代碼
- # Define list of workers that will be used
- # for mapping requests
- worker.list=loadbalancer,status
- # Define Node1
- # modify the host as your host IP or DNS name.
- worker.node1.port=8009
- worker.node1.host=node1.mydomain.com
- worker.node1.type=ajp13
- worker.node1.lbfactor=1
- worker.node1.cachesize=10
- # Define Node2
- # modify the host as your host IP or DNS name.
- worker.node2.port=8009
- worker.node2.host= node2.mydomain.com
- worker.node2.type=ajp13
- worker.node2.lbfactor=1
- worker.node2.cachesize=10
- # Load-balancing behaviour
- worker.loadbalancer.type=lb
- worker.loadbalancer.balance_workers=node1,node2
- worker.loadbalancer.sticky_session=1
- #worker.list=loadbalancer
- # Status worker for managing load balancer
- worker.status.type=status
上述文件配置mod_jk執行Round-Robin的基于sticky-sessions的負載平衡策略,兩個節點都監聽8009端口。
works.properties文件中,每個節點使用worker.XXX 命名規范進行定義,這里 XXX 可以是任何名字,用來命名Servlet容器。對于每個工作者,必須指定在目標Servlet容器中配置的AJP13連接器的IP地址和端口號。
lbfactor 屬性用來表示負載平衡權重,決定節點之間的優先級,值越大,該節點將接受越多的請求。這個選項可以用來分配不同的節點不同的負載。
cachesize 屬性定義關聯的Servlet容器的線程池大小,確定這個值沒有超過Servlet容器在AJP13連接器中的配置。可以參考jakarta.apache.org/tomcat/connectors-doc/config/workers.html
conf/workers.properties 最后定義負載平衡工作者,唯一需要改變的是worker.loadbalancer.balanced_workers 設置,必須列出剛才定義的所有工作者。
sticky_session 屬性指定集群針對HTTP會話的處理方式,如果指定worker.loadbalancer.sticky_session=0,每個請求將在兩個節點中進行負載平衡。但是當一個用戶在某個節點創建一個會話時,比較好的方式是隨后的請求都導向這個節點,這被稱作"sticky session",由于客戶總是使用會話創建的節點服務所有隨后的請求。否則用戶的會話數據必須在兩個節點進行同步,要啟用"sticky session",必須設置 worker.loadbalancer.sticky_session 值為1。
注意
A non-loadbalanced setup with a single node required the worker.list=node1 entry before mod_jk would function correctly.
1.5.4. 配置JBoss
最后必須配置集群中所有節點的JBoss Tomcat實例。
在每個節點中,我們必須根據workers.properties文件中的worker名稱來命名節點。比如,在JBoss 實例node1中,需要編輯JBOSS_HOME/server/all/deploy/jbossweb-tomcat50.sar/server.xml 文件,定位 元素添加一個jvmRoute屬性:
- <Engine name="jboss.web" defaultHost="localhost" jvmRoute="node1">
- ... ...
- Engine>
然后,對于集群中的每一個節點,我們必須通知它添加一個jvmRoute值到會話cookies中,以便mod_jk可以路由隨后的請求。編輯 JBOSS_HOME/server/all/deploy/jbossweb-tomcat50.sar/META-INF/jboss-service.xml 文件,定義UseJK的元素,設置值為true:
- <attribute name="UseJK">trueattribute>
到此為止,我們已經成功設置Apache_mod_jk使用sticky-session方式的負載平衡。
1.5.5. 配置HTTP會話狀態復制
目前為止,已經成功配置了sticky-session方式的負載平衡,但是這種方式并不是一個完善的解決方案,因為一個節點崩潰,所有的會話數據都會丟失。更可選的解決方式是在集群的節點之間復制會話狀態,這樣客戶訪問任一個節點都會獲得同樣的會話狀態。
jboss.cache:service=TomcatClusteringCache MBean 使用 JBoss Cache提供HTTP會話狀態復制服務,這個MBean定義在deploy/tc5-cluster.sar/META-INF/jboss-service.xml 文件中。
注意
JBoss AS 4.0.4 CR2以前的版本,HTTP會話緩存配置文件在deploy/tc5-cluster-service.xml文件中。
下面是一個典型的deploy/tc5-cluster.sar/META-INF/jboss-service.xml 文件
- <mbean code="org.jboss.cache.aop.TreeCacheAop"
- name="jboss.cache:service=TomcatClusteringCache">
- <depends>jboss:service=Namingdepends>
- <depends>jboss:service=TransactionManagerdepends>
- <depends>jboss.aop:service=AspectDeployerdepends>
- <attribute name="TransactionManagerLookupClass">
- org.jboss.cache.BatchModeTransactionManagerLookup
- attribute>
- <attribute name="IsolationLevel">REPEATABLE_READattribute>
- <attribute name="CacheMode">REPL_ASYNCattribute>
- <attribute name="ClusterName">
- Tomcat-${jboss.partition.name:Cluster}
- attribute>
- <attribute name="UseMarshalling">falseattribute>
- <attribute name="InactiveOnStartup">falseattribute>
- <attribute name="ClusterConfig">
- ... ...
- attribute>
- <attribute name="LockAcquisitionTimeout">15000attribute>
- mbean>
詳細的配置請參見JBossCache緩存配置部分,下面討論幾個比較關鍵的配置:
-
TransactionManagerLookupClass 設置事務管理器工廠,缺省值為org.jboss.cache.BatchModeTransactionManagerLookup,這個類通知緩存不要參與JTA事務,自己管理事務。
-
IsolationLevel 設置更新分布式緩存的隔離級別,可選值包括:SERIALIZABLE, REPEATABLE_READ, READ_COMMITTED, READ_UNCOMMITTED, 和 NONE。 這里的隔離級別和數據庫的隔離級別有同樣的含義,對于大多數WEB應用程序來講通常設置為REPEATABLE_READ。
-
CacheMode 控制緩存如何被復制。可選值包括:REPL_SYNC 和REPL_ASYNC,確定改變是應該同步還是異步復制。使用同步復制,確保在請求完成之前傳播改變,同步復制相對來說會慢一些。
-
ClusterName 指定集群名稱。缺省的集群名稱是由當前的JBoss分區名稱加上"Tomcat-"前綴。所有的節點應該使用相同的集群名稱。
-
UseMarshalling 和InactiveOnStartup 屬性必須有相同的值,如果使用FIELD級別的會話復制,這兩個值必須為true。
-
ClusterConfig 配置底層的JGoups 堆棧。最重要的配置元素是廣播地址和端口號mcast_addr 和mcast_port,詳細配置請參見JGroups配置。
-
LockAcquisitionTimeout 設置獲取鎖的最大超時值,缺省值為15000。
-
UseReplQueue 使用異步復制時是否啟動復制隊列,這允許多個更新一起執行從而提升性能。復制隊列屬性由 ReplQueueInterval 和ReplQueueMaxElements 屬性配置。
-
ReplQueueInterval 配置JBoss緩存處理復制隊列的時間間隔。
-
ReplQueueMaxElements: 配置復制隊列可以保存的最多的元素數目。
1.5.6. 在應用程序中啟用會話復制
要在你的WEB應用程序中啟用集群,必須在web.xml文件中聲明distributable。示例如下:
- web-app>
可以在jboss-web.xml文件中進一步配置會話復制,示例如下:
xml 代碼
- <jboss-web>
- <replication-config>
- <replication-trigger>SET_AND_NON_PRIMITIVE_GETreplication-trigger>
- <replication-granularity>SESSIONreplication-granularity>
- <replication-field-batch-mode>truereplication-field-batch-mode>
- replication-config>
- jboss-web>
replication-trigger 元素確定什么情況觸發一次會話復制,有四個選項:
-
SET: 使用此選項,一個會話只有在設置屬性時才被認為需要復制。如果你的應用總是需要改變會話的屬性,這個選項將是性能最優的。如果一個對象只是被檢索和修改,但是不需要改寫會話,這個對象的改變并不會造成會話復制。
-
SET_AND_GET: 使用此選項,任何屬性的獲取和設置都被認為需要復制。如果一個對象被檢索和修改,但是不需要改定會話,這個對象的改變將會被復制。這個選項有顯著的性能問題。
-
SET_AND_NON_PRIMITIVE_GET: 此選項類似于 SET_AND_GET,唯一的例外是只有非原始類型的檢索操作被認為需要復制。比如,HTTP會話請求可以從屬性中檢索一個非原始類型的對象實例并更改,如果我們沒有指定此選項,更改將不會被復制。這是缺省設置。
-
ACCESS: 使用此選項,只要會話被訪問都被認為需要復制。由于每個HTTP請求都會造成會話被訪問,所以每個請求都會導致會話復制。使用此選項,會話時間戳將在集群中同步。注意使用此選項會有顯著的性能問題。
replication-granularity 元素控制復制粒度,支持的選項包括:
-
SESSION: 基于會話的復制,只要會話發生改變,整個會話對象都會被序列化。
-
ATTRIBUTE: 基于屬性的復制,復制只在屬性被認為是臟的時候發生,比如lastAccessTime.。對于持有大量數據的會話,這個選項可以提升性能。
-
FIELD: 基于字段的復制,復制只在會話屬性包含的對象的字段發生變化時發生。
replication-field-batch-mode 表示是否需要在每個HTTP請求進行批量更新,缺省值為true。
如果你的會話通常比較小,SESSION選項比較適合,如果會話比較大,而且某些部分不是經常被訪問,ATTRIBUTE 選項比較適合,如果會話屬性包含大數據量的對象而且只有字段經常更改,FIELD 選項比較適合。
1.5.7. 使用FIELD級別的復制
FIELD-level replication only replicates modified data fields inside objects stored in the session. It could potentially drastically reduce the data traffic between clustered nodes, and hence improve the performance of the whole cluster. To use FIELD-level replication, you have to first prepare your Java class to indicate which fields are to be replicated. This is done via JDK 1.4 style annotations embedded in JavaDocs:
To annotate your POJO, we provide two annotations: @@org.jboss.web.tomcat.tc5.session.AopMarker and @@org.jboss.web.tomcat.tc5.session.InstanceAopMarker. When you annotate your class with AopMarker, you indicate that instances of this class will be used in FIELD-level replication. For exmaple,
/*
* My usual comments here first.
* @@org.jboss.web.tomcat.tc5.session.AopMarker
*/
public class Address
{
...
}
If you annotate it with InstanceAopMarker instead, then all of its sub-class will be automatically annotated as well. For example,
/*
*
* @@org.jboss.web.tomcat.tc5.session.InstanceOfAopMarker
*/
public class Person
{
...
}
then when you have a sub-class like
public class Student extends Person
{
...
}
there will be no need to annotate Student. It will be annotated automatically because it is a sub-class of Person.
However, since we only support JDK 1.4 style annotation (provided by JBoss Aop) now, you will need to perform a pre-processing step. You need to use the JBoss AOP pre-compiler annotationc and post-compiler aopc to process the above source code before and after they are compiled by the Java compiler. Here is an example on how to invoke those commands from command line.
$ annotationc [classpath] [source files or directories]
$ javac -cp [classpath] [source files or directories]
$ aopc [classpath] [class files or directories]
Please see the JBoss AOP documentation for the usage of the pre- and post-compiler. The JBoss AOP project also provides easy to use ANT tasks to help integrate those steps into your application build process. In the next AS release, JDK 5.0 annotation support will be provided for greater transparency. But for now, it is important that you perform the pre- and post-compilation steps for your source code.
Note
Or, you can see a complete example on how to build, deploy, and validate a FIELD-level replicated web application from this page: http://wiki.jboss.org/wiki/Wiki.jsp?page=Http_session_field_level_example. The example bundles the pre- and post-compile tools so you do not need to download JBoss AOP separately.
When you deploy the web application into JBoss AS, make sure that the following configurations are correct:
-
In the server's deploy/tc5-cluster.sar/META-INF/jboss-service.xml file, the inactiveOnStartup and useMarshalling attributes must both be true.
-
In the application's jboss-web.xml file, the replication-granularity attribute must be FIELD.
Finally, let's see an example on how to use FIELD-level replication on those data classes. Notice that there is no need to call session.setAttribute() after you make changes to the data object, and all changes to the fields are automatically replicated across the cluster.
<pre class="programlistin