- 浏览: 85182 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
July01:
推荐用StratoIO打印控件,支持网页、URL、图片、PD、 ...
[转]网页打印问题 -
agh_alan:
sssssssssssssssssssssssssssssss ...
[转]网页打印问题 -
vieri122:
请问 抓包数据如何让中文数据不是乱码?
使用 Eclipse 中的 TCP/IP Monitor -
shingo7:
多谢整理看了后帮助很大
tomcat5集群中的SESSON复制 -
huyiho0311:
...
CSS样式使用优先级判断
Tomcat 5服务器为集群和SESSION复制提供了集成的支持。本系列的第一篇文章将为大家提供SESSION持久性以及TOMCAT集群中SESSION复制的内在工作机制一个概要认识。我将会讨论SESSION复制在TOMCAT5中是怎样进行的以及跨越多集群节点的SESSION持久性的复制机制。在第2部分,我会详细讨论一个带有SESSION复制功能的TOMCAT集群的安装例子,并且比较不同的复制情形。
集群
传统独立服务器(非集群的)不提供任何失效无缝转移以及负载平衡能力。当服务器失败的时候,就无法获取整个网站的内容,除非服务器被重新唤起。由于服务器失效,任何存储在服务器内存中的SESSION都会丢失,用户必须重新登陆并且输入所有由于服务器失效丢失的数据。
不同的是,作为集群一部分的服务器则提供了可测性以及失效无缝转移能力。一个集群就是一组同步运行并且协同工作,能提供高可靠性,高稳定性以及高可测性的多服务器例程。服务端集群对客户端表现出来似乎就是一个单独的服务器例程。从客户端的视角来看,集群的客户端和单独的服务器没多大不同,但是他们通过提供实效无缝转移和SESSION复制做到了不间断服务以及SESSION数据持久性。
集群中的服务器通讯
集群中的应用程序服务器通过诸如IP多点传送(IP multicast)和IP sockets这样的技术和其他服务器共享信息
●IP多点传送:主要用于1对多的服务器通讯,通过广播服务和 heartbeats消息的可用来显示服务器的有效
●IP sockets:主要用于在集群的服务器例程中进行P2P服务器通讯
使用IP多点传送进行一对多通讯
TOMCAT服务器使用IP多点传送在集群中的服务器例程间进行一对多的通讯,IP多点传送是一种能够让多服务器向指定IP地址和端口号进行订阅并且监听消息的广播技术(多点传送IP地址范围从224.0.0.0 到239.255.255.255)。在集群中的每个服务器都使用多点传送广播特定的 heartbeat消息,通过监视这些 heartbeat消息,在集群中的服务器例程判断什么时候服务器例程失效。在服务器通讯中使用IP多点传送的一个缺点是他不能保证这些消息被确实接收到了。例如,一个应用持续的本地多点传送缓存满了,就不能写入新的多点传送消息,等消息过了之后该应用程序就没有被通知到。
使用IP Sockets进行服务器通讯
IP sockets 同样也通过了一套在集群中的服务器间进行发送消息和数据的机制。服务器例程使用IP sockets 在集群节点间进行HTTP SESSION状态的复制。正确的SOKET配制对于集群的性能是至关重要的,基于SOCKET的通讯的效率取决于SOCKET的实现类别(例如:系统使用本地的或者纯JAVA SOCKET读取器实现),如果服务器使用纯JAVA SOCKET读取器则要看服务器例程是否注册使用了足够的SOCKET读取器线程。
如果想要有最佳的SOCKET性能,系统应该注册使用本地的SOCEKT而不是纯JAVA实现。这是因为相对于基于JAVA的SOCKET实现,本地SOCKET消耗更少的系统资源。虽然 SOCKET读取器的JAVA实现是P2P通信中一种可靠而且可移动的方法,可是他不能为集群中的重型SOCKET使用提供最好的性能。当判断从 SOCKET是否有数据读取的时候本地SOCKET读取器使用了更有效率的方法。使用本地SOCKET读取器实现,读取器线程不需要去统计静止的 SOCKET:他们仅仅为活动的SOCKET服务,并且在一个给定的SOCKET开始活跃起来时他们可以立刻捕捉到。而使用纯JAVA SOCKET读取器,线程必须动态的统计所有打开的SOCKET,判断他们是否包含可读取的数据。换句话说,SOCKET读取器总是忙于统计 SOCKET,即使这些SOCKET没有数据可读。这些本不应该的系统开销降低了性能。
TOMCAT 5中的集群
虽然在TOMCAT5的早些版本中也有集群的功能,但是在稍后的版本中(5。0。19或者更高),集群变的更加模块组件化。在 server.xml 中集群元素已经被重构,这样我们可以替换集群的不同部分而不会影响其他元素。例如,当前配置中把成员服务设置为多点传送发现。这里可以轻易地把成员服务修改替换为使用TCP或者 Unicast ,而不会改变集类逻辑的其他部分。
其他一些集群元素,例如SESSION管理器,复制发送端,复制接受端也可以被自定义的实现取代而不影响集群配置的其他部分。同样,在TOMCAT集群中的任何服务器组件可以使用集类API向集群中的所有成员发送消息。
SESSION复制
服务器集群通常操纵两种SESSION: sticky sessions和 replicated sessions 。sticky sessions就是存在单机服务器中的接受网络请求的SESSION,其他集群成员对该服务器的SESSION状态完全不清楚,如果存有SESSION 的服务器失败的话,用户必须再次登陆网站,重新输入所有存储在SESSION中的数据。
另一种SESSION类型是,在一台服务器中SESSION状态被复制到集群中的其他所有服务器上,无论何时,只要SESSION 被改变,SESSION数据都要重新被复制。这就是 replicated session 。 sticky 和 replicated sessions都有他们的优缺点, Sticky sessions简单而又容易操作,因为我们不必复制任何SESSION数据到其他服务器上。这样就会减少系统消耗,提高性能。但是如果服务器失败,所有存储在该服务器内存中的SESSION数据也同样会消失。如果SESSION数据没有被复制到其他服务器,这些SESSION就完全丢失了。当我们在进行一个查询事务当中的时候,丢失所有已经输入的数据,就会导致很多问题。
为了支持 JSP HTTP session 状态的自动失效无缝转移,TOMCAT服务器复制了在内存中的SESSION状态。这是通过复制存储在一台服务器上的SESSION数据到集群中其他成员上防止数据丢失以及允许失效无缝转移。
对象的状态管理
通过在服务器上的保存状态可以区分出4种对象:
●无状态:一个无状态对象在调用的时候不会在内存中保存任何状态,因为客户端和服务器端没必要保存任何有关对方的信息。在这种情况下,客户端会在每次请求服务器时都会发送数据给服务器。SESSION状态被在客户端和服务器端来回发送。这种方法不总是可行和理想的,特别是当传输的数据比较大或者一些安全信息我们不想保存在客户端的时候;
●会话:一个会话对象在一个SESSION中只被用于特定的某个客户端。在SESSION中,他可以为所有来自该客户端的请求服务,并且仅仅是这个客户端的请求。贯穿一个SESSION,两个请求间的状态信息必须保存。会话服务通常在内存中保存短暂的状态,当在服务器失败的时候可能会丢失。SESSION状态通常被保存在请求间的服务器的内存中。为了清空内存,SESSION状态也可以被从内存中释放(就像在一个对象CACHE)。在该对象中,性能和可量测性都有待提高,因为更新并不是被单独的写到磁盘上,并且服务器失败的时候数据也没办法抢救。
●缓存:缓存对象在内存中保存状态,并且使用这个去处理从多客户端来的请求。缓存服务的实现可以扩展到他们把缓存的是数据备份保存在后端存储器中(通常是一个关系数据库)。
●独立的:一个独立的对象在一个时间内只活跃在集群中的一台服务器上,处理来自多客户端的请求。他通常由那些私有的,持久的,在内存中缓寸的数据支持。他同样也在内存中保持短暂状态,在服务器失败的时候要重建或者丢失。当失败的时候,独立对象必须在同一个服务器上重起或者移植到另一台服务器上。
(来源: "Using WebLogic Server Clusters")
SESSION复制的设计考虑事项
网络考虑事项
把集群的多点传送地址和其他应用程序隔离是至关重要的。我们不希望集群配置或者网络布局干扰到多点传送服务器通信。和其他应用程序共享集群多点传送地址将迫使集群的服务器例程处理不应该的消息,消耗系统内存。共享多点传送地址可能也会使IP多点传送缓冲过载,延迟服务器 heartbeat 消息传输。这样的延迟可能导致一个服务器例程被标识为死亡,仅仅因为他的 heartbeat 消息没有被及时接收。
编程考虑事项
除了上面提到的网络相关因素,还有些和我们写 J2EE 网络应用程序有关的设计考虑也会影响SESSION复制。以下列出了一些编程方面的考虑:
●SESSION数据必须被序列化:为了支持HTTP session 状态的内存内复制,所有的 servlet 和 JSP session 数据必须被序列化,对象中的每个域都必须被序列化,这样对象被可靠的序列化。
●把应用程序设计为幂等的:幂等的的意思就是一个操做不会修改状态信息,并且每次操作的时候都返回同样的结果(换句话说就是:做多次和做一次的效果是一样的),通常,WEB请求,特别是 HTML forms 都被发送多次(当用户点击发送按纽两次,重载页面多次),导致多次HTTP请求。设计SERVLET和其他WEB对象为幂等的,可以容忍多次请求。详细可以去参考设计模式“Synchronized Token ”和“Idempotent Receiver ”关于怎样设计幂等的的应用程序。
●在BUSINESS层存储状态:会话状态应该使用有状态的SESSION BEANS存储在EJB层,而不是存储在WEB层的HttpSession。因为企业应用程序要支持各种类型客户端(WEB客户端,JAVA应用程序,其他EJB),存储数据在WEB层会导致在客户端的双数据存储。因此,有状态的SESSION BEAN在这些情况下就被用于存储SESSION状态。无状态的SESSION BEAN要为每次的调用重构造会话状态。这些状态可能必须从数据库中恢复的数据中重编译。这些缺点失去了使用无状态SESSION BEAN去提高性能和可测量性的目的,严重的减低了性能。
●序列化系统消耗:序列化SESSION数据在复制SESSION状态的时候回会些系统消耗。随着序列化对象大小的增长消耗也越多。最好是保持SE
实践中整理出tomcat集群和负载均衡
(一)环境说明
(1)服务器有4台,一台安装apache,三台安装tomcat
(2)apache2.0.55、tomcat5.5.15、jk2.0.4、jdk1.5.6或jdk1.4.2
(3)ip配置,一台安装apache的ip为192.168.0.88,三台安装tomcat的服务器ip分别为192.168.0.1/2/4
(二)安装过程
(1)在三台要安装tomcat的服务器上先安装jdk
(2)配置jdk的安装路径,在环境变量path中加入jdk的bin路径,新建环境变量JAVA_HOME指向jdk的安装路径
(3)在三台要安装tomcat的服务器上分别安装tomcat,调试三个tomcat到能够正常启动
(4)tomcat的默认WEB服务端口是8080,默认的模式是单独服务,我的三个tomcat的WEB服务端口修改为7080/8888/9999
修改位置为tomcat的安装目录下的conf/server.xml
修改前的配置为
<Connector port="8080" maxHttpHeaderSize="8192"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" redirectPort="8443" acceptCount="100"
connectionTimeout="20000" disableUploadTimeout="true" />
修改后的配置为
<Connector port="7080" maxHttpHeaderSize="8192"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" redirectPort="8443" acceptCount="100"
connectionTimeout="20000" disableUploadTimeout="true" />
依次修改每个tomcat的监听端口(7080/8888/9999)
(5)分别测试每个tomcat的启动是否正常
http://192.168.0.1:7080
http://192.168.0.2:8888
http://192.168.0.4:9999
(三)负载均衡配置过程
(1)在那台要安装apache的服务器上安装apache2.0.55,我的安装路径为默认C:\Program Files\Apache Group\Apache2
(2)安装后测试apache能否正常启动,调试到能够正常启动http://192.168.0.88
(3)下载jk2.0.4后解压缩文件
(4)将解压缩后的目录中的modules目录中的mod_jk2.so文件复制到apache的安装目录下的modules目录中,我的为C:\Program Files\Apache Group\Apache2\modules
(5)修改apache的安装目录中的conf目录的配置文件httpd.conf,在文件中加LoadModule模块配置信息的最后加上一句LoadModule jk2_module modules/mod_jk2.so
(6)分别修改三个tomcat的配置文件conf/server.xml,修改内容如下
修改前
<!-- An Engine represents the entry point (within Catalina) that processes
every request. The Engine implementation for Tomcat stand alone
analyzes the HTTP headers included with the request, and passes them
on to the appropriate Host (virtual host). -->
<!-- You should set jvmRoute to support load-balancing via AJP ie :
<Engine name="Standalone" defaultHost="localhost" jvmRoute="jvm1">
-->
<!-- Define the top level container in our container hierarchy -->
<Engine name="Catalina" defaultHost="localhost">
修改后
<!-- An Engine represents the entry point (within Catalina) that processes
every request. The Engine implementation for Tomcat stand alone
analyzes the HTTP headers included with the request, and passes them
on to the appropriate Host (virtual host). -->
<!-- You should set jvmRoute to support load-balancing via AJP ie :-->
<Engine name="Standalone" defaultHost="localhost" jvmRoute="tomcat1">
<!-- Define the top level container in our container hierarchy
<Engine name="Catalina" defaultHost="localhost">
-->
将其中的jvmRoute="jvm1"分别修改为jvmRoute="tomcat1"和jvmRoute="tomcat2"和jvmRoute="tomcat3"
(7)然后重启三个tomcat,调试能够正常启动。
(8)在apache的安装目录中的conf目录下创建文件workers2.propertie,写入文件内容如下
# fine the communication channel
[channel.socket:192.168.0.1:8009]
info=Ajp13 forwarding over socket
#配置第一个服务器
tomcatId=tomcat1 #要和tomcat的配置文件server.xml中的jvmRoute="tomcat1"名称一致
debug=0
lb_factor=1 #负载平衡因子,数字越大请求被分配的几率越高
# Define the communication channel
[channel.socket:192.168.0.2:8009]
info=Ajp13 forwarding over socket
tomcatId=tomcat2
debug=0
lb_factor=1
# Define the communication channel
[channel.socket:192.168.0.4:8009]
info=Ajp13 forwarding over socket
tomcatId=tomcat3
debug=0
lb_factor=1
[status:]
info=Status worker, displays runtime information.
[uri:/jkstatus.jsp]
info=Display status information and checks the config file for changes.
group=status:
[uri:/*]
info=Map the whole webapp
debug=0
(9)在三个tomcat的安装目录中的webapps建立相同的应用,我和应用目录名为TomcatDemo,在三个应用目录中建立相同 WEB-INF目录和页面index.jsp,index.jsp的页面内容如下
<%@ page contentType="text/html; charset=GBK" %>
<%@ page import="java.util.*" %>
<html><head><title>Cluster App Test</title></head>
<body>
Server Info:
<%
out.println(request.getLocalAddr() + " : " + request.getLocalPort()+"<br>");%>
<%
out.println("<br> ID " + session.getId()+"<br>");
// 如果有新的 Session 属性设置
String dataName = request.getParameter("dataName");
if (dataName != null && dataName.length() > 0) {
String dataValue = request.getParameter("dataValue");
session.setAttribute(dataName, dataValue);
}
out.print("<b>Session 列表</b>");
Enumeration e = session.getAttributeNames();
while (e.hasMoreElements()) {
String name = (String)e.nextElement();
String value = session.getAttribute(name).toString();
out.println( name + " = " + value+"<br>");
System.out.println( name + " = " + value);
}
%>
<form action="index.jsp" method="POST">
名称:<input type=text size=20 name="dataName">
<br>
值:<input type=text size=20 name="dataValue">
<br>
<input type=submit>
</form>
</body>
</html>
(10)重启apache服务器和三个tomcat服务器,到此负载 均衡已配置完成。测试负载均衡先测试apache,访问http://192.168.0.88/jkstatus.jsp
能否正常访问,并查询其中的内容,有三个tomcat的相关配置信息和负载说明,访问http://192.168.0.88/TomcatDemo/index.jsp看能够运行,
能运行,则已建立负载均衡。
(四)tomcat集群配置
(1)负载均衡配置的条件下配置tomcat集群
(2)分别修改三个tomcat的配置文件conf/server.xml,修改内容如下
修改前
<!--
<Cluster className="org.apache.catalina.cluster.tcp.SimpleTcpCluster"
managerClassName="org.apache.catalina.cluster.session.DeltaManager"
expireSessionsOnShutdown="false"
useDirtyFlag="true"
notifyListenersOnReplication="true">
<Membership
className="org.apache.catalina.cluster.mcast.McastService"
mcastAddr="228.0.0.4"
mcastPort="45564"
mcastFrequency="500"
mcastDropTime="3000"/>
<Receiver
className="org.apache.catalina.cluster.tcp.ReplicationListener"
tcpListenAddress="auto"
tcpListenPort="4001"
tcpSelectorTimeout="100"
tcpThreadCount="6"/>
<Sender
className="org.apache.catalina.cluster.tcp.ReplicationTransmitter"
replicationMode="pooled"
ackTimeout="5000"/>
<Valve className="org.apache.catalina.cluster.tcp.ReplicationValve"
filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;"/>
<Deployer className="org.apache.catalina.cluster.deploy.FarmWarDeployer"
tempDir="/tmp/war-temp/"
deployDir="/tmp/war-deploy/"
watchDir="/tmp/war-listen/"
watchEnabled="false"/>
<ClusterListener className="org.apache.catalina.cluster.session.ClusterSessionListener"/>
</Cluster>
-->
修改后
<!-- modify by whh -->
<Cluster className="org.apache.catalina.cluster.tcp.SimpleTcpCluster"
managerClassName="org.apache.catalina.cluster.session.DeltaManager"
expireSessionsOnShutdown="false"
useDirtyFlag="true"
notifyListenersOnReplication="true">
<Membership
className="org.apache.catalina.cluster.mcast.McastService"
mcastAddr="228.0.0.4"
mcastPort="45564"
mcastFrequency="500"
mcastDropTime="3000"/>
<Receiver
className="org.apache.catalina.cluster.tcp.ReplicationListener"
tcpListenAddress="auto"
tcpListenPort="4001"
tcpSelectorTimeout="100"
tcpThreadCount="6"/>
<Sender
className="org.apache.catalina.cluster.tcp.ReplicationTransmitter"
replicationMode="pooled"
ackTimeout="5000"/>
<Valve className="org.apache.catalina.cluster.tcp.ReplicationValve"
filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;"/>
<Deployer className="org.apache.catalina.cluster.deploy.FarmWarDeployer"
tempDir="/tmp/war-temp/"
deployDir="/tmp/war-deploy/"
watchDir="/tmp/war-listen/"
watchEnabled="false"/>
<ClusterListener className="org.apache.catalina.cluster.session.ClusterSessionListener"/>
</Cluster>
<!-- modify by whh -->
将集群配置选项的注释放开即可,如上。
(3)重启三个tomcat。到此tomcat的集群已配置完成。
(五)应用配置
对于要进行负载和集群的的tomcat目录下的webapps中的应用中的WEB-INF中的web.xml文件要添加如下一句配置
<distributable/>
配置前
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="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 http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">
<display-name>TomcatDemo</display-name>
</web-app>
配置后
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="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 http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">
<display-name>TomcatDemo</display-name>
<distributable/>
</web-app>
问:tomcat集群是怎么处理session的阿
答:在tomcat做集群之后,每个tomcat之间自动根据tomcat的配置文件中的参数进行session复制,
对于一个客户端对说,只要是同一个IP,那它每次上传的sessionID就是一样的,
集群
传统独立服务器(非集群的)不提供任何失效无缝转移以及负载平衡能力。当服务器失败的时候,就无法获取整个网站的内容,除非服务器被重新唤起。由于服务器失效,任何存储在服务器内存中的SESSION都会丢失,用户必须重新登陆并且输入所有由于服务器失效丢失的数据。
不同的是,作为集群一部分的服务器则提供了可测性以及失效无缝转移能力。一个集群就是一组同步运行并且协同工作,能提供高可靠性,高稳定性以及高可测性的多服务器例程。服务端集群对客户端表现出来似乎就是一个单独的服务器例程。从客户端的视角来看,集群的客户端和单独的服务器没多大不同,但是他们通过提供实效无缝转移和SESSION复制做到了不间断服务以及SESSION数据持久性。
集群中的服务器通讯
集群中的应用程序服务器通过诸如IP多点传送(IP multicast)和IP sockets这样的技术和其他服务器共享信息
●IP多点传送:主要用于1对多的服务器通讯,通过广播服务和 heartbeats消息的可用来显示服务器的有效
●IP sockets:主要用于在集群的服务器例程中进行P2P服务器通讯
使用IP多点传送进行一对多通讯
TOMCAT服务器使用IP多点传送在集群中的服务器例程间进行一对多的通讯,IP多点传送是一种能够让多服务器向指定IP地址和端口号进行订阅并且监听消息的广播技术(多点传送IP地址范围从224.0.0.0 到239.255.255.255)。在集群中的每个服务器都使用多点传送广播特定的 heartbeat消息,通过监视这些 heartbeat消息,在集群中的服务器例程判断什么时候服务器例程失效。在服务器通讯中使用IP多点传送的一个缺点是他不能保证这些消息被确实接收到了。例如,一个应用持续的本地多点传送缓存满了,就不能写入新的多点传送消息,等消息过了之后该应用程序就没有被通知到。
使用IP Sockets进行服务器通讯
IP sockets 同样也通过了一套在集群中的服务器间进行发送消息和数据的机制。服务器例程使用IP sockets 在集群节点间进行HTTP SESSION状态的复制。正确的SOKET配制对于集群的性能是至关重要的,基于SOCKET的通讯的效率取决于SOCKET的实现类别(例如:系统使用本地的或者纯JAVA SOCKET读取器实现),如果服务器使用纯JAVA SOCKET读取器则要看服务器例程是否注册使用了足够的SOCKET读取器线程。
如果想要有最佳的SOCKET性能,系统应该注册使用本地的SOCEKT而不是纯JAVA实现。这是因为相对于基于JAVA的SOCKET实现,本地SOCKET消耗更少的系统资源。虽然 SOCKET读取器的JAVA实现是P2P通信中一种可靠而且可移动的方法,可是他不能为集群中的重型SOCKET使用提供最好的性能。当判断从 SOCKET是否有数据读取的时候本地SOCKET读取器使用了更有效率的方法。使用本地SOCKET读取器实现,读取器线程不需要去统计静止的 SOCKET:他们仅仅为活动的SOCKET服务,并且在一个给定的SOCKET开始活跃起来时他们可以立刻捕捉到。而使用纯JAVA SOCKET读取器,线程必须动态的统计所有打开的SOCKET,判断他们是否包含可读取的数据。换句话说,SOCKET读取器总是忙于统计 SOCKET,即使这些SOCKET没有数据可读。这些本不应该的系统开销降低了性能。
TOMCAT 5中的集群
虽然在TOMCAT5的早些版本中也有集群的功能,但是在稍后的版本中(5。0。19或者更高),集群变的更加模块组件化。在 server.xml 中集群元素已经被重构,这样我们可以替换集群的不同部分而不会影响其他元素。例如,当前配置中把成员服务设置为多点传送发现。这里可以轻易地把成员服务修改替换为使用TCP或者 Unicast ,而不会改变集类逻辑的其他部分。
其他一些集群元素,例如SESSION管理器,复制发送端,复制接受端也可以被自定义的实现取代而不影响集群配置的其他部分。同样,在TOMCAT集群中的任何服务器组件可以使用集类API向集群中的所有成员发送消息。
SESSION复制
服务器集群通常操纵两种SESSION: sticky sessions和 replicated sessions 。sticky sessions就是存在单机服务器中的接受网络请求的SESSION,其他集群成员对该服务器的SESSION状态完全不清楚,如果存有SESSION 的服务器失败的话,用户必须再次登陆网站,重新输入所有存储在SESSION中的数据。
另一种SESSION类型是,在一台服务器中SESSION状态被复制到集群中的其他所有服务器上,无论何时,只要SESSION 被改变,SESSION数据都要重新被复制。这就是 replicated session 。 sticky 和 replicated sessions都有他们的优缺点, Sticky sessions简单而又容易操作,因为我们不必复制任何SESSION数据到其他服务器上。这样就会减少系统消耗,提高性能。但是如果服务器失败,所有存储在该服务器内存中的SESSION数据也同样会消失。如果SESSION数据没有被复制到其他服务器,这些SESSION就完全丢失了。当我们在进行一个查询事务当中的时候,丢失所有已经输入的数据,就会导致很多问题。
为了支持 JSP HTTP session 状态的自动失效无缝转移,TOMCAT服务器复制了在内存中的SESSION状态。这是通过复制存储在一台服务器上的SESSION数据到集群中其他成员上防止数据丢失以及允许失效无缝转移。
对象的状态管理
通过在服务器上的保存状态可以区分出4种对象:
●无状态:一个无状态对象在调用的时候不会在内存中保存任何状态,因为客户端和服务器端没必要保存任何有关对方的信息。在这种情况下,客户端会在每次请求服务器时都会发送数据给服务器。SESSION状态被在客户端和服务器端来回发送。这种方法不总是可行和理想的,特别是当传输的数据比较大或者一些安全信息我们不想保存在客户端的时候;
●会话:一个会话对象在一个SESSION中只被用于特定的某个客户端。在SESSION中,他可以为所有来自该客户端的请求服务,并且仅仅是这个客户端的请求。贯穿一个SESSION,两个请求间的状态信息必须保存。会话服务通常在内存中保存短暂的状态,当在服务器失败的时候可能会丢失。SESSION状态通常被保存在请求间的服务器的内存中。为了清空内存,SESSION状态也可以被从内存中释放(就像在一个对象CACHE)。在该对象中,性能和可量测性都有待提高,因为更新并不是被单独的写到磁盘上,并且服务器失败的时候数据也没办法抢救。
●缓存:缓存对象在内存中保存状态,并且使用这个去处理从多客户端来的请求。缓存服务的实现可以扩展到他们把缓存的是数据备份保存在后端存储器中(通常是一个关系数据库)。
●独立的:一个独立的对象在一个时间内只活跃在集群中的一台服务器上,处理来自多客户端的请求。他通常由那些私有的,持久的,在内存中缓寸的数据支持。他同样也在内存中保持短暂状态,在服务器失败的时候要重建或者丢失。当失败的时候,独立对象必须在同一个服务器上重起或者移植到另一台服务器上。
(来源: "Using WebLogic Server Clusters")
SESSION复制的设计考虑事项
网络考虑事项
把集群的多点传送地址和其他应用程序隔离是至关重要的。我们不希望集群配置或者网络布局干扰到多点传送服务器通信。和其他应用程序共享集群多点传送地址将迫使集群的服务器例程处理不应该的消息,消耗系统内存。共享多点传送地址可能也会使IP多点传送缓冲过载,延迟服务器 heartbeat 消息传输。这样的延迟可能导致一个服务器例程被标识为死亡,仅仅因为他的 heartbeat 消息没有被及时接收。
编程考虑事项
除了上面提到的网络相关因素,还有些和我们写 J2EE 网络应用程序有关的设计考虑也会影响SESSION复制。以下列出了一些编程方面的考虑:
●SESSION数据必须被序列化:为了支持HTTP session 状态的内存内复制,所有的 servlet 和 JSP session 数据必须被序列化,对象中的每个域都必须被序列化,这样对象被可靠的序列化。
●把应用程序设计为幂等的:幂等的的意思就是一个操做不会修改状态信息,并且每次操作的时候都返回同样的结果(换句话说就是:做多次和做一次的效果是一样的),通常,WEB请求,特别是 HTML forms 都被发送多次(当用户点击发送按纽两次,重载页面多次),导致多次HTTP请求。设计SERVLET和其他WEB对象为幂等的,可以容忍多次请求。详细可以去参考设计模式“Synchronized Token ”和“Idempotent Receiver ”关于怎样设计幂等的的应用程序。
●在BUSINESS层存储状态:会话状态应该使用有状态的SESSION BEANS存储在EJB层,而不是存储在WEB层的HttpSession。因为企业应用程序要支持各种类型客户端(WEB客户端,JAVA应用程序,其他EJB),存储数据在WEB层会导致在客户端的双数据存储。因此,有状态的SESSION BEAN在这些情况下就被用于存储SESSION状态。无状态的SESSION BEAN要为每次的调用重构造会话状态。这些状态可能必须从数据库中恢复的数据中重编译。这些缺点失去了使用无状态SESSION BEAN去提高性能和可测量性的目的,严重的减低了性能。
●序列化系统消耗:序列化SESSION数据在复制SESSION状态的时候回会些系统消耗。随着序列化对象大小的增长消耗也越多。最好是保持SE
实践中整理出tomcat集群和负载均衡
(一)环境说明
(1)服务器有4台,一台安装apache,三台安装tomcat
(2)apache2.0.55、tomcat5.5.15、jk2.0.4、jdk1.5.6或jdk1.4.2
(3)ip配置,一台安装apache的ip为192.168.0.88,三台安装tomcat的服务器ip分别为192.168.0.1/2/4
(二)安装过程
(1)在三台要安装tomcat的服务器上先安装jdk
(2)配置jdk的安装路径,在环境变量path中加入jdk的bin路径,新建环境变量JAVA_HOME指向jdk的安装路径
(3)在三台要安装tomcat的服务器上分别安装tomcat,调试三个tomcat到能够正常启动
(4)tomcat的默认WEB服务端口是8080,默认的模式是单独服务,我的三个tomcat的WEB服务端口修改为7080/8888/9999
修改位置为tomcat的安装目录下的conf/server.xml
修改前的配置为
<Connector port="8080" maxHttpHeaderSize="8192"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" redirectPort="8443" acceptCount="100"
connectionTimeout="20000" disableUploadTimeout="true" />
修改后的配置为
<Connector port="7080" maxHttpHeaderSize="8192"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" redirectPort="8443" acceptCount="100"
connectionTimeout="20000" disableUploadTimeout="true" />
依次修改每个tomcat的监听端口(7080/8888/9999)
(5)分别测试每个tomcat的启动是否正常
http://192.168.0.1:7080
http://192.168.0.2:8888
http://192.168.0.4:9999
(三)负载均衡配置过程
(1)在那台要安装apache的服务器上安装apache2.0.55,我的安装路径为默认C:\Program Files\Apache Group\Apache2
(2)安装后测试apache能否正常启动,调试到能够正常启动http://192.168.0.88
(3)下载jk2.0.4后解压缩文件
(4)将解压缩后的目录中的modules目录中的mod_jk2.so文件复制到apache的安装目录下的modules目录中,我的为C:\Program Files\Apache Group\Apache2\modules
(5)修改apache的安装目录中的conf目录的配置文件httpd.conf,在文件中加LoadModule模块配置信息的最后加上一句LoadModule jk2_module modules/mod_jk2.so
(6)分别修改三个tomcat的配置文件conf/server.xml,修改内容如下
修改前
<!-- An Engine represents the entry point (within Catalina) that processes
every request. The Engine implementation for Tomcat stand alone
analyzes the HTTP headers included with the request, and passes them
on to the appropriate Host (virtual host). -->
<!-- You should set jvmRoute to support load-balancing via AJP ie :
<Engine name="Standalone" defaultHost="localhost" jvmRoute="jvm1">
-->
<!-- Define the top level container in our container hierarchy -->
<Engine name="Catalina" defaultHost="localhost">
修改后
<!-- An Engine represents the entry point (within Catalina) that processes
every request. The Engine implementation for Tomcat stand alone
analyzes the HTTP headers included with the request, and passes them
on to the appropriate Host (virtual host). -->
<!-- You should set jvmRoute to support load-balancing via AJP ie :-->
<Engine name="Standalone" defaultHost="localhost" jvmRoute="tomcat1">
<!-- Define the top level container in our container hierarchy
<Engine name="Catalina" defaultHost="localhost">
-->
将其中的jvmRoute="jvm1"分别修改为jvmRoute="tomcat1"和jvmRoute="tomcat2"和jvmRoute="tomcat3"
(7)然后重启三个tomcat,调试能够正常启动。
(8)在apache的安装目录中的conf目录下创建文件workers2.propertie,写入文件内容如下
# fine the communication channel
[channel.socket:192.168.0.1:8009]
info=Ajp13 forwarding over socket
#配置第一个服务器
tomcatId=tomcat1 #要和tomcat的配置文件server.xml中的jvmRoute="tomcat1"名称一致
debug=0
lb_factor=1 #负载平衡因子,数字越大请求被分配的几率越高
# Define the communication channel
[channel.socket:192.168.0.2:8009]
info=Ajp13 forwarding over socket
tomcatId=tomcat2
debug=0
lb_factor=1
# Define the communication channel
[channel.socket:192.168.0.4:8009]
info=Ajp13 forwarding over socket
tomcatId=tomcat3
debug=0
lb_factor=1
[status:]
info=Status worker, displays runtime information.
[uri:/jkstatus.jsp]
info=Display status information and checks the config file for changes.
group=status:
[uri:/*]
info=Map the whole webapp
debug=0
(9)在三个tomcat的安装目录中的webapps建立相同的应用,我和应用目录名为TomcatDemo,在三个应用目录中建立相同 WEB-INF目录和页面index.jsp,index.jsp的页面内容如下
<%@ page contentType="text/html; charset=GBK" %>
<%@ page import="java.util.*" %>
<html><head><title>Cluster App Test</title></head>
<body>
Server Info:
<%
out.println(request.getLocalAddr() + " : " + request.getLocalPort()+"<br>");%>
<%
out.println("<br> ID " + session.getId()+"<br>");
// 如果有新的 Session 属性设置
String dataName = request.getParameter("dataName");
if (dataName != null && dataName.length() > 0) {
String dataValue = request.getParameter("dataValue");
session.setAttribute(dataName, dataValue);
}
out.print("<b>Session 列表</b>");
Enumeration e = session.getAttributeNames();
while (e.hasMoreElements()) {
String name = (String)e.nextElement();
String value = session.getAttribute(name).toString();
out.println( name + " = " + value+"<br>");
System.out.println( name + " = " + value);
}
%>
<form action="index.jsp" method="POST">
名称:<input type=text size=20 name="dataName">
<br>
值:<input type=text size=20 name="dataValue">
<br>
<input type=submit>
</form>
</body>
</html>
(10)重启apache服务器和三个tomcat服务器,到此负载 均衡已配置完成。测试负载均衡先测试apache,访问http://192.168.0.88/jkstatus.jsp
能否正常访问,并查询其中的内容,有三个tomcat的相关配置信息和负载说明,访问http://192.168.0.88/TomcatDemo/index.jsp看能够运行,
能运行,则已建立负载均衡。
(四)tomcat集群配置
(1)负载均衡配置的条件下配置tomcat集群
(2)分别修改三个tomcat的配置文件conf/server.xml,修改内容如下
修改前
<!--
<Cluster className="org.apache.catalina.cluster.tcp.SimpleTcpCluster"
managerClassName="org.apache.catalina.cluster.session.DeltaManager"
expireSessionsOnShutdown="false"
useDirtyFlag="true"
notifyListenersOnReplication="true">
<Membership
className="org.apache.catalina.cluster.mcast.McastService"
mcastAddr="228.0.0.4"
mcastPort="45564"
mcastFrequency="500"
mcastDropTime="3000"/>
<Receiver
className="org.apache.catalina.cluster.tcp.ReplicationListener"
tcpListenAddress="auto"
tcpListenPort="4001"
tcpSelectorTimeout="100"
tcpThreadCount="6"/>
<Sender
className="org.apache.catalina.cluster.tcp.ReplicationTransmitter"
replicationMode="pooled"
ackTimeout="5000"/>
<Valve className="org.apache.catalina.cluster.tcp.ReplicationValve"
filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;"/>
<Deployer className="org.apache.catalina.cluster.deploy.FarmWarDeployer"
tempDir="/tmp/war-temp/"
deployDir="/tmp/war-deploy/"
watchDir="/tmp/war-listen/"
watchEnabled="false"/>
<ClusterListener className="org.apache.catalina.cluster.session.ClusterSessionListener"/>
</Cluster>
-->
修改后
<!-- modify by whh -->
<Cluster className="org.apache.catalina.cluster.tcp.SimpleTcpCluster"
managerClassName="org.apache.catalina.cluster.session.DeltaManager"
expireSessionsOnShutdown="false"
useDirtyFlag="true"
notifyListenersOnReplication="true">
<Membership
className="org.apache.catalina.cluster.mcast.McastService"
mcastAddr="228.0.0.4"
mcastPort="45564"
mcastFrequency="500"
mcastDropTime="3000"/>
<Receiver
className="org.apache.catalina.cluster.tcp.ReplicationListener"
tcpListenAddress="auto"
tcpListenPort="4001"
tcpSelectorTimeout="100"
tcpThreadCount="6"/>
<Sender
className="org.apache.catalina.cluster.tcp.ReplicationTransmitter"
replicationMode="pooled"
ackTimeout="5000"/>
<Valve className="org.apache.catalina.cluster.tcp.ReplicationValve"
filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;"/>
<Deployer className="org.apache.catalina.cluster.deploy.FarmWarDeployer"
tempDir="/tmp/war-temp/"
deployDir="/tmp/war-deploy/"
watchDir="/tmp/war-listen/"
watchEnabled="false"/>
<ClusterListener className="org.apache.catalina.cluster.session.ClusterSessionListener"/>
</Cluster>
<!-- modify by whh -->
将集群配置选项的注释放开即可,如上。
(3)重启三个tomcat。到此tomcat的集群已配置完成。
(五)应用配置
对于要进行负载和集群的的tomcat目录下的webapps中的应用中的WEB-INF中的web.xml文件要添加如下一句配置
<distributable/>
配置前
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="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 http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">
<display-name>TomcatDemo</display-name>
</web-app>
配置后
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="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 http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">
<display-name>TomcatDemo</display-name>
<distributable/>
</web-app>
问:tomcat集群是怎么处理session的阿
答:在tomcat做集群之后,每个tomcat之间自动根据tomcat的配置文件中的参数进行session复制,
对于一个客户端对说,只要是同一个IP,那它每次上传的sessionID就是一样的,
发表评论
-
ESB的一些理解
2011-03-24 17:16 10021.统一的服务发布方式和调用方式 2.协议的适配及转化 3.支 ... -
有没有办法支持批量插入clob类型的数据
2008-07-19 09:44 1771项目中有张表要插入clob类型的数据,查阅资料后发现jdbc要 ... -
Tomcat集群与负载均衡
2007-12-11 16:28 1541在单一的服务器上执行W ... -
Apache与Tomcat的三种连接方式介绍
2007-12-11 12:35 2398首先我们先介绍一下为 ... -
[转]沿着“重用”我们一路走来——SA、OO(DP)、Component、SOA、AOP
2007-12-10 21:13 1238自从有了软件开发以来 ... -
分布式事务介绍(Distributed Transaction Processing DTP)
2007-10-31 16:10 3346第一阶段开始时,向此事务涉及到的全部资源发送提 ... -
构建更好的异常处理框架[转]
2007-09-19 14:04 1108企业应用程序在构建时 ...
相关推荐
在IT领域,特别是Web应用服务器的管理与优化中,Tomcat集群实现Session复制是一个关键的技术点,它确保了高可用性和负载均衡,特别是在处理大量并发请求的场景下。本文将深入探讨这一主题,涵盖其原理、配置方法以及...
在Tomcat5中,Session复制可以通过IP多点传送(IP multicast)和IP sockets实现。IP多点传送是一种一对多的服务器通讯机制,可以让多服务器向指定IP地址和端口号进行订阅并且监听消息。IP sockets则是一种点对点的...
一直以来,我误解认为启动了n个tomcat,则Session需要同步复制到n个Tomcat中存在,因此在启动了6个以上的Tomcat,性能会大大下降。 而实际情况下,采取Apache 加Tomcat进行负载均衡集群的时候,是可以不用将Session...
NULL 博文链接:https://xueweiabcok.iteye.com/blog/1841448
在这个场景中,我们关注的是如何在Tomcat集群环境中实现Session共享,以便提高应用程序的可扩展性和可用性。标题和描述提到的“session共享包”是解决这一问题的关键。 **什么是Session?** 在Web应用中,Session是...
当我们谈论“Tomcat7集群实现session共享”时,我们关注的是如何在多个Tomcat实例之间有效地同步用户会话信息,以便在集群环境中提供高可用性和负载均衡。 首先,理解session共享的重要性。在Web应用中,session是...
在IT行业中,尤其是在Web...总的来说,利用Redis进行Tomcat集群Session共享是一种高效且灵活的方法,能够提高系统的可用性和用户体验。通过深入理解这一技术,开发者可以更好地构建和维护大规模分布式Web应用程序。
tomcat8 Redis集群 同步Session 中用到的jar 附带tomcat content.xml配置文件
在构建高可用的Web服务时,Tomcat集群是常见的选择,但随之而来的一个问题就是如何在集群中的各个节点间共享Session。"Tomcat8集群session共享(redis处理)"的主题正是针对这一问题,通过集成Redis作为分布式缓存来...
通过复制应用和配置,可以创建一个Tomcat集群,这样当一台服务器出现故障时,其他服务器能够接管其工作,保证服务的连续性。然而,由于每个Tomcat实例都有自己的内存空间,所以默认情况下,每个服务器会独立维护用户...
Nginx Tomcat 集群的Session 复制,解决了,集群情况下的session复制问题。
总之,通过合理配置Tomcat集群和使用Redis作为session存储,我们可以实现跨服务器的session共享,确保用户在多台服务器间的会话一致性。这个压缩包提供了一个预配置的解决方案,对于快速搭建和测试session共享环境...
本文将详细介绍如何在Windows环境下,利用Nginx作为反向代理服务器,与Tomcat集群配合实现负载均衡,并进行session复制,确保用户会话在不同服务器之间的一致性。 首先,Nginx是一款轻量级、高性能的HTTP和反向代理...
本篇文章将深入探讨Tomcat集群中session共享的解决方案,以及相关的应用知识。 1. **Session复制**:这是最基础的session共享方法。通过配置Tomcat的`cluster`模块,可以设置session复制策略。每当一个session在...
本篇文章将详细探讨如何在Redis+Tomcat集群配置中实现Session共享。 首先,我们需要理解什么是Session。Session是Web应用中用于存储用户状态的一种机制,通常用于保存用户的登录信息、购物车等数据。在单台服务器...
这就是“Tomcat集群session共享”的核心需求。本篇将详细介绍如何在Tomcat7中实现基于Redis的Session共享,并涉及相关的jar包。 首先,让我们了解为何需要session共享。在单个Tomcat服务器中,Session信息存储在...
tomcat8.5.29 redisclouder集群 session共享集群相关配置文件 亲测可用tomcat8.5.29 redisclouder集群 session共享集群相关配置文件 亲测可用 tomcat8.5.29 redisclouder集群 session共享集群相关配置文件 亲测可用 ...
本篇将深入探讨Apache如何实现负载均衡,以及Tomcat集群和session复制的相关知识。 首先,Apache的负载均衡主要通过模块mod_proxy来实现。这个模块能够将客户端的HTTP请求转发到不同的后端服务器,从而达到负载均衡...
Tomcat5 提供了集群(Cluster)功能来实现 Session 的复制,确保用户在不同服务器间的会话状态能够无缝切换。以下是关于 Tomcat5 Session 复制的详细说明: 1. **配置集群组件** 在 `conf/server.xml` 文件中,你...