标题索引


  • 追朔原因

  • 方案构建

  • 方案评估


追朔原因

    网站集群会话管理毋庸置疑,互联网上方案层出不穷,构建稳定、高效、适应业务系统的方案需根据自己的业务发展自行设计,根据以往经验tomcat构建会话管理时,往往异常莫名奇妙问题恒生,因此自测方案迫在眉睫。

方案构建

    1.会话管理

    通常采用Cookie技术或Session技术,如下为俩者方案详解,Cookie技术具体原理及过程如下所示:

tomcat会话管理集群建设方案_session

图1-1 Cookie会话管理技术流程图

    如上所示Cookie技术是调用Serlet接口中的Set-Cookie方法,可以将会话、网购产品等非重要数据保存Cookie中并通过response报文返回浏览器,浏览器缓存Cookie,浏览器再次访问Serlet接口时携带之前分配的Cookie,从而携带之前Cookie中保存的内容。

    Session技术具体原理如下所示:

tomcat会话管理集群建设方案_session_02

图1-2 Session会话管理技术流程图

    如上所示Session技术调用Serlet接口的Session方法,可以将会话ID、网购产品等非重要数据保存会话,通过构建response响应报文返回浏览器会话ID,浏览器缓存会话ID,浏览器再次访问Serlet接口时携带之前分配的会话ID,从而可以从会话服务器中获取保存在会话中的内容。

    2.核心配置

    调度器Cookie转发

    采用调度器采用Cookie会话管理时,会话保持技术主要集中在调度器,服务器端无需采用其他Cookie或Session技术即可做到会话保持,如apache做调度时核心配置:

[ root@centos7 ~ ]#vim /etc/httpd/conf.d/vhost.conf
    #apache给请求报文头部添加Cookie,并转发
   Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED
   <Proxy balancer://tcpsv>
                BalancerMember http://172.18.27.23:8080 route=1
                BalancerMember http://172.18.27.24:8080 route=2 
                #调度采用基于Cookie的会话保持                                                                                                             
                proxyset stickysession=ROUTEID
   </Proxy>
   
   <VirtualHost *:80>
           ServerName www.jncsy.com
          ProxyVia On
          ProxyRequests Off
          ProxyPreserveHost On
          <Proxy *>
                  Require all granted
          </Proxy>
          <Location />
                  Require all granted
          </Location>
          ProxyPass / balancer://tcpsv/
          ProxyPassReverse / balancer://tcpsv/
    </VirtualHost>

    集群会话同步

    参考官方集群文档https://tomcat.apache.org/tomcat-7.0-doc/cluster-howto.html,在每台tomcat  server.xml文件中添加

<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.8"
                        port="45564"
                        frequency="500"
                        dropTime="3000"/>
            <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                      <!--定义接收会话同步的IP地址 -->
					  address="172.18.27.23"
                      port="4000"
                      autoBind="100"
                      selectorTimeout="5000"
					<!--根据服务器数量定义,具体为服务器数量-1  -->
                      maxThreads="8"/>

            <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.JvmRouteSessionIDBinderListener" />
          <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener" />
        </Cluster>

    并在在目录/WEB-INF的目录的web.xml中的文件的末尾中添加

	<welcome-file-list>
         <welcome-file>index.html</welcome-file>
         <welcome-file>index.htm</welcome-file>
         <welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
	<!-- 开启会话分布功能 -->
        <distributable/>
</web-app>

    会话服务器

    会话服务器采用tomcat+memcache构建,其中tomcat中添加/usr/share/tomcat/bin下添加会话管理包,让tomcat支持会话管理,在每个页面程序中的WEB-INF下常见lib目录并在此目录中添加序列化工具,将服务器产生的会话通过序列化工具转化为可以存储在memcache中的键值,具体可参考官网文档https://github.com/magro/memcached-session-manager/wiki/SetupAndConfiguration。

    核心配置如下:

[ root@nginxser01 lib ]#pwd                     #上传序列化工具
/usr/local/tomcat/webapps/test/WEB-INF/lib
[ root@nginxser01 lib ]#ls
asm-6.0.jar     kryo-serializers-0.42.jar  msm-kryo-serializer-2.1.1.jar  reflectasm-1.11.3.jar
kryo-4.0.1.jar  minlog-1.3.0.jar           objenesis-2.6.jar
[ root@nginxser01 lib ]#pwd
/usr/local/tomcat/lib                           #上传会话管理工具
[ root@nginxser01 lib ]#ls
memcached-session-manager-2.1.1.jar memcached-session-manager-tc8-2.1.1.jar 
spymemcached-2.12.3.jar 
[ root@nginxser01 conf]# vim server.xml         #粘性会话和非粘性会话根据业务需求二选一
   <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
        <Context path="/test" docBase="test">
    <!-- 粘性会话主备模式,单台存储会话-->
    <!--    <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
    memcachedNodes="n1:172.18.27.110:11211,n2:172.18.253.104:11211"
    failoverNodes="n1"
    requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
    transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
    /> -->
    <!--非粘性会话主主模式,两台同时存储会话-->
    <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
    memcachedNodes="n1:172.18.27.110:11211,n2:172.18.253.104:11211"
    sticky="false"                                                                                                                              
    sessionBackupAsync="false"
    lockingMode="auto"                                                                                                   
    requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
    transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
    />
    </Context>

方案评估

    根据如上3套方案,若业务量相对较小时,建议采用基于Cookie调度,因为网络NAT技术有可能会产生调度不均衡,但是并非同一IP会同时产生大量访问量。若业务量相对较大时,建议采用专用会话管理服务器集群,专业的工具做专业的事效果会更佳。若服务器资源相对匮乏、内存资源无法保障时,建议采用会话同步。