Tomcat实现会话保持

Tomcat会话保持的几种方式

  • 利用Nginx和Apache反向代理时使用源地址hash算法,将相同源地址的请求发送到相同的一台后端Tomcat服务器
  • 利用Tomcat自带的集群工具实现会话绑定,这个方式会让每个Tomcat主机把自己的会话信息共享到其他Tomcat主机。不宜过多,4,5个节点就已经很大了。
  • 将会话信息保存到Memcached,当用户访问的时候,会把会话信息保存到一个非关系型数据库Memcached中,当再次访问的时候,Tomcat会到数据库找会话记录,实现会话保持。

这里主要介绍下后面两种方式。

环境准备

ip角色安装的软件
192.168.253.128TomcatATomcat
192.168.253.158TomcatBTomcat
192.168.253.158Nginx反代Nginx

TomcatA的测试页面

<%@ page language="java" %>
<html>
	<head><title>TomcatA</title></head>
	<body>
		<h1><font color="red">TomcatA</font></h1>
		<table align="centre" border="1">
			<tr>
				<td>Session ID</td>
			<% session.setAttribute("TomcatA","TomcatA"); %>
				<td><%= session.getId() %></td>
			</tr>
			<tr>
				<td>Created on</td>
				<td><%= session.getCreationTime() %></td>
			</tr>
		</table>
	</body>
</html>

TomcatB测试页面

<%@ page language="java" %>
<html>
	<head><title>TomcatB</title></head>
	<body>
		<h1><font color="red">TomcatB</font></h1>
		<table align="centre" border="1">
			<tr>
				<td>Session ID</td>
			<% session.setAttribute("TomcatB","TomcatB"); %>
				<td><%= session.getId() %></td>
			</tr>
			<tr>
				<td>Created on</td>
				<td><%= session.getCreationTime() %></td>
			</tr>
		</table>
	</body>
</html>

访问两个Tomcat节点初始页,出现下图则成功。其中Session ID就是我们的会话ID,如果实现了同一个主机访问得到相同的Session ID则可以认为会话绑定成功。
在这里插入图片描述

Nginx反向代理配置文件

[root@localhost ~]# cat /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
    worker_connections 1024;
}
http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    access_log  /var/log/nginx/access.log  main;
    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;
    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;
    include /etc/nginx/conf.d/*.conf;
    upstream tomcat {
        server 192.168.253.128:8080 weight=1;
        server 192.168.253.158:8080 weight=1;
    }
    server {
        listen       80 default_server;
        location / {
        proxy_pass   http://tomcat ;
        }
    }
}

这里的设置的算法是轮询,权重是1比1

Tomcat Clustering

第一步:修改配置文件server.xml

将下面这段配置添加到每个节点的主配置文件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.4"
                        port="45564"
                        frequency="500"
                        dropTime="3000"/>
            <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                      address="ip"   #这里的ip是集群内部通信监听的ip地址
                      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.MessageDispatchInterceptor"/>
          </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"
                 channelSendOptions="8">

          <Manager className="org.apache.catalina.ha.session.DeltaManager"  #会话管理器
                   expireSessionsOnShutdown="false"   #不允许会话过期
                   notifyListenersOnReplication="true"/>  #监听事件

          <Channel className="org.apache.catalina.tribes.group.GroupChannel">  #channel定义信道
            <Membership className="org.apache.catalina.tribes.membership.McastService"
                        address="228.0.0.4"  #多播地址通信
                        port="45564"             #多播地址使用的端口,监听再这个端口上的就是同一个集群成员
                        frequency="500"      #每隔0.5s发心跳探测
                        dropTime="3000"/> #3s没收到心跳探测认为他down了
            <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" #接受信息,java内部的一个异步处理逻辑
                      address="ip"   #这里的ip是集群内部通信监听的ip地址
                      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.MessageDispatchInterceptor"/>
          </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>

第二步:配置webapps

在对应的站点目录下,创建WEB-INF/web.xml文件,添加元素;
因为是测试所以比较简单直接复制全局的web.xml,然后再里面添加元素就好了

mkdir /data/test/WEB-INF
cp /usr/local/tomcat/conf/web.xml /data/test/WEB-INF/   #复制默认的web.xml到对应的站点目录下

/data/test/WEB-INF/web.xml 中添加下面一行

<distributable/>

两台tomcat节点重启一下tomcat

catalina.sh  stop
catalina.sh  start

在这里插入图片描述
在这里插入图片描述

可以看到Session ID没变,所以实现了会话保持。

将Session保存在Memcached中

原理:Tomcat会将会话信息保存在Memcached中,当有用户访问时,就可以直接在Memcached中找会话信息。不用基于前端的负载均衡器绑定ip,也不需要tomcat集群互相复制会话信息。
项目地址:https://github.com/magro/memcached-session-manager
项目文档:https://github.com/magro/memcached-session-manager/wiki/SetupAndConfiguration

第一步:下载memcached-session-manager会话管理工具

下载如下jar文件至各tomcat节点的tomcat安装目录下的lib目录中
其中的${version}要换成你所需要的版本号,tc${6,7,8}要换成与tomcat版本相同的版本号。

memcached-session-manager-${version}.jar   
memcached-session-manager-tc${6,7,8}-${version}.jar
spymemcached-${version}.jar

这里节点是tomcat8.5,具体版本为

memcached-session-manager-1.9.6.jar  #下载地址  http://repo1.maven.org/maven2/de/javakaffee/msm/memcached-session-manager/1.9.6/
memcached-session-manager-tc8-1.9.6.jar  #下载地址http://repo1.maven.org/maven2/de/javakaffee/msm/memcached-session-manager-tc8/1.9.6/
spymemcached-2.12.2    #下载地址  http://repo1.maven.org/maven2/net/spy/spymemcached/2.12.2/

将这些文件下载到tomcat的lib目录下

第二步:添加序列化序列化工具javolution-serializer

这里的序列化工具有许多种

  • kryo-serializer: msm-kryo-serializer, kryo-serializers-0.34+, kryo-3.x, minlog, reflectasm, asm-5.x, objenesis-2.x
  • javolution-serializer: msm-javolution-serializer, javolution-5.4.3.1
  • xstream-serializer: msm-xstream-serializer, xstream, xmlpull, xpp3_min
  • flexjson-serializer: msm-flexjson-serializer, flexjson

这次使用的序列化工具是javolution-serializer,具体版本如下

msm-javolution-serializer  #下载地址   http://repo1.maven.org/maven2/de/javakaffee/msm/msm-javolution-serializer/1.9.6/
javolution-5.4.3.1   #下载地址   http://www.java2s.com/Code/Jar/j/Downloadjavolution5431jar.htm

将这些文件下载到tomcat的lib目录下

第三步:修改配置文件

分别在两个tomcat上的某host上定义一个用于测试的context容器,并在其中创建一个会话管理器,如下所示:

<Context path="" docBase="/data/test" reloadable="true" >
   <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
     memcachedNodes="n1:192.168.253.128:11211,n2:192.168.253.158:11211"
     failoverNodes="n1"
     requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
     transcoderFactoryClass="de.javakaffee.web.msm.serializer.javolution.JavolutionTranscoderFactory"
  />
</Context>

第四步:安装Memcached

在两个tomcat节点安装Memcached并启动

yum install memcached -y
systemctl start memcached

第五步:重启Tomcat并测试

catalina.sh  stop
catalina.sh  start

在这里插入图片描述
在刷新一次

在这里插入图片描述

这时候可以看到使用的是n2这个主机的Memcached,这时候我们down了n2(192.168.253.158)的Memcached

在这里插入图片描述

在这里插入图片描述

可以看到Session ID没变,但是后面变成了n1节点,证明了即使n2宕了,n1也能接管服务

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值