1.5.5 配置HTTP会话状态复制
在章节
5.3
中
,
“在
mod_jk
中配置工作节点”
,
我们涵盖了如何使用”会话粘贴”,以确保为了维持会话状态客户在一个会话上总是请求相同的服务节点。可是
,
它并不是完美的。随着时间的过去,在所有分布式节点上的负载可能是不平均,如果一个节点当掉
(
关闭了
)
,那么在它上面的所有会话数据就丢失了。一个更好和更可靠的办法就是在集群中的所有节点之间复制会话数据。这样,客户可以连接到任何服务节点上,并获得同样的会话数据。
jboss.cache:service=TomcatClusteringCache MBean
在
JBoss Tomcat
集群的
HTTP
负载平衡中使用
JBoss
缓存提供
HTTP
会话复制服务。该
MBean
已经在
deploy/tc5-cluster.sar/META-INF/jboss-service.xml
文件中定义。
注意:
在AS 4.0.4 CR2以前, HTTP会话缓存配置文件是deploy/tc5-cluster-service.xml文件. 更多的细细请见AS 4.0.3的文档
在AS 4.0.4 CR2以前, HTTP会话缓存配置文件是deploy/tc5-cluster-service.xml文件. 更多的细细请见AS 4.0.3的文档
下面是一个典型的deploy/tc5-cluster.sar/META-INF/jboss-service.xml 文件。在TomcatClusteringCache MBean中这个配置属性与部分 2, “JBossCache配置”非常相似。
<
mbean
code
="org.jboss.cache.aop.TreeCacheAop"
name ="jboss.cache:service=TomcatClusteringCache" >
< depends >jboss:service=Naming </ depends >
< depends >jboss:service=TransactionManager </ depends >
< depends >jboss.aop:service=AspectDeployer </ depends >
< attribute name ="TransactionManagerLookupClass" >
org.jboss.cache.BatchModeTransactionManagerLookup
</ attribute >
< attribute name ="IsolationLevel" >REPEATABLE_READ </ attribute >
< attribute name ="CacheMode" >REPL_ASYNC </ attribute >
< attribute name ="ClusterName" >
Tomcat-${jboss.partition.name:Cluster}
</ attribute >
< attribute name ="UseMarshalling" >false </ attribute >
< attribute name ="InactiveOnStartup" >false </ attribute >
< attribute name ="ClusterConfig" >
... ...
</ attribute >
< attribute name ="LockAcquisitionTimeout" >15000 </ attribute >
</ mbean >
name ="jboss.cache:service=TomcatClusteringCache" >
< depends >jboss:service=Naming </ depends >
< depends >jboss:service=TransactionManager </ depends >
< depends >jboss.aop:service=AspectDeployer </ depends >
< attribute name ="TransactionManagerLookupClass" >
org.jboss.cache.BatchModeTransactionManagerLookup
</ attribute >
< attribute name ="IsolationLevel" >REPEATABLE_READ </ attribute >
< attribute name ="CacheMode" >REPL_ASYNC </ attribute >
< attribute name ="ClusterName" >
Tomcat-${jboss.partition.name:Cluster}
</ attribute >
< attribute name ="UseMarshalling" >false </ attribute >
< attribute name ="InactiveOnStartup" >false </ attribute >
< attribute name ="ClusterConfig" >
... ...
</ attribute >
< attribute name ="LockAcquisitionTimeout" >15000 </ attribute >
</ mbean >
对于
TreeCache MBean
的详细配置见部分
2,
“
JBossCache
配置”。下面,我们将仅仅讨论与
HTTP
集群会话复制关联的几个属性。
•
TransactionManagerLookupClass
设置事务管理工厂。默认值是
org.jboss.cache.BatchModeTransactionManagerLookup.
。它通知缓存不要参与
JTA-specific
事务。代替
,
它的缓存管理自己的事务以支持细微的卵复制。
•
IsolationLevel
设置隔离级别为更新对于事务处理分布式缓存。有效的值有
SERIALIZABLE, REPEATABLE_READ, READ_COMMITTED, READ_UNCOMMITTED,
和
NONE.
这些隔离级别设定与在数据库上的隔离级别是相同的东西。默认隔离值
REPEATABLE_READ
对于大多数
web
应用程序是有意义的。
•
CacheMode
控制缓存的复制方式。有效值包括
REPL_SYNC
和
REPL_ASYNC,
来确定改变是同步的或者是异步的。使用同步复制确保改变在
web
请求完成之前传播到集群。然而
,
同步复制是非常慢的
.
对于异步方式
,
你必须应该启用
(enable)
并调整复制队列。
•
ClusterName
指定了缓存所服务的群集的名字。缺省的群集名是
"Tomcat-"
后面跟着当前的
JBoss
分区名。所有节点都应该使用相同的群集名。虽然会话复制能够和
JBoss
的其他群集服务共享同一通道(多点传送地址和端口),复制还是应该有自己的群集名。
•
UseMarshalling
和
InactiveOnStartup
属性必须有相同的值。如果需要使用
FIELD
级会话复制(请参考后面的内容),它们的值必须是
true
。否则,它们的缺省值是
false
。
•
ClusterConfig
配置底层的
JGroups
栈。最重要的配置元素是用于群集通讯的多点传送地址和端口,分别是
mcast_addr
和
mcast_port
。这些值对你的网络该很有用。请参考章节
1,
“
JGroups
配置”来获得更多信息。
•
LockAcquisitionTimeout
设置等待获得一个锁的最大时间,单位是毫秒。默认值是
15000.
•
UseReplQueue
确定当使用异步复制的时候是否激活复制队列。这允许若干缓存更新被绑定在一起提高性能。复制队列的性能由
ReplQueueInterval
和
ReplQueueMaxElements
的性能约束。
•
ReplQueueInterval
指定
JBoss Cache
在发送请求到复制队列之前的等待时间,单位是毫秒。
•
ReplQueueMaxElements:
指定
JBoss
缓存将发送一个更新之前,在复制队列里允许的元素的最大数量。
1.5.6 在你的应用程序中授权session复制
要在你的
web
应用程序中启用集群,你必须在
web.xml
描述符中声明
distributable
。这里有一个例子:
<?
xml
version
="1.0"
?>
< web-app [url]http://java.sun.com/xml/ns/j2ee[/url] ="http://java.sun.com/xml/ns/j2ee" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
[url]http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd[/url]"
version ="2.4" >
< distributable />
<!-- ... -->
</ web-app >
< web-app [url]http://java.sun.com/xml/ns/j2ee[/url] ="http://java.sun.com/xml/ns/j2ee" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
[url]http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd[/url]"
version ="2.4" >
< distributable />
<!-- ... -->
</ web-app >
你可以在
jboss-web.xml
文件中用
replication-config
元素进一步配置会话复制。这里有一个例子:
才
replication-trigger
元素决定用什么触发一个会话复制
(
或什么时候会话被认为是
dirty
的
)
。它有四个选项:
•
SET:
在这个选项下,只有在会话里设置了属性,会话才被认为是
dirty
。如果你的应用程序总把改变的写回到会话里,从性能角度来讲这个选项可能是最优化的。如果只从会话里取出一个对象而不把它写回到会话里,对这个对象的修改将不会被复制。
•
SET_AND_GET:
如使用这个策略,所有
get
或
set
的属性都会被标记为
ditry
。如果从会话里取出一个对象并修改它,但没有写回到这个会话里,这些修改也将被复制。这个选项对性能有比较大的影响。
•
SET_AND_NON_PRIMITIVE_GET:
这个策略和
SET_AND_GET
相似,除了只有非基本(
non-primitive
)
get
操作被当作
dirty
。例如,
http
会话请求可能从属性里取出一个非基本对象实例,然后修改了这个实例。如果我们没有指定非基本
get
应该考虑为
dirty
,这个修改就不会正确地被复制。这个选项是缺省值。
•
ACCESS:
这个选项表示
,
只要会话被访问,就把会话标记为
ditry
。因为在每个
HTTP
请求的过程中,会话都会被访问,所以会话每次都会被复制。会话实例里的时间戳也会相应地更新。由于复制并没有包括时间戳,其他群集节点的时间戳可能不会被更新。如果
HTTP
请求没有取出或修改任何会话属性,其他节点的会话就可能会先于活动节点过期。当设置了这个选项,会话的时间戳将在所有群集节点中同步。注意采用这个选项对性能影响很大,需要小心行事。
replication-granularity
元素控制复制单位的大小。支持的选项包括:
•
SESSION:
复制基于每一会话实例。只要当调用
snapshot manager
时它被认为有修改,整个会话对象都将串行化。
•
ATTRIBUTE:
复制仅针对于会话里的
ditry
属性加上某些会话数据,如
lastAccessTime
。对于承载大量数据的会话,这个选项可以提高复制性能。
•
FIELD:
复制仅针对于会话属性对象里的数据字段(后面会有更多内容)。
replication-field-batch-mode
指出你是否在每个
HTTP
请求之间进行批量更新。它的缺省值是
true
。
如果你的会话通常很小,使用
SESSION
选项是更好的策略。如果你的会话更大些而且某些部分并不常被访问,
ATTRIBUTE
方式的复制就会更有效。如果你的应用程序在会话属性里拥有非常大的数据对象,而且只有这些对象里的某些字段被经常修改,采用
FIELD
策略将是最佳选择。在后面的内容里,让我们讨论一下怎样使用
FIELD
级的复制。
1.5.7 使用字段级(FIELD)级别复制
字段级复制只复制存储在会话里的对象内部的被修改的数据字段。它能够极大地减少群集节点之间的数据通信,也因此提高了整个群集系统的性能。为了使用字段级复制,你首先得用
Java
类来指出哪个字段要被复制。它是通过在
JavaDocs
嵌入的
JDK 1.4
风格的注解(
annotations
)来完成的:
为了注解(
annotate
)你的
POJO
,我们提供两个注解方式:
@@org.jboss.web.tomcat.tc5.session.AopMarker
和
@@org.jboss.web.tomcat.tc5.session.InstanceAopMarker.
当你用
AopMarker
注解你的类时,你可以指出这个类的实例字段级复制。例如:
/*
* My usual comments here first.
* @@org.jboss.web.tomcat.tc5.session.AopMarker
*/
public class Address
{
...
}
* My usual comments here first.
* @@org.jboss.web.tomcat.tc5.session.AopMarker
*/
public class Address
{
...
}
如果你用
InstanceAopMarker
注解类时,它所有的子类都将自动被注解。例如
,
/*
*
* @@org.jboss.web.tomcat.tc5.session.InstanceOfAopMarker
*/
public class Person
{
...
}
*
* @@org.jboss.web.tomcat.tc5.session.InstanceOfAopMarker
*/
public class Person
{
...
}
当你有一个子类,如:
public
class Student
extends Person
{
...
}
{
...
}
你不需要注解
Student
。因为它是
Person
的子类,所以它将自动被注解。
然而,既然目前我们只支持
JDK 1.4
风格的注解(由
JBoss Aop
提供),你将需要执行一个预处理步骤。在
Java
编译器编译之前和之后,你需要用
JBoss AOP pre-compiler annotationc
和
post-compiler aopc
来处理上面的源码。这里是一个怎样从命令行调用这些命令的例子。
$ annotationc [classpath] [source files or directories]
$ javac -cp [classpath] [source files or directories]
$ aopc [classpath] [class files or directories]
$ javac -cp [classpath] [source files or directories]
$ aopc [classpath] [class files or directories]
请参考
JBoss AOP
文档关于怎样使用
pre-
和
post-compiler
。
JBoss AOP
项目也提供使用
ANT
来把上述步骤集成在应用程序的
build
过程中的简单方法。下一个
AS
发布版本将提供对
JDK 5.0
注解的更透明的支持。但是现在,你还得用
pre-
和
post-compiler
来编译你的源码。
注意:
或者,你也能够在[url]http://wiki.jboss.org/wiki/Wiki.jsp?page=Http_session_field_level_example[/url]里看到一个怎样构建(build),部署(deploy),和验证(validate)采用字段级复制的 web 应用程序的完整例子。这个例子捆绑了 pre- 和 post-compile 工具,所以你不需要再下载单独的 JBoss AOP 了。
或者,你也能够在[url]http://wiki.jboss.org/wiki/Wiki.jsp?page=Http_session_field_level_example[/url]里看到一个怎样构建(build),部署(deploy),和验证(validate)采用字段级复制的 web 应用程序的完整例子。这个例子捆绑了 pre- 和 post-compile 工具,所以你不需要再下载单独的 JBoss AOP 了。
当你把
web
应用程序部署到
JBoss AS
时,请确保下面的配置是正确的:
•
在服务器的
deploy/tc5-cluster.sar/META-INF/jboss-service.xml
文件里,
inactiveOnStartup
和
useMarshalling
属性必须都为
true
。
•
在应用程序的
jboss-web.xml
文件里,
replication-granularity
属性必须为
FIELD
。
最后,让我们看一个怎样在哪些数据类上使用字段级(
FIELD-level
)复制的例子。请注意你不需要在修改数据对象(
data object
)后调用
session.setAttribute()
,对字段的所有修改都自动跨群集地被复制了。
// Do
this only once. So
this can be in init(), e.g.
if(firstTime)
{
Person joe = new Person( "Joe", 40); Person mary = new Person( "Mary", 30); Address addr = new Address(); addr.setZip(94086);
joe.setAddress(addr);
mary.setAddress(addr); // joe and mary share the same address!
session.setAttribute( "joe", joe); // that's it.
session.setAttribute( "mary", mary); // that's it.
}
Person mary = (Person)session.getAttribute( "mary");
mary.getAddress().setZip(95123); // this will update and replicate the zip code.
if(firstTime)
{
Person joe = new Person( "Joe", 40); Person mary = new Person( "Mary", 30); Address addr = new Address(); addr.setZip(94086);
joe.setAddress(addr);
mary.setAddress(addr); // joe and mary share the same address!
session.setAttribute( "joe", joe); // that's it.
session.setAttribute( "mary", mary); // that's it.
}
Person mary = (Person)session.getAttribute( "mary");
mary.getAddress().setZip(95123); // this will update and replicate the zip code.
除了简单的对象(
plain objects
),你还可以使用那些对象的常规
Java
集合(
Java collection
)作为会话属性。
JBoss cache
会自动地判断怎样处理这些集合和复制它们的成员对象里的字段的变更。
1.5.8 监控session复制
如果你已经部署和访问了你的应用程序,你可以使用
jboss.cache:service=TomcatClusteringCache MBean
和调用
printDetails
操作。你应该看到下面的输出结果。
/JSESSION
/quote
/FB04767C454BAB3B2E462A27CB571330
VERSION: 6
FB04767C454BAB3B2E462A27CB571330:
org.jboss.invocation.MarshalledValue@1f13a81c
/AxCI8Ovt5VQTfNyYy9Bomw** VERSION: 4
AxCI8Ovt5VQTfNyYy9Bomw**: org.jboss.invocation.MarshalledValue@e076e4c8
/quote
/FB04767C454BAB3B2E462A27CB571330
VERSION: 6
FB04767C454BAB3B2E462A27CB571330:
org.jboss.invocation.MarshalledValue@1f13a81c
/AxCI8Ovt5VQTfNyYy9Bomw** VERSION: 4
AxCI8Ovt5VQTfNyYy9Bomw**: org.jboss.invocation.MarshalledValue@e076e4c8
这个输出结果展示了在一个叫
quote
应用程序里的两个独立的
web
会话,它们通过
JBossCache
来共享。这个例子使用了
session
的
replication-granularity
。如果使用了
attribute
级的复制,应该可以看到展示每个被复制的会话属性的其他条目。在两种情况下,被复制的值都存储在一个不透明的
MarshelledValue
容器里。目前还没有任何工具可以让你查看这些被复制的会话值。如果你没有看到任何输出,要么是应用程序没有正确地标记为
distributable
,要么就是你根本没有访问把值写入
HTTP
会话的应用程序。
org.jboss.cache
和
org.jboss.web
日志类别提供了可用于调试目的对会话复制的其他视角。
1.5.9 使用单点登录(Single Sign On)
JBoss
支持群集的单点登录(
single sign-on
),允许用户在一个
JBoss
服务器上验证应用程序,然后被在同一个主机或群集里的其他节点里的被部署在同一个虚拟主机上的所有应用程序识别。
HTTP
会话复制服务处理复制验证(
Authentication replication
)。虽然会话复制不需要显性地为这个应用程序启用,但
tc5-cluster-service.xml
文件必须被部署。
为了启用单点登录,你必须在
tomcat server.xml
文件的
Host
元素里加入
ClusteredSingleSignOn
开关(
valve
)。这个开关(
valve
)的配置如下:
<
Valve
className
="org.jboss.web.tomcat.tc5.sso.ClusteredSingleSignOn"
/>
本文转自xudayu 51CTO博客,原文链接:http://blog.51cto.com/xudayu/67634,如需转载请自行联系原作者