tomcat的session会话保持方案

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了tomcat的session会话保持方案相关的知识,希望对你有一定的参考价值。

基础知识

??

tomcat

??
??tomcat是Apache软件基金会的Jakarta项目中的核心项目,最新的Servlet和JSP规范能够在Tomcat中很好的表现。作为一个免费的开放源代码的Web应用服务器,属于轻量级的应用服务器,在中小型系统和并发量不是很大的场景下被广泛使用,是开发和调试JSP代码的首选。实际上而言,tomcat是Apache服务器的拓展,但是可以独立运行,tomcat可以独立的去处理html和jsp页面。
??

memcached

??
??Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。Memcached基于一个存储键/值对的hashmap。其守护进程(daemon )是用C写的,但是客户端可以用任何语言来编写,并通过memcached协议与守护进程通信。这里主要是做为tomcat的session存储设备。
??

session

??
??在计算机中,尤其是在网络应用中,称为“会话控制”。Session 对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web 页时,如果该用户还没有会话,则 Web 服务器将自动创建一个 Session 对象。当会话过期或被放弃后,服务器将终止该会话。

??在现今的互联网架构中会话保持越来越重要,但是会话的保持却在一定程度上依赖于提供服务的服务器上,随着并发量的不断提升,服务器最终会由于负载过高而宕机,因此引入了负载均衡机制,但是负载均衡的调度会使得同一用户的请求被调度到不同的主机之上,会严重的影响到session的保存。
??

实验模拟

??
这里打算实现两种session会话的保持方案。
一.Tomcat自身的session复制集群方案;
二.Tomcat+memcached的共享session保持方案。
??

实验设备

??

ip地址 操作系统
nginx代理 192.168.99.131 CentOS7.4
tomcat1 192.168.99.130 CentOS7.4
tomcat2 192.168.99.240 CentOS7.4

??
环境配置
??
清空防火墙规则,关闭selinux,安装jdk

#清空防火墙规则
iptables -F
iptables -X

#临时设置关闭selinux
setenforce 0

#安装jdk,centos7的源默认最高支持jdk1.8
yum install java-1.8.0-openjdk-devel -y

??

tomcat自身集群session复制实现会话保持

??

基础知识

??
??在<engine>或者<host>配置启用集群,使用Delta Manager to replicate session deltas 启用所有的会话复制。通过all-to-all,意味着会话会被复制到进群中的其他所有节点,这样是设计适用于较小的集群,但是,并不建议在较大的集群上去部署,在使用delta管理器的时候,它将会复制到所有的节点上,甚至是还没有部署应用程序的节点。官方默认提供了一个backupManager的管理器,这个管理器的作用是仅仅将会话数据复制到一个备份节点上,而且,仅仅复制到已经部署了应用的节点,但是这个管理器目前仍在测试阶段,不能保证其正常运行。
??

设计示意图

??
技术分享图片
??

开始部署

??

一.配置反向代理层nginx

??
1.安装nginx并设置代理

#安装nginx,nginx在epel源,因此未安装epel源的话要先安装epel源
yum instll nginx -y

2.修改默认的nginx配置文件

vim /etc/nginx/nginx.conf

技术分享图片
3.编辑代理配置文件

 vim /etc/nginx/conf.d/proxy.conf 

upstream web {
        server 192.168.99.130:80;
        server 192.168.99.240:80;
}

server {
        listen 80 default_server;
        index index.jsp index.html;
        server_name douma.com;
        location / {
                proxy_pass http://web;
        }
}

技术分享图片

4.检查语法并启动nginx

#检查语法
nginx -t

#检查无误后启动nginx
systemctl start nginx 

技术分享图片
??

二.配置tomcat1

??
1.安装tomcat以及对应的其他管理工具

yum install tomcat tomcat-lib tomcat-admin-webapps tomcat-webapps tomcat-docs-webapp -y

2.配置tomcat显示session会话信息

mkdir -pv /appdata/webapps/ROOT/{lib,classes,WEB-INF}

#编写session会话显示页
vim /appdata/webapps/ROOT/index.jsp

                         <%@ 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("magedu.com","magedu.com"); %>
                                                                        <td><%= session.getId() %></td>
                                                                </tr>
                                                                <tr>
                                                                        <td>Created on</td>
                                                                        <td><%= session.getCreationTime() %></td>
                                                                </tr>
                                                        </table>
                                                </body>
                                        </html>

#复制全局web.xml到对应目录并修改
cp /etc/tomcat/web.xml  /appdata/webapps/ROOT/WEB-INF/

#编辑web.xml
添加<distributable/>字段

技术分享图片

3.修改server.xml配置文件

vim /etc/tomcat/server.xml 

        <Host name="douma.com" appBase="/appdata/webapps" unpackWARs="ture" autoDeploy="true">
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="douma.com_access_log." suffix=".txt"
               pattern="%h %l %u %t "%r" %s %b" />

       <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.99.130"  #这里改为本机地址
                        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>

4.启动tomcat并访问8080端口

    systemctl start tomcat

技术分享图片

5.安装nginx

yum install nginx -y

6.编写反代配置

#编辑默认配置文件取消default_server

技术分享图片

#添加反代配置
vim /etc/nginx/conf.d/proxy.conf 

upstream web {
        server 192.168.99.130:8080;
}
server {
        listen 80 default_server;
        server_name douma.com;
        location / {
                index index.jsp index.html;
                proxy_pass http://web;
        }
}

技术分享图片

7.启动nginx

systemctl start nginx

技术分享图片
??

三.配置tomcat2

??
基本配置和tomcat1相同,仅仅需要在编写页面,配置nginx代理配置和配置集群服务时候修改ip地址。

vim /appdata/webapps/ROOT/index.jsp 

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

验证
技术分享图片
??

验证是否能够共享session

??
访问前端nginx调度器
技术分享图片
刷新一下
技术分享图片
虽然刷新了页面,也同时由另一台服务器响应,但是session会话信息还是很好的保存下来了。
??

配置文件介绍

??

#classname配置tomcat集群在进行信息传递时互相使用什么类来进行传递;channelsendoptions可以设置为2,4,8.10;
 #2表示确认发送 Channel.SEND_OPTIONS_USE_ACK
 #4表示同步发送Channel.SEND_OPTIONS_SYNCHRONIZED_ACK 
 #8表示你异步发送Channel.SEND_OPTIONS_ASYNCHRONOUS
 #10表示 在异步模式下,可以通过加上确认发送(Acknowledge)来提高可靠性

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

#manager决定如何管理集群的session信息,
#className-指定实现org.apache.catalina.ha.ClusterManager接口的类,信息之间的管理.
#expireSessionsOnShutdown-设置为true时,一个节点关闭,将导致集群下的所有Session失效
#notifyListenersOnReplication-集群下节点间的Session复制、删除操作,是否通知session listeners
#maxInactiveInterval-集群下Session的有效时间(单位:s)。
#maxInactiveInterval内未活动的Session,将被Tomcat回收。默认值为1800s
        <Manager className="org.apache.catalina.ha.session.DeltaManager"
                expireSessionsOnShutdown="false"
                notifyListenersOnReplication="true"/>
#Channel是Tomcat节点之间进行通讯的工具。
#Channel包括5个组件:Membership、Receiver、Sender、Transport、Interceptor
        <Channel className="org.apache.catalina.tribes.group.GroupChannel">

#Membership维护集群的可用节点列表。它可以检查到新增的节点,也可以检查到没有心跳的节点
#className-指定Membership使用的类
#address-组播地址
#port-组播端口
#frequency-发送心跳(向组播地址发送UDP数据包)的时间间隔(单位:ms)。默认值为500
#dropTime-Membership在dropTime(单位:ms)内未收到某一节点的心跳,则将该节点从可用节点列表删除。默认值为3000     
        <Membership className="org.apache.catalina.tribes.membership.McastService"
                        address="228.0.0.4"
                        port="45564"
                        frequency="500"
                        dropTime="3000"/>
#Receiver : 接收器,负责接收消息BioReceiver(阻塞式)、NioReceiver(非阻塞式)
#className-指定Receiver使用的类
#address-接收消息的地址(默认是自动,但是最好手动更改为本地网卡对外ip)
#port-接收消息的端口
#autoBind-端口的变化区间
#如果port为4000,autoBind为100,接收器将在4000-4099间取一个端口,进行监听
#selectorTimeout-NioReceiver内轮询的超时时间
#maxThreads-线程池的最大线程数
        <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                        address="192.168.99.240"
                        port="4000"
                        autoBind="100"
                        selectorTimeout="5000"
                        maxThreads="6"/>
#sender:发送器负责发送消息 sender内嵌了transport组件,transport组件是负责真正传送消息
        <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
 #Transport分为两种:bio.PooledMultiSender(阻塞式)、nio.PooledParallelSender(非阻塞式) 
                <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
        </Sender>

 #MessageDispatch15Interceptor-查看Cluster组件发送消息的方式是否设置为Channel.SEND_OPTIONS_ASYNCHRONOUS(Cluster标签下的channelSendOptions为8时)。
 #当设置为Channel.SEND_OPTIONS_ASYNCHRONOUS时,MessageDispatch15Interceptor先将等待发送的消息进行排队,然后将排好队的消息转给Sender
        <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
        <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
        </Channel>

#Valve :可以作为过滤器,ReplicationValve-在处理请求前后打日志;过滤不涉及Session变化的请求。   #vmRouteBinderValve-Apache的mod_jk发生错误时,保证同一客户端的请求发送到集群的同一个节点
        <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
                filter=""/>
        <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>

#Deployer:同步集群下的所有节点的一致性
        <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
                tempDir="/tmp/war-temp/"
                deployDir="/tmp/war-deploy/"
                watchDir="/tmp/war-listen/"
                watchEnabled="false"/>
#ClusterListener : 监听器,监听Cluster组件接收的消息,使用DeltaManager时,Cluster接收的信息通过ClusterSessionListener传递给DeltaManager
        <ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>
        <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
        </Cluster>

??

tomcat+memcached实现session会话保持

??

设计架构图

??
图中的memcached在两个tomcat节点都会安装,来实现冗余。图中独立摘出来仅仅是为了方便理解。
技术分享图片
??

开始部署

??

一.配置nginx代理

??
1.安装nginx并设置代理

#安装nginx,nginx在epel源,因此未安装epel源的话要先安装epel源
yum instll nginx -y

2.修改默认的nginx配置文件

vim /etc/nginx/nginx.conf

技术分享图片
3.编辑代理配置文件

 vim /etc/nginx/conf.d/proxy.conf 

upstream web {
        server 192.168.99.130:80;
        server 192.168.99.240:80;
}

server {
        listen 80 default_server;
        index index.jsp index.html;
        server_name douma.com;
        location / {
                proxy_pass http://web;
        }
}

技术分享图片

4.检查语法并启动nginx

#检查语法
nginx -t

#检查无误后启动nginx
systemctl start nginx 

技术分享图片
??

二.配置tomcat1节点

??
1.安装nginx配置本地代理

yum install nginx -y

    #编辑默认配置文件取消default_server
    vim /etc/nginx/nginx.conf

    #创建新的代理配置文件
    vim /etc/nginx/conf.d/proxy.conf

    upstream web {
        server 192.168.99.130:8080;
}
server {
        listen 80 default_server;
        server_name douma.com;
        location / {
                index index.jsp index.html;
                proxy_pass http://web;
        }
}

#语法检查无误后启动nginx
nginx -t
systemctl start nginx

2.安装tomcat和其他管理工具

yum install tomcat tomcat-lib tomcat-admin-webapps tomcat-webapps tomcat-docs-webapp -y

3.创建测试项目

mkdir -pv /appdata/webapps/ROOT/{lib,classes,WEB-INF}

#创建测试页面
vim /appdata/webapps/ROOT/index.jsp

                              <%@ 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("magedu.com","magedu.com"); %>
                                                                        <td><%= session.getId() %></td>
                                                                </tr>
                                                                <tr>
                                                                        <td>Created on</td>
                                                                        <td><%= session.getCreationTime() %></td>
                                                                </tr>
                                                        </table>
                                                </body>
                                        </html>

#拷贝默认web.xml文件到新建目录
cp /etc/tomcat/web.xml /appdata/webapps/ROOT/WEB-INF/

#修改web.xml文件添加<distributable/>字段

技术分享图片

4.配置memcached的session会话保持

#安装软件包
yum install memcached -y

#下载msm的对应jar包

技术分享图片

将下载的包放置到/usr/share/java/tomcat下

技术分享图片

5.修改server.xml文件

 vim /etc/tomcat/server.xml 

 #配置虚拟主机
 <Host name="douma.com" appBase="/appdata/webapps" unpackWARs="ture" autoDeploy="true">
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="douma.com_access_log." suffix=".txt"
               pattern="%h %l %u %t "%r" %s %b" />
     </Host>                         

 #在host字段内添加

 <Context path="/" docBase="ROOT" reloadable="">
                <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
 #memcached的节点名(节点名自己定义,仅仅是显示)和对应ip端口     
 memcachedNodes="n1:192.168.99.130:11211,n2:192.168.99.240:11211"
 #备用节点设置
                failoverNodes="n1"
                requestUriIgnorePattern=".*.(ico|png|gif|jpg|css|js)$"
                transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
                />
        </Context>

技术分享图片
6.启动tomcat

systemctl start tomcat

7.验证
技术分享图片
??

三.配置tomcat2节点

??
配置基本同配置tomcat1,要注意修改nginx代理后端的ip

nginx proxy.conf
upstream web {
        server 192.168.99.240:8080;
}
server {
        listen 80 default_server;
        server_name douma.com;
        location / {
                index index.jsp index.html;
                proxy_pass http://web;
        }
}

server.xml
<Host name="douma.com" appBase="/appdata/webapps" unpackWARs="ture" autoDeploy="true">
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="douma.com_access_log." suffix=".txt"
               pattern="%h %l %u %t "%r" %s %b" />

        <Context path="/" docBase="ROOT" reloadalbe="">
                <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
                memcachedNodes="n1:192.168.99.130:11211,n2:192.168.99.240:11211"
                failoverNodes="n1"
                requestUriIgnorePattern=".*.(ico|png|gif|jpg|css|js)$"
                transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
                />
        </Context>
        </Host>

技术分享图片
技术分享图片
??

四.配置完成后验证

??
访问代理服务器192.168.99.131

技术分享图片
技术分享图片

msm包的分享链接
https://pan.baidu.com/s/10k85xdXh2_7neCtfr9LNsQ

以上是关于tomcat的session会话保持方案的主要内容,如果未能解决你的问题,请参考以下文章

tomcat基于session会话保持以及msm会话保持

tomcat session会话复制

Apache+Tomcat+Memcached实现会话保持

Nginx+Tomcat+Memcached实现会话保持

session会话-nginx-mysql-tomcat

tomcat session会话保持实验-之Nginx+tomcat+memcached