一、Session的定义

  在计算机科学中,特别是在网络中,session是两个或更多个通信设备之间或计算机和用户之间的临时和交互式信息交换。session在某个时间点建立,然后在之后的某一时间点拆除。建立的通信session可以在每个方向上涉及多个消息。session通常是有状态的,这意味着至少一个通信部分需要保存关于会话历史的状态信息以便能够进行通信,而在无状态通信中,通信由具有响应的独立请求组成。——Wikipedia

  Session:在计算机中,尤其是在网络应用中,称为“会话控制”。Session 对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web 页时,如果该用户还没有会话,则 Web 服务器将自动创建一个 Session 对象。当会话过期或被放弃后,服务器将终止该会话。Session 对象最常见的一个用法就是存储用户的首选项。例如,如果用户指明不喜欢查看图形,就可以将该信息存储在 Session 对象中。——百度

二、Session的作用与意义

  在WEB应用中,一般都是采用http协议进行通信,但http是一种无状态的通信协议,这里的无状态是指协议对于事务处理没有记忆能力,在会话结束后,服务器不知道客户端是什么状态。在http协议初期,为了保证WEB的并发访问处理能力,http协议不会保存客户端访问的任何状态信息。后来http协议中加入了keep-alive功能,这是一种会话保持机制,这样便可以将会话持续保持一段时间,当用户在这个时间段又一次访问时会提高响应速度节省资源,但keep-alive也不会记录用户的状态,只是让连接保持一段时间,当用户超过这个时间段再次访问,依然还是会当做新请求进行处理。但在WEB应用中有很多场景都需要根据用户的历史访问状态来将请求分配给后端服务器处理,例如登录记录、购物车记录,浏览记录等,用户每次访问都无法找到以前的记录是很影响用户体验的,这样就诞生了cookie和session机制。

  先来说说cookie,当用户访问www.abc.com时需要登录,因为http是无状态的,所以导致访问www.abc.com/xxx又需要重新登录,这样是很头痛的事情,cookie的出现解决了这个问题,cookie可以将用户的少量信息保存至用户客户端本地,它将www.abc.com域名作为一个全局,在用户登录此域名下的所有URI时都不需要重新登陆。但用户本地的存储大小是有限的,并且将一些私密信息储存在本地是有安全风险的。

  如何保证用户体验,又能保证安全性,这就是Session的意义,session也是一种用户状态储存机制,但与cookie不同的是,session储存在后端服务器的内存中。session在web应用中有着非常重要的意义,它可以很方便很安全的控制访问权限。

二、常见的Session会话保持方式

1.Session sticky(session会话粘性)

会话粘性是指在用户第一次访问后按一定的算法与之将其中一台后端服务器做绑定,一般分为两种:

a.souce_ip:如nginx中的ip_hash算法、LVS中的sh算法

b.cookie:HAProxy中的cookie

2.Session Cluster(session集群)

  Session Cluster是指将后端服务器组成一个集群,共享所有的session, 当某一台服务器故障后不至于影响用户体验。这种方法一般用在后端服务器较少的情况(3-4台),因为当服务器太多时会占用大量的IO,影响集群性能。

下面将以Tomcat为例介绍介绍这种session保持机制。

1.实现基础

Tomcat Session Cluster的实现是利用组播将集群中的session进行共享,这与keepalived类似。Tomcat原生就支持这种机制,所以配置起来比较简单,但不能支持太多的主机,

2.结构与IP分配

Nginx主机:IP:192.168.29.109

Tomcat主机集群:192.168.29.107、192.168.29.132、192.168.29.110

安装好Nginx和Tomcat,教程:https://www.cnblogs.com/readygood/p/9801253.html

关闭防火墙和Selinux

1.配置Nginx

vim /etc/nginx/nginx.conf #配置主配置文件
upstream tcsv { #在http模块中插入upstream模块
server 10.10.10.130:;
server 10.10.10.131:;
server 10.10.10.132:;
}
vim /etc/nginx/conf.d/tomcat.conf #添加虚拟主机
server {
listen ;
server_name www.ready.com;
location / {
proxy_pass http://tcsv;
}
}

2.配置Tomcat,创建.jsp测试页

mkdir -pv /var/lib/tomcat/webapps/test/{WEB-INF,META-INF,classes,lib} #创建jsp文件所需目录
vim /var/lib/tomcat/webapps/test/index.jsp #创建jsp测试文件,功能为session ID监控
<%@ page language="java" %>
<html>
<head><title>TomcatA</title></head>
<body>
<h1><font color="red">Tomcat.ready.com</font></h1> #将3台Tomcat主机配置为不同颜色,我这里分别是red、green、blue
<table align="centre" border="">
<tr>
<td>Session ID</td>
<% session.setAttribute("ready.com","ready.com"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>

3.启动Nginx和Tomcat,并刷新页面(修改hosts添加本地解析)

不同颜色代表不同主机的响应,我们可以发现就算响应的主机相同Session ID也不同,这说明Session机制未开启(因为前端Nginx调度默认采用的rr算法),就算在同一主机访问也会被识别为不同用户。

4.配置Tomcat Cluster服务

Tomcat原生就是支持此服务的,所以只需要在/etc/tomcat/server.xml中嵌入 <Cluster> 组件即可,要注意的是 <Cluster> 组件只能用在 <Engine> 和 <Host> 中。注意事项如下:

1.默认多播地址为228.0.0.4

2.默认多播端口是45564(端口和地址一起决定集群成员。

3.广播的IP是 java.net.InetAddress.getLocalHost().getHostAddress() (确保没有广播127.0.0.1,这是一个常见的错误)

4.监听复制消息的TCP端口是范围4000-4100中的第一个可用服务器套接字

5.侦听器被配置为 ClusterSessionListener

6.配置两个拦截器 TcpFailureDetector 和 MessageDispatch15Interceptor

vi /etc/tomcat/server.xml
a.将下面的代码插入 <Engine> 或者 <Host> 中
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
channelSendOptions=""> <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="" #默认端口
frequency=""
dropTime=""/>
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
address="192.168.29.132" #填写本机IP地址,默认为auto
port=""
autoBind=""
selectorTimeout=""
maxThreads=""/> <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>
b.将默认web.xml文件(/etc/tomcat/web.xml)复制到事先创建好的/usr/share/tomcat/webapps/test/WEB-INF/目录下并修改

web.xml文件是用来初始化配置信息:比如Welcome页面、servlet、servlet-mapping、filter、listener、启动加载级别等。

cp /etc/tomcat/web.xml /usr/share/tomcat/webapps/test/WEB-INF/
vim /usr/share/tomcat/webapps/test/WEB-INF/web.xml

在 <web-app> 内任意位置插入代码 <distributable/> ,其他Tomcat主机也做相同操作。

c.重启Tomcat服务,查看Tomcat状态

在日志中看到下面的信息就说明session共享配置成功:

d.刷新页面,观察session ID的变化

可以看到不管怎么刷新Session ID都保持不变,但标题颜色会变化,说明无论去前端Nginx怎么调度Session都没有发生变化。

e.注意事项

1.在插入 <Cluster> 组件时要注意 <Receiver> 中的 address= 的IP配置,尽量不要用“auto”。

2.Tomcat主机的网关一定要设置正确,不然无法发送和接收组播信息。

3.要在日志中看到类似 [tcp://{192, 168, 29, 107}:4000,{192, 168, 29, 107},4000, alive=1037 的信息才说明组播信息成功发送,也可以使用 tcpdump 命令来检查组播信息状态:

tcpdump -i ens33 -nn host 228.0.0.4

3.Tomcat+memcached+msm实现Session共享

  在Tomcat Session Cluster方式实现session共享时,后端不能承载太多的Tomcat主机,只适用于小型的集群使用,为了克服这一问题,我们可以将后端的Tomcat集群的所有session都存放在一个共享的存储中,这样不管用户请求被反代到哪一个后端服务器都不会影响体验。

1.memcached简介

  Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。memcached特性:

1.仅可用来存储可序列化的数据。

2.分布式缓存:互不通信的分布式集群。

3.数据存储在内存中,重启即丢失数据。

4.缓存耗尽:LRU

5.惰性清理机制。

3.安装memcached

  memcached已经收录在yum的base仓库,安装起来非常简单。

~]# yum install -y memcached

  查看memcached的配置文件

~]# cat /etc/sysconfig/memcached
PORT="" #监听端口
USER="memcached" #用户名
MAXCONN="" #最大并发连接数
CACHESIZE="" #缓存空间大小,默认为64MB
OPTIONS=""

  memcached常用选项:

memcached程序的常用选项:
-m <num>:Use <num> MB memory max to use for object storage; the default is 64 megabytes.
-c <num>:Use <num> max simultaneous connections; the default is 1024.
-u <username>:以指定的用户身份来运行进程;
-l <ip_addr>:监听的IP地址,默认为本机所有地址;
-p <num>:监听的TCP端口, the default is port 11211.
-U <num>:Listen on UDP port <num>, the default is port 11211, 0 is off.
-M:内存耗尽时,不执行LRU清理缓存,而是拒绝存入新的缓存项,直到有多余的空间可用时为止;
-f <factor>:增长因子;默认是1.25;
-t <threads>:启动的用于响应用户请求的线程数;

4.Memcached Session Manager(MSM)安装

  MSM是一个将Tomcat Session存储在memcached中的工具,这样就能克服Tomcat自建的session共享机制后端服务器的数量限制。

试验结构图:

5.下载MSM所需.jar文件并放在Tomcat安装目录的lib目录下

  我这里是yum安装的,目录是在/usr/share/java/tomcat/下,需要复制到该目录的文件如下(两台Tomcat主机操作相同),这一步很重要,如果文件版本不对会导致后面session共享不成功,我所用到的版本如下:

memcached-session-manager-1.8..jar
memcached-session-manager-tc7-1.8..jar
msm-javolution-serializer-1.8..jar
spymemcached-2.10..jar
javolution-5.5..jar

放在 /usr/share/java/tomcat/ 目录下

6.在/etc/tomcat/server.xml默认配置内的<Host>上增加<Context>

在两台Tomcat主机上修改相同配置

vim /etc/tomcat/server.xml

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

7.创建java测试项目

192.168.29.107主机上的配置:

mkdir -pv /usr/share/tomcat/webapps/test/WEB-INF/{classes,lib}
vim /usr/share/tomcat/webapps/test/index.jsp
<%@ page language="java" %>
<html>
<head><title>TomcatB</title></head>
<body>
<h1><font color="blue">Tomcat.Ready.com</font></h1>
<table align="centre" border="">
<tr>
<td>Session ID</td>
<% session.setAttribute("ready.com","ready.com"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>

192.168.29.110主机上的配置:

mkdir -pv /usr/share/tomcat/webapps/test/WEB-INF/{classes,lib}
vim /usr/share/tomcat/webapps/test/index.jsp
<%@ page language="java" %>
<html>
<head><title>TomcatB</title></head>
<body>
<h1><font color="red">Jerrmouse.Ready.com</font></h1>
<table align="centre" border="">
<tr>
<td>Session ID</td>
<% session.setAttribute("ready.com","ready.com"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>

8.启动Tomcat和memcached,并查看是否正常运行

systemctl start tomcat
systemctl start memcached
ss -lntup

完成上述步骤后浏览器访问显示如下:

Session ID后面多出了n1字符,并且不断刷新页面Session ID都不会改变,说明MSM+Tomcat的session共享配置成功。

再强调一次,复制到/usr/share/java/tomcat/的jar文件版本很重要。

Session会话保持机制的原理与Tomcat Session共享的几种实现方式(Session Cluster、memcached+MSM)的更多相关文章

  1. 浏览器禁用cookie后php如何保持session会话-use_trans_sid机制

    原文:浏览器禁用cookie后php如何保持session会话-use_trans_sid机制 为防止浏览器禁用cookie导致服务器会话无法保持,php开发了一个机制,该机制开启后,浏览器发起请求后 ...

  2. Tomcat 部署项目的几种常见方式

    转自:https://www.cnblogs.com/yuht/p/5714624.html https://www.cnblogs.com/ysocean/p/6893446.html Tomcat ...

  3. tomcat下jndi的三种配置方式

    jndi(Java Naming and Directory Interface,Java命名和目录接口)是一组在Java应用中访问命名和目录服务的API.命名服务将名称和对象联系起来,使得我们可以用 ...

  4. 【转】tomcat下jndi的三种配置方式

    jndi(Java Naming and Directory Interface,Java命名和目录接口)是一组在Java应用中访问命名和目录服务的API.命名服务将名称和对象联系起来,使得我们可以用 ...

  5. Tomcat部署项目的几种常见方式

    以前学习的时候只知道在Eclipse或者MyEclipse中发布项目到Tomcat,最近实习时发现不同的项目还有不同的发布方式,所以特地学习了Tomcat发布项目的方式,在此记录下来. 1 直接将we ...

  6. tomcat自动缓存的几种解决方式

    第一种方法:打开一个项目,这里我打开的Mail项目,然后点击Myeclipse菜单栏中的project-选择clean: 选择要clean的项目,确定即可不用进入tomcat服务器直接清理缓存. 上面 ...

  7. 分布式Tomcat session会话Sticky Sessions问题

    分布式session会话Sticky Sessions - tomcat_baby的专栏 - CSDN博客https://blog.csdn.net/tomcat_baby/article/detai ...

  8. python+pytest接口自动化(10)-session会话保持

    在接口测试的过程中,经常会遇到有些接口需要在登录的状态下才能请求,否则会提示请登录,那么怎样解决呢? 上一篇文章我们介绍了Cookie绕过登录,其实这就是保持登录状态的方法之一. 另外一种方式则是通过 ...

  9. cookie、localStorage、sessionStorage和会话控制机制

    简介 cookie cookie的内容主要包括:名字Name.值Value.域Domain.路径Path.过期时间Expires/Max-Age.大小Size.HTTP.Secure.SameSite ...

随机推荐

  1. 《Linux就该这么学》第九天课程

    这次课程主要学了如何分区以及RAID技术 有扩展分区:扩展分区可以指定sdb*中的*(1~4)为多少,则其他三个为主分区,扩展分区中的逻辑分区sdb*(*从5开始)无扩展分区:四个皆为主分区 RAID ...

  2. centos7 安装搜狗输入法

    1.root权限,卸载 ibus : yum remove ibus 2.加入EPEL源   sudo yum install epel-release 3.添加mosquito-myrepo源 su ...

  3. Note of Python Turtle

    Note of Python Turtle         Turtle 库函数是 Python语言中一个流行的绘图函数库.Turtle 意思是海龟,在Python中显示为一个小箭头,通过它的移动而留 ...

  4. Pycharm 开发 Django 项目

    1. 安装Pycharm, 自行百度安装教程 2. 安装python3 自行百度安装教程 3. 安装Django框架 使用命令: Window的终端控制台输入:安装Django框架. pip inst ...

  5. json、txt、xlsx

    json:   json异于pickle,无乱码,各语言都支持,但Python各对象只直接接收int,str,(),[],{}.读入txt时只接受str,int变为str(int),()[]{}被js ...

  6. MFC TabCtrl 控件修改标签尺寸

    注意:无论那种方法,都要先设置Tab控件的Style属性为fixed width. 第一种方法 MFC,tabcontrol控件改变标签大小 - CSDN博客 https://blog.csdn.ne ...

  7. 项目Alpha冲刺(团队1/10)

    项目Alpha冲刺(团队1/10) 团队名称: 云打印 作业要求: 项目Alpha冲刺(团队) 作业目标: 完成项目Alpha版本 团队队员 队员学号 队员姓名 个人博客地址 备注 221600412 ...

  8. XCode 无法识别设备

    XCode 取消Unpair Device 后不能读取设备 1:退出XCode 2:断开设备连接 3:在终端执行‘sudo pkill usbmuxd’ 4:重启XCode 5:连接设备即可

  9. JavaScript中关于页面URL地址的获取

    1 window.location.host; //返回url的主机部分,例如 www.xxx.com window.location.hostname; //返回url的主机名,例如 www.xxx ...

  10. 分布式任务调度系统xxl-job相关问题补充

    搭建xxl-job时可能会遇到的问题 邮箱配置不起作用报异常 以163邮箱为例,接收邮件需要开启POP3/STMP服务 光开启服务还不够,需要添加授权码 授权码为手动输入,可以与登录密码不同,所以服务 ...