之前在学习的时候没怎么注意,今天又回过头来仔细研究研究了一下Session的生命周期。css
Session存储在服务器端,通常为了防止在服务器的内存中(为了高速存取),Sessinon在用户访问第一次访问服务器时建立,须要注意只有访问JSP、Servlet等程序时才会建立Session,只访问HTML、IMAGE等静态资源并不会建立Session,可调用request.getSession(true)强制生成Session。html
Session何时失效?前端
1. 服务器会把长时间没有活动的Session从服务器内存中清除,此时Session便失效。Tomcat中Session的默认失效时间为20分钟。java
2. 调用Session的invalidate方法。linux
Session对浏览器的要求:nginx
虽 然Session保存在服务器,对客户端是透明的,它的正常运行仍然须要客户端浏览器的支持。这是由于Session须要使用Cookie做为识别标志。 HTTP协议是无状态的,Session不能依据HTTP链接来判断是否为同一客户,所以服务器向客户端浏览器发送一个名为JSESSIONID的 Cookie,它的值为该Session的id(也就是HttpSession.getId()的返回值)。Session依据该Cookie来识别是否 为同一用户。web
该Cookie为服务器自动生成的,它的maxAge属性通常为-1,表示仅当前浏览器内有效,而且各浏览器窗口间不共享,关闭浏览器就会失 效。所以同一机器的两个浏览器窗口访问服务器时,会生成两个不一样的Session。可是由浏览器窗口内的连接、脚本等打开的新窗口(也就是说不是双击桌面 浏览器图标等打开的窗口)除外。这类子窗口会共享父窗口的Cookie,所以会共享一个Session。正则表达式
注意:新开的浏览器窗口会生成新的Session,但子窗口除外。子窗口会共用父窗口的Session。例如,在连接上右击,在弹出的快捷菜单中选择"在新窗口中打开"时,子窗口即可以访问父窗口的Session。apache
若是客户端浏览器将Cookie功能禁用,或者不支持Cookie怎么办?例如,绝大多数的手机浏览器都不支持Cookie。Java Web提供了另外一种解决方案:URL地址重写。centos
URL地址重写是对客户端不支持Cookie的解决方案。URL地址重写的原理是将该用户Session的id信息重写到URL地 址中。服务器可以解析重写后的URL获取Session的id。这样即便客户端不支持Cookie,也可使用Session来记录用户状态。 HttpServletResponse类提供了encodeURL(String url)实现URL地址重写,该方法会自动判断客户端是否支持Cookie。若是客户端支持Cookie,会将URL原封不动地输出来。若是客户端不支持Cookie,则会将用户Session的id重写到URL中。
注意:TOMCAT判断客户端浏览器是否支持Cookie的依据是 请求中是否含有Cookie。尽管客户端可能会支持Cookie,可是因为第一次请求时不会携带任何Cookie(由于并没有任何Cookie能够携 带),URL地址重写后的地址中仍然会带有jsessionid。当第二次访问时服务器已经在浏览器中写入Cookie了,所以URL地址重写后的地址中 就不会带有jsessionid了。
1、使用tomcat自带的cluster方式,多个tomcat间自动实时复制session信息,配置起来比较简单。但这个方案的效率比较低,在大并发下表现并很差。
1.系统环境
系统:centos6.5 主机:172.16.20.54(tomcat1) 172.16.20.55(tomcat2) 172.16.20.51(nginx) Tomcat:apache-tomcat-7.0.54.tar.gz Jdk: jdk-7u75-linux-x64.tar.gz Nginx: nginx-1.2.7.tar.gz
2.配置tomcat集群
我这里采用主机的默认配置文件,这里不作性能设置的说明,具体调优参数能够参考tomcat官网。首先在server.xml文件把cluster 集群功能打开便可。而后在<Engine>上添加集群节点名。这个非必须设置,我这里为了演示效果,因此把集群节点名添加上去。
3.在web.xml上添加<distributable />
使用distributable元素是告诉servlet/JSP容器,编写的应用将在分布式Web容器中部署,由于咱们这里是用默认的配置文档,因此咱们应该在webapps下的web.xml文件中添加<distributable />元素。
备注:
4.编写测试页面
分别在tomcat1和tomcat2主机上编写index.jsp文件,将其放在webapps/ROOT下,文件内容以下:
<%@ page language=”java” %>
<html>
<head><title>TomcatA</title></head>
<body>
<h1><font color=”blue”>TomcatA </font></h1>
<table align=”centre” border=”1″>
<tr>
<td>Session ID</td>
<td><%= request.getSession().getId() %></td>
</tr>
</table>
</body>
</html>
<%@ page language=”java” %>
<html>
<head><title>TomcatB</title></head>
<body>
<h1><font color=”blue”>TomcatA </font></h1>
<table align=”centre” border=”1″>
<tr>
<td>Session ID</td>
<td><%= request.getSession().getId() %></td>
</tr>
</table>
</body>
</html>
Nginx不是咱们重点的配置内容,因此我这里只贴upstream的配置,默认的权重都是1:
upstream test{
server 172.16.20.54:8080;
server 172.16.20.55:8080;
}
6. 测试session id是否一致
2、利用nginx的upstream模块,基于ip hash访问策略,保证访问的ip始终被路由到同一个tomcat实例上,这个配置只要在 nginx上作配置便可,tomcat无需配置。但若是应用是某一个局域网大量用户同时登录,负载策略会显得不均衡,且若是tomcat实例出现故 障,session将丢失。
1.系统环境
系统:centos6.5
主机:172.16.20.54(tomcat1) 172.16.20.55(tomcat2) 172.16.20.51(nginx)
Tomcat:apache-tomcat-7.0.54.tar.gz
Jdk: jdk-7u75-linux-x64.tar.gz
Nginx: nginx-1.2.7.tar.gz
2.配置nginx反向代理tomcat集群
upstream test{
server 172.16.20.54:8080;
server 172.16.20.55:8080;
ip_hash;
}
备注:tomcat不用作任何配置,测试脚本仍是和以前的同样
这实际上会有一个很大的问题就是容错率不高,并且只要当前的tomcat实例出问题了,nginx不得不从新分配下一个实例,天然你的session id也改变了。生产环境不建议用这个方案。
3、利用memcached把多个tomcat的session集中管理,前端在利用nginx负载和动静态资源分离,在兼顾系统水平扩展的同时又能保证较高的性能。
1.系统环境
系统:centos6.5
主机:172.16.20.54(tomcat1) 172.16.20.55(tomcat2) 172.16.20.51(nginx)
Tomcat:apache-tomcat-7.0.54.tar.gz
Jdk: jdk-7u75-linux-x64.tar.gz
Nginx: nginx-1.2.7.tar.gz
jar包:asm-3.2.jar minlog-1.2.jar reflectasm-1.01.jar kryo- 1.04.jar kryo-serializers-0.11.jar memcached-session-manager-1.8.3.jar memcached-session-manager-tc7-1.8.3.jar msm-kryo-serializer-1.8.3.jar spymemcached-2.11.1.jar
2.配置nginx反向代理tomcat集群
upstream test{
server 172.16.20.54:8080;
server 172.16.20.55:8080;
ip_hash;
}
注:只能指定ip_hash是由于让主机能根据IP地址到指定的实例上,即便tomcat实例出现故障,也能够从memcached里获取 session的值,因此不存在方案二的问题,实际上我认为方案三是结合了方案一和二的优势而设计的,若是你这里不喜欢使用ip_hash也是能够的,这 取决你的自身业务状况。
3.配置memcached
Memcached的安装,这里略过,能够查看我以前写的文章memcached集群及magent缓存代理服务器搭建。这里在主机172.16.20.54开启两个memcached实例,分别是:
/usr/local/memcached/bin/memcached -d -p 11211 -u memcached -m 256 -c 1024 -P /var/run/memcached/memcached_11211.pid
/usr/local/memcached/bin/memcached -d -p 11212 -u memcached -m 256 -c 1024 -P /var/run/memcached/memcached_11212.pid
Memcached1: 172.16.20.54 11211
Memcached1: 172.16.20.54 11212
4. 配置tomcat
能够在context.xml或者server.xml上配置集群文件,我这里在context.xml上添加memcached-session-manager配置语句:
<Manager className=”de.javakaffee.web.msm.MemcachedBackupSessionManager”
sticky=”false”
memcachedNodes=”n1:172.16.20.54:11211 n2:172.16.20.54:11212″
failoverNodes=””
requestUriIgnorePattern=”.*\.(png|gif|jpg|css|js|ico)$”
sessionBackupAsync=”false”
sessionBackupTimeout=”500″
transcoderFactoryClass=”de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory”
customConverter=”de.javakaffee.web.msm.serializer.kryo.JodaDateTimeRegistration,de.javakaffee.web.msm.serializer.kryo.WicketSerializerFactory”
/>
sticky=”false” #非黏性设置,默认为黏性
memcachedNodes #配置memcached节点
failoverNodes #默认为空,若是这里指定memcached冗余节点的话,sticky必定要为true,不然会报错
requestUriIgnorePattern #忽略session的正则表达式
sessionBackupAsync #指定Session是否应该被异步保存到Memcached中。 若是被设置为true,backupThreadCount设置起做用,若是设置false,经过sessionBackupTimeout
sessionBackupTimeout #设置备份一个Session所用的时间,若是操做超过期间那么保存失败。此属性只在sessionBackupAsync=”false”是起做用。默认100毫秒
transcoderFactoryClass #默认 为 de.javakaffee.web.msm.JavaSerializationTranscoderFactory此属性值是建立序列化和反序列 化保存到Memcached中的Session的编码转换器的工厂类名。这个指定的类必须实现了 de.javakaffee.web.msm.TranscoderFactory和提供一个无参的构造方法。
customConverter #可选项,自定义转换器容许您提供应用程序特定类型的自定义序列化。多个自定义转换器类名称指定逗号隔开(可选空间逗号后)。转换器类必须在类路径中可用的web应用程序(WEB-INF/lib中),在这里能够不设置。
具体参考参数请查看:
https://code.google.com/p/memcached-session-manager/wiki/SetupAndConfiguration
5.测试session id是否一致
从图中能够看出,session一致,且能够看出是从memcached1中获取的。
假如,memcached1出现故障,看下session值会不会自动复制到memcached2中去:
从图中能够看出session的值是从memcached2中获取的,且session值保持一致。
至此:tomcat集群session共享配置方案配置完成。