Java应用服务器之tomcat会话复制集群配置

  会话是识别用户,跟踪用户访问行为的一个手段,经过cookie(存在客户端)或session(存在服务端)来判断本次请求是那个客户端发送过来;经常使用的会话保持有绑定会话,就是前边咱们聊的在代理上经过算法或经过给客户端响应首部加cookie这种方式来保持同一cookie或同一ip地址的请求始终发送到同一后端server进行响应;可是这样的会话绑定的方式存在一个问题,就是当后端某一server宕机,那么以前上面的全部会话信息将消失,那么后续的客户端来请求,代理是否要把请求调度到后端宕机的server呢?若是说调度上去呢,那么用户以前的会话信息又没有了,若是说不调度呢,那么用户将不可以获得服务;因此对于这种状况咱们须要把会话都同步到后端全部server上,即使某一台或几台后端server宕机了,不会致使用户的会话信息丢失,一样服务也是可用的;这种冗余的方式保存会话信息,使得用户的会话信息可以在任何一台后端server上都会有;这也意味着只要有用户来请求,前端调度器能够任意把请求调度到后端的某一台server上,而后服务端把本次请求的用户会话信息经过广播的方式,通知给其余后端server,这样一来这个客户端后续来请求,无论调度到后端那一台server上,由于后端server上都有这个客户端以前请求的会话信息,因此无论到那一台都可以识别;对于tomcat来说,它内部就有一个组件支持这样的功能,它能够基于多播通讯的方式,把会话信息同步给后端其余节点,这个组件就是cluster;前端

  示例:使用tomcat cluster组件来定义tomcat的会话复制集群nginx

  环境说明web

名称 ip地址 端口
代理Nginx 192.168.0.41 80
应用服务tomcatA 192.168.0.42 8080
应用服务tomcatB 192.168.0.43 8080

 

 

 

 

 

  准备测试页面,以及配置tomcatA算法

  提示:以上是myapp里的内容以及文件目录结构apache

  提示:以上配置表示部署一个/myapp的应用,它的文件路径在/webapps/myapp,而且在engine上配置了 jvmRoute=“tomcatA”;后端

  提示:cluster配置须要注意上面打红框的位置,在官方配置文档中,后面的<ClusterListener 的后面没有把标签闭合了,咱们在使用时须要给它闭合了,不然会出现语法错,致使tomcat起不来;其次就是咱们须要更改接收器的ip地址,默认它是auto,auto表示自动监听本机一个地址,这个地址也多是127.0.0.1,若是监听在127.0.0.1,那么主机就不可以接收到,其余节点发来的会话信息;说下这个配置文件吧,cluster组件中主要就是定义了DeltaManager的属性,该组件用于处理增量会话的事务,也就是用这个管理的功能实现多节点复制会话信息;其次咱们要在其cluster内部定义个chanel,这个组件主要定义集群通讯和各成员的一些属性,好比成员关系断定呀,接收器和发送器;Membership组件用于定义成员关系断定的,里面主要定义多播地址和端口等属性,若是多播地址相同,那么就是同一集群的成员,不然不是;Receiver主要用于定义接收器的相关属性,好比接收器监听的地址和端口超时时长,最大线程等等;Sender用于指定发送器,发送器咱们这里不须要认为手动定义,用官方给定的示例便可;后面的Interceptor主要定义了tcp报文的检查以及消息摘要,后面两台哦Interceptor主要做用是保证tcp报文的完整和正确性;Deployer主要用于定义部署应用相关属性,它的主要做用是若是咱们定义了集群,咱们能够在集群成员中的一台server上部署好应用,而后其余成员能够经过网络自动部署;一般咱们建议使用这个自动部署的功能;tomcat

  完整的server.xml配置服务器

<?xml version='1.0' encoding='utf-8'?>
<Server port="8005" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <Listener className="org.apache.catalina.core.JasperListener" />
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
  <GlobalNamingResources>
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>
  <Service name="Catalina">
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
    <Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcatA">
      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>

      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log." suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />
        <Context path="/myapp" docBase="/webapps/myapp" reloadable=""/>
        <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="192.168.0.42"
                      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.JvmRouteSessionIDBinderListener"/>
          <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
        </Cluster>
      </Host>
    </Engine>
  </Service>
</Server>
View Code

  给咱们定义的应用修改器web.xml 在其中加上<distributable/>元素cookie

  提示:对于web.xml配置文件,咱们能够从/etc/tomcat/中复制一份到本身的应用目录结构里,而后在非注释掉位置加上<distributable/>元素便可网络

  对于tomcatB来讲,咱们也须要准备好一样的文件,为了区分,咱们把index.jsp修改为tomcatB ,在配置文件中咱们须要修改接收器的监听地址,以及jvmRoute的值,其余的均可以不变

  到此tomcat会话复制集群就配置好了;其实从上面的配置文件能够看大,tomcat的会话复制集群就是利用多播地址通讯,一个请求无论到集群那个基点,它都会经过多播通讯,把会话信息以组播的方式发送给其余成员;这里建议把接收器的地址专门用张网卡配置好地址;接下来咱们启动下tomcatA,tomcatB,而后看看日志是否初始集群成功,并接收到集群成员接收器的地址;

  提示:这里注意一点若是tomcat启动特别慢,就是8005端口要等好久才起来,能够尝试安装rng-tools,并启动rngd,这样能够加快tomcat启动

  提示:若是在tomcatA的日志中可以看到tomcatB的接收器地址和端口,那么就表示tomcatA已经识别到tomcatB,并把tomcatB看成集群成员加入到集群;一样在tomcatB的日志中可以看到tomcatA的接收器地址和端口,表示tomcatB已经识别tomcatA并把它加入到集群;

  配置nginx负载均衡后端两台tomcat server

  提示:这里须要主要反代时须要把反代的URI和后面proxy_pass后面的URI相同,不然代理后,会话复制集群不会生效;

  验证:检查nginx的配置文件语法,启动nginx访问192.168.0.41/myapp看看有什么变化

  提示:能够看到访问192.168.0.41/myapp时sessionid始终没有发生变化,变化的只有后面的jvmRoute的值和页面的值;这说明咱们访问nginx时,nginx也基于本身的轮询算法把请求调度到后端去了,第一次访问时,后端server会响应一个set-cookie的首部,把当前访问的页面的session信息响应给客户端,第二次访问客户端就会把上一次访问相应的cookie带上去访问,这时后端server接受到客户端发送过来的cookie,而后就在本身内存里找对应的session信息;因为后端server是把session信息基于多播通讯的方式共享给集群其余节点,因此第二次无论调度到那台server上,对应server都会有该客户端第一次访问服务端的session信息;因此咱们第二次访问时,sessionid仍是第一次访问服务器的sessionid,后面的tomcatB表示由tomcatB这个jvmRoute处理的此次请求;

相关文章
相关标签/搜索