tomcat配置session共享

     参考地址:

      http://developer.51cto.com/art/201105/260375.htm

      http://www.360doc.com/content/13/1224/19/13247663_339826101.shtml

      http://www.imooo.com/web/xml-soap/254546.htm

      http://zyycaesar.iteye.com/blog/296606

      http://blog.csdn.net/zhuying_linux/article/details/6590700

     通过网上查找资料,知道了tomcat其实是可以实现session共享的,下面就具体的说明下怎么配置实现多个服务器之间的session共享。

     1、最简单的实现tomcat之间session共享的方法:

          第一步:启动负载均衡器如(nginx),这里就不讲了;

          第二步:准备多台tomcat服务器;

          第三步:修改conf目录下的server.xml文件,去掉下面这句的注释,然后再web.xml文件的节点</web-app>前加上<distributable />(这个是tomcat进行session复制所必须的,否则session不能进行复制!)即可;

<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>

          或者改变Tomcat的content.xml配置文件,修改 <Context distributable="true">,配置好之后启动服务器就可以了。

   

      2、<Cluster>标签详解,<Cluster>默认配置如下

<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="8">
			<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="4000" autoBind="100" selectorTimeout="5000" 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.MessageDispatch15Interceptor"/>
			</Channel>
		 
			<Valve className="org.apache.catalina.ha.tcp.ReplicationValve" filter=""/>
			<Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>

			<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>
    前面提到的<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>简单配置就等同于默认配置。

    Cluster
    Tomcat集群配置。集群的配置比较复杂,默认的集群配置可以满足一般的开发需求
    常用属性:
        className-指定Cluster使用的类
        channelSendOptions-Cluster发送消息的方式
        channelSendOptions可以设置为2、4、8、10,每个数字代表一种方式
            2 = Channel.SEND_OPTIONS_USE_ACK(确认发送)
            4 = Channel.SEND_OPTIONS_SYNCHRONIZED_ACK(同步发送)
            8 = Channel.SEND_OPTIONS_ASYNCHRONOUS(异步发送)
        在异步模式下,可以通过加上确认发送(Acknowledge)来提高可靠性,此时channelSendOptions设为10

    Manager
        Manager决定如何管理集群的Session信息。Tomcat提供了两种Manager:BackupManager和DeltaManager
        BackupManager-集群下的所有Session,将放到一个备份节点。集群下的所有节点都可以访问此备份节点
        DeltaManager-集群下某一节点生成、改动的Session,将复制到其他节点。DeltaManager是Tomcat默认的集群Manager,能满足一般的开发需求
        使用DeltaManager,每个节点部署的应用要一样;使用BackupManager,每个节点部署的应用可以不一样
        常用属性:
            className-指定实现org.apache.catalina.ha.ClusterManager接口的类
            expireSessionsOnShutdown-设置为true时,一个节点关闭,将导致集群下的所有Session失效
            notifyListenersOnReplication-集群下节点间的Session复制、删除操作,是否通知session listeners
            maxInactiveInterval-集群下Session的有效时间(单位:s)。maxInactiveInterval内未活动的Session,将被Tomcat回收。默认值为1800(30min)

    Channel
        Channel是Tomcat节点之间进行通讯的工具。Channel包括5个组件:Membership、Sender、Transport、Receiver、Interceptor

    Membership
        Membership维护集群的可用节点列表。它可以检查到新增的节点,也可以检查到没有心跳的节点
        常用属性:
            className-指定Membership使用的类
            address-组播地址
            port-组播端口
            frequency-发送心跳(向组播地址发送UDP数据包)的时间间隔(单位:ms)。默认值为500
            dropTime-Membership在dropTime(单位:ms)内未收到某一节点的心跳,则将该节点从可用节点列表删除。默认值为3000
            组播(Multicast):一个发送者和多个接收者之间实现一对多的网络连接。一个发送者同时给多个接收者传输相同的数据,只需复制一份相同的数据包。它提高了数据传送效率,减少了骨干网络出现拥塞的可能性
            相同组播地址、端口的Tomcat节点,可以组成集群下的子集群

    Receiver
        接收器,负责接收消息
        接收器分为两种:BioReceiver(阻塞式)、NioReceiver(非阻塞式)
        常用属性:
            className-指定Receiver使用的类
            address-接收消息的地址
            port-接收消息的端口
            autoBind-端口的变化区间
            如果port为4000,autoBind为100,接收器将在4000-4099间取一个端口,进行监听
            selectorTimeout-NioReceiver内轮询的超时时间
            maxThreads-线程池的最大线程数
       
    Sender
        发送器,负责发送消息
        Sender内嵌了Transport组件,Transport真正负责发送消息
        Transport分为两种:bio.PooledMultiSender(阻塞式)、nio.PooledParallelSender(非阻塞式)

    Interceptor
        Cluster的拦截器
        TcpFailureDetector-网络、系统比较繁忙时,Membership可能无法及时更新可用节点列表,此时TcpFailureDetector可以拦截到某个节点关闭的信息,并尝试通过TCP连接到此节点,以确保此节点真正关闭,从而更新集群可以用节点列表
        MessageDispatch15Interceptor-MessageDispatch15Interceptor查看Cluster组件发送消息的方式是否设置为Channel.SEND_OPTIONS_ASYNCHRONOUS(Cluster标签下的channelSendOptions为8时)。设置为Channel.SEND_OPTIONS_ASYNCHRONOUS时,MessageDispatch15Interceptor先将等待发送的消息进行排队,然后将排好队的消息转给Sender

    Valve
        Valve可以理解为Tomcat的拦截器
        ReplicationValve-在处理请求前后打日志;过滤不涉及Session变化的请求
        JvmRouteBinderValve-Apache的mod_jk发生错误时,保证同一客户端的请求发送到集群的同一个节点

    Deployer
        同步集群下所有节点的一致性。Deployer没试验成功过。。。

    ClusterListener
        监听器,监听Cluster组件接收的消息
        使用DeltaManager时,Cluster接收的信息通过ClusterSessionListener传递给DeltaManager

3、使用这样方法配置的集群会将Session同步到所在网段上的所有配置了集群属性的实例上(此处讲所在网段可能不准确,因为用的228.0.0.4地址进行的广播,我不清楚这是个什么性质的广播地址)。也就是说如果该广播地址下的所有Tomcat实例都会共享Session,那么假如有几个互不相关的集群,就可能造成Session复制浪费,所以为了避免浪费就需要对节点多做点设置了,如下:  

<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster">    
    <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"/>    
    Channel>    
Cluster>

tomcat的集群部署修改动作都比较简单,但实际在运行过程中会出现一系列的问题,我这里列举我在配置后使用过程中出现的一些问题和要点,供大家参考:
    1、用户存入SESSION中的数据的问题
        使用tomcat集群进行SESSION复制,必须要保证你的session中存放的所有对象都是实现了java.io.Serializable接口 的,因为session复制就是序列化对象到其他WEB应用服务器上的,所以如果没有实现该接口,那么SESSION同步将会失败。另外一点,就是如果要 同步的机器比较多的话,那么要注意保证SESSION中存放的数据比较小,不要什么都存放到SESSION中,因为复制SESSION也是需要开销的,数 据越大开销也越大。


    2、Tomcat执行SESSION复制的触发条件
        我们在tomcat的server.xml文件中集群部分cluster标签中可以看到属性:useDirtyFlag, 如果这个设置为true(默认的),那么只有当使用setAttribute往session中设置数据的时候才会同步其他WEB服务器的 SESSION,如果为false,那么每一次请求的sesison都会被同步到其他服务器上。因此在操作SESSION的时候要特别注意,避免出现 SESSION无法同步的问题。
        举个简单的例子,比如我们在单机应用情况下修改SESSION中用户的某一个数据,那么通常就是:

User user = (User)request.getSession().getAttribute("user");
User.setName("my name");

        这样我们就是直接存取出来,然后进行修改,虽然在单机情况下没有问题,但是在集群条件下,这样就导致了多台WEB服务器上的SESSION不同步的问 题,因为SESSION并没有改变,Tomcat无法监视session中某个数据的值是否发生了变化。因此,我们还需要执行如下操作以保证 SESSION的同步:

request.getSession().setAttribute(“user”, user);

        所以,我们在操作SESSION的时候要特别注意!另外的建议就是,我们应该尽可能的不要修改SESSION中的数据。
        因为Tomcat的SESSION复制通信是通过组播功能来实现不同服务器之间的交互的,所以需要在服务器上开通组播功能,windows默认情况下是开通组播服务的,而Linux系统下默认是没有开通的,我们需要通过如下命令来开通其组播功能:
        route add -net 224.0.0.0 netmask 240.0.0.0 dev eth0
        如果需要服务器启动时即开通组播需在/etc/sysconfig/static-routes文件内加入eht0 net 224.0.0.0 netmask 240.0.0.0。具体组播概念请查阅CCNP相关内容。
        可以通过netstate -g 来查看组播状态,也可以在route -e 命令中看到

猜你喜欢

转载自x125858805.iteye.com/blog/2197463