009 和 6009,集群 Receiver 节点 tcpListenPort 端口分别配置为 5001 和 6001, Connector 节点端口分别配置为 8080 和 9090,AJPConnector 端口分别配置为 8009 和 9009, Connector 端口配置参照单主机多站点场景。
请注意两个 Tomcat 配置文件 Host 节点的域名 配置必须一样,Server.xml 中的 jvmRoute 名称必须和 worker.properties 中的 tomcat 实例名称 一致,不然无法实现 session_stricky。
Web.xml 配置 此配置说明当前 Web 工程处于分布式部署环境。
Web.xml 配置文件加上ltdistributable/gt节点, 如果不进行这个配置,每次访问页面 tomcat 都会产生一个新的 sessionid。
Tomcat
源码修改 如果使用 Tomcat5.0.28 ,需要修改以下两个类以修改 Tomcat 的 BUG 及增加未实现 java.io.Serializable 接口的类名日志输出。
org.apache.catalina.cluster.session.DeltaSessionFacade,让其实现 java.io.Serializable 接口。
org.apache.catalina.cluster.session.DeltaSession,将其 1262 行的内容从 throw new IllegalArgumentExceptionquotAttribute quotnamequot is not serializablequot 改为 throw new IllegalArgumentExceptionquotAttribute quotnamequot value:quotvalue.getClassquot is not serializablequot 第一个类未实现 java.io.Serializable 接口将导致以下异常发生:2010-07-27 08:26:15261 ERROR org.apache.catalina.cluster.session.DeltaManager - Unable to serialize delta requestjava.io.NotSerializableException: org.apache.catalina.cluster.session.DeltaSessionFacade at java.io.ObjectOutputStream.writeObject0ObjectOutputStream.java:1081 at java.io.ObjectOutputStream.defaultWriteFieldsObjectOutputStream.java:1375 at java.io.ObjectOutputStream.writeSerialDataObjectOutputStream.java:1347 at java.io.ObjectOutputStream.writeOrdinaryObjectObjectOutputStream.java:1290 at java.io.ObjectOutputStream.writeObject0ObjectOutputStream.java:1079 at java.io.ObjectOutputStream.writeObjectObjectOutputStream.java:302 at org.apache.catalina.cluster.session.DeltaRequestAttributeInfo.writeExternalDeltaRequest.java:300 at org.apache.catalina.cluster.session.DeltaRequest.writeExternalDeltaRequest.java:217 at org.apache.catalina.cluster.session.DeltaManager.unloadDeltaRequestDeltaManager.java:393 at org.apache.catalina.cluster.session.DeltaManager.requestCompletedDeltaManager.java:782 at org.apache.catalina.cluster.tcp.ReplicationValve.invokeReplicationValve.java:203 at org.apache.catalina.core.StandardValveContext.invokeNextStandardValveContext.java:102 at org.apache.catalina.valves.ErrorReportValve.invokeErrorReportValve.java:118 at org.apache.catalina.core.StandardValveContext.invokeNextStandardValveContext.java:102 at org.apache.catalina.core.StandardPipeline.invokeStandardPipeline.java:520 at org.apache.catalina.core.StandardEngineValve.invokeStandardEngineValve.java:109 at org.apache.catalina.core.StandardValveContext.invokeNextStandardValveContext.java:104 at org.apache.catalina.core.StandardPipeline.invokeStandardPipeline.java:520 at org.apache.catalina.core.ContainerBase.invokeContainerBase.java:929 at org.apache.coyote.tomcat5.CoyoteAdapter.serviceCoyoteAdapter.java:160 at org.apache.jk.server.JkCoyoteHandler.invokeJkCoyoteHandler.java:300 at org.apache.jk.common.HandlerRequest.invokeHandlerRequest.java:374 at org.apache.jk.common.ChannelSocket.invokeChannelSocket.java:743 修改第二个类时能将以下异常信息,提示哪些类未实现 java.io.Serializable 接口 修改前日志: 2010-07-27 08:41:10886 ERROR ERROR - Attribute msgSaveIdInSession is not serializable java.lang.IllegalArgumentException: Attribute msgSaveIdInSession is not serializable at org.apache.catalina.cluster.session.DeltaSession.setAttributeDeltaSession.java:1262 at org.apache.catalina.cluster.session.DeltaSession.setAttributeDeltaSession.java:1246 at org.apache.catalina.cluster.session.DeltaSessionFacade.setAttributeDeltaSessionFacade.java:131 at com.csmis.sys.msg.view.MsgDefine.getInstanceMsgDefine.java:50 at org.apache.
jsp.main.mainFrame_005fcs_
jsp._jspServicemainFrame_005fcs_
jsp.java:511 at org.apache.jasper.runtime.HttpJspBase.serviceHttpJspBase.java:94 at javax.servlet.http.HttpServlet.serviceHttpServlet.java:802修改后日志: 2010-07-27 08:48:22573 ERROR ERROR - Attribute msgSaveIdInSession value:class com.csmis.sys.msg.view.MsgDefine is not serializable java.lang.IllegalArgumentException: Attribute msgSaveIdInSession value:class com.csmis.sys.msg.view.MsgDefine is not serializable at org.apache.catalina.cluster.session.DeltaSession.setAttributeDeltaSession.java:1262 at org.apache.catalina.cluster.session.DeltaSession.setAttributeDeltaSession.java:1246 at org.apache.catalina.cluster.session.DeltaSessionFacade.setAttributeDeltaSessionFacade.java:131 at com.csmis.sys.msg.view.MsgDefine.getInstanceMsgDefine.java:50 at org.apache.
jsp.main.mainFrame 005fcs
jsp. jspServicemainFrame 005fcs
jsp.java:511原理解析 对于 WEB 应用集群的技术实现而言,最大的难点就是如何能在集群中的多个节点之间保持数据的一致性,会话(Session)信息是这些数据中最重要的一块。
要实现这一点,大体上有两种方式,一种是把所有 Session 数据放到一台服务器上或者数据库中,集群中的所有节点通过访问这台 Session 服务器来获取数据;另一种就是在集群中的所有节点间进行 Session 数据的同步拷贝,任何一个节点均保存了所有的 Session 数据。
两种方式都各有优点,第一种方式简单、易于实现,但是存在着 Session 服务器发生故障会导致全系统不能正常工作的风险;第二种方式可靠性更高,任一节点的故障不会对整个系统对客户访问的响应产生影响,但是技术实现上更复杂一些。
常见的平台或中间件如 microsoftasp.net 和 IBM WAS 都会提供对两种共享方式的支持,tomcat 也是这样,但是一般采用第二种方式。
下面对这里的配置项作详细解释,以下内容均是从网上转载,并非针对Tomcat 5.0,希望能带着批判的眼光阅读。
tomcat 集群各节点通过建立 tcp 链接来完成 Session 的拷贝,拷贝有同步和异步两种模式。
在同步模式下,对客户端的响应必须在 Session 拷贝到其他节点完成后进行;异步模式无需等待 Session 拷贝完成就可响应。
异步模式更高效,但是同步模式可靠性更高。
同步异步模式由 channelSendOptions 参数控制,默 批注 s1: Tomcat 5.0 不支持此参数认值是 8,为异步模式,4 是同步模式。
在异步模式下,可以通过加上拷贝确认(Acknowledge)来提高可靠性,此时 channelSendOptions 设为 10。
Manager 用来在节点间拷贝 Session,默认使用 DeltaManager,DeltaManager 采用的一种 all-to-all 的工作方式,即集群中的节点会把 Session数据向所有其他节点拷贝,而不管其他节点是否部署了当前应用。
当集群中的节点数量很多并且部署着不同应用时,可以使用 BackupManager,BackManager 仅向部署了当前应用的节点拷贝 Session。
但是到目前为止 BackupManager 并未经过大规模测试,可靠性不及 DeltaManager。
Channel 负责对 tomcat 集群的 IO 层进行配置。
Membership 用于发现集群 批注 s2: Tomcat5.0 无此元素中的其他节点,这里的 address 用的是组播地址(Multicast address,了解更多组播地址详情请参见http://zyycaesar.javaeye.com/admin/blogs/296501),使用同一个组播地址和端口的多个节点同属一个子集群, 因此通过自定义组播地址和端口就可将一个大的 tomcat 集群分成多个子集群。
Receiver 用于各个节点接收其他节点发送的数据,在默认配置下 tomcat 会从 4000-4100 间依次选取一个可用的端口进行接收,自定义配置时,如果多个 tomcat 节点在一台物理服务器上注意要使用不同的端口。
Sender 用于向其他节点发送数据,具体实现通过 Transport 配置,PooledParallelSender 是从 tcp 连接池中获取连接,可以实现并行发送,即集群中的多个节点可以同时向其他所有节点发送数据而互不影响。
Interceptor 有点类似下面将要解释的 Valve,起到一个阀门的作用,在数据到达目的节点前进行检测或其他操作,如 TcpFailureDetector 用于检测在数据的传输过程中是否发生了 tcp 错误。
关于 Channel 的编程模型,请参见http://tomcat.apache.org/tomcat-6.0-doc/api/org/apache/catalina/tribes/Channel.html。
Valve 用于在节点向客户端响应前进行检测或进行某些操作,ReplicationValve 就是用于用于检测当前的响应是否涉及 Session 数据的更新,如果是则启动 Session 拷贝操作, filter 用于过滤请求,如客户端对图片,css,js 的请求就不会涉及 Session,因此不需检测,默认状态下不进行过滤,监测所有的响应。
JvmRouteBinderValve 会在前端的 Apache mod_jk 发生错误时保证同一客户端的请求发送到集群的同一个节点,tomcat 官方文档并未解释如何实现这一点,而且笔者认为这一设置似乎并无多大实用性。
Deployer 用于集群的 farm 功能,监控应用中文件的更新,以保证集群中 批注 s3: Tomcat5.0 无此元素所有节点应用的一致性,如某个用户上传文件到集群中某个节点的应用程序目录下,Deployer 会监测到这一操作并把这一文件拷贝到集群中其他节点相同应用的对应目录下以保持所有应用的一致。
这是一个相当强大的功能,不过很遗憾,tomcat 集群目前并不能做到这一点,开发人员正在努力实现它,这里的配置只是预留了一个接口。
Listener 用于跟踪集群中节点发出和收到的数据,也有点类似 Valve 的功 批注 s4: Tomcat5.0 无此元素能。
在大体了解了 tomcat 集群实现模型后,就可以对集群作出更优化的配置了,tomcat 推荐了一套配置,使用了比 DeltaManager 更高效的 BackupManager,并且对 ReplicationValve 设置了请求过滤,注意在一台服务器部署多个节点时需要修改 Receiver 的侦听端口,另外,为了更高效的在节点间拷贝数据,所有tomcat 节点最好采用相同的配置 Tomcat6.0 的集群除了可以进行 Session 数据的拷贝,还可进行 Context 属性的拷贝,通过修改 context.xml 的 Context 配置可以实现,使用ltContextclassNamequotorg.apache.catalina.ha.context.ReplicatedContextquotdistributablequottruequot/gt属性。
存在的问题1. 在系统中使用 session 暂存数据时,如果被存的对象所属类未实现 java.io.Serializable 接 口时会出现错误2. 在系统中使用静态变量时变量中的数据不能同步, 导致不同页面中显示的内容不同, 如, 公共字典项中使用了静态变量用来缓存公共字典中的数据, 当公共字典中的项目发生变 化时,只有当前服务器上的静态变量进行了重置, 其它服务器上的静态变更仍保持原有 的值,此时会发生不同服务器上的数据不一致现象。
3. 系统中使用 application 级的变量时数据不能同步。
使用集群后系统中可能存在的问题1. 首页内容不能及时更新。
包括新闻、通知、安全天数、系统模板、系统标志等。
2. 公共字典中的项目更新后在其它界面中使用公共字典时不能显示最新值。
附录:JK 配置文件详解一、简介:每个 Tomcat worker 是一个服务于 web server、等待执行 servlet 的 Tomcat 实例。
例如我们经常使用像 Apache 之类的 web server 转发 sevlet 请求给位于其后面的一个 Tomcat 进程(也就是前面所说的 worke.
上一篇:
基于J2EE的Web开发
下一篇:
计算机实践报告论文