服务器重启session会销毁吗(服务器关闭session销毁了吗)
session会随着服务器的关闭而消失吗?为什么我重启服务器浏览器不重启浏览器中保存的sessio
1、客户端:默认情况下关闭浏览器 失效SessionId
2、服务器:如tomcat默认情况下 关闭服务器时 序列号session;启动时反序列化
所以正常情况下 重启服务器 是不丢session的
问题:Session的销毁方式到底有哪些?
Session,作为我们离不开的后台的技术,它的出现主要是为了解决 Http 协议的 无状态 特点,用于解决用户状态的存储问题,而往往对于存储来说都会涉及到一个时间问题,下面我们来看看它的销毁方式到底有哪些。
默认时间到期
自己设定到期时间
立刻失效
关闭浏览器
关闭服务器
当客户端第一次请求 servlet 并且操作 session
时,session 对象生成,以 Tomcat 为例,Tomcat 中 session 默认的存活时间为
30min,即你不操作界面的时间,一旦有操作,session 会重新计时。那么 session 的默认时间可以改么?答案是肯定的。可以在
Tomcat 中的 web.xml 文件中进行修改。如下图:
当然除了以上的修改方式外,我们也可以在程序中自己设定 session 的生命周期,通过 session.setMaxInactiveInterval(int); 来设定 session 的最大不活动时间,单位为秒。
HttpSession session=req.getSession();session.setMaxInactiveInterval(5);
当然我们也可以通过 getMaxInactiveInterval(); 方法来查看当前 Session 对象的最大不活动时间。
或者我们也可以通过 session.invalidate(); 方法让 session 立刻失效。
session.invalidate();
session 的底层依赖 cookie
实现,因为不同用户访问服务器要判别到底是使用哪个 session,所以当用户第一次访问服务器的时候往往会把一个 session id 通过
cookie 存储到用户端,并且该 cookie 的有效时间为关闭浏览器,从而 session 在浏览器关闭时也相当于失效了(因为没有
session id 再与之对应)。如下图,关闭后再打开,重新给浏览器分配了个 session id。
需要注意的是这里只是 cookie 失效了,你再访问相当于服务器把你当成了新用户,又给你创建了一个 session,并没有把之前的 session 对象销毁。
当非正常关闭服务器时,session 销毁;当正常关闭服务器时,session 将被 序列化 到磁盘上,在工作空间 work 目录下的 SESSION.ser 文件中,如果对象被保存在了 session 中,服务器在关闭时要把对象序列化到硬盘,这个对象就必须实现 Serializable 接口,下次启动服务时,自动加载到内存。如下图,正常关闭后可以看到文件夹中多了一个 SESSIONS.ser 文件,再次启动服务器则文件消失。
从图中除了看到 Cookie 的名称和内容外,我们还需要关心一个信息, 到期时间 ,到期时间用来指定该 cookie 何时失效。默认为当前浏览器关闭即失效。我们可以手动设定 cookie 的有效时间(通过到期时间计算),通过 setMaxAge(int expiry); 方法设定 cookie 的最大有效时间,以 秒 为单位。
大于 0 的整数,表示存储的秒数;若为负数,则表示不存储该 cookie;若为 0,则删除该 cookie。
负整数 :cookie 的 maxAge 属性的默认值就是 -1,表示只在浏览器内存中存活,一旦关闭浏览器窗口,那么 cookie 就会消失。
正整数 :表示 cookie 对象可存活指定的秒数。当生命大于 0 时,浏览器会把 Cookie 保存到硬盘上,就算关闭浏览器,就算重启客户端电脑,cookie 也会存活相应的时间。
零 :cookie 生命等于 0 是一个特殊的值,它表示 cookie 被作废!也就是说,如果原来浏览器已经保存了这个 Cookie,那么可以通过 Cookie 的 setMaxAge(0) 来删除这个 Cookie。 无论是在浏览器内存中,还是在客户端硬盘上都会删除这个 Cookie。
服务端session笔记
注:以下内容基于以tomcat作为web服务器
session是http协议无状态问题的常见解决方案之一 ,用户登录成功之后,把用户信息保存到session(默认储存在服务端的内存)。对于浏览器发起的HTTP请求,可以根据session中是否存在用户信息判断用户是否登录,也方便业务逻辑中获取当前会话用户信息。
服务端创建session时,会生成JSESSIONID作为唯一标识,并将一个key为"JSESSIONID"的cookie返回给前端(前提是浏览器支持cookie),之后,根据浏览器发起请求时携带的JSESSIONID判断用户身份。
tomcat的JSESSIONID生成的机制是一个随机数加时间加上jvm的id值,jvm的id值会根据服务器的硬件信息计算得来,因此不同jvm的id值都是唯一的。
当后端显式调用request.getSession()或request.getSession(true)时,会创建session(注意:需要显式调用,spring或tomcat不会自动生成)
request.getSession()有个重载方法request.getSession(boolean create)
create为true表示,若可以根据前端cookie中的JSESSIONID找到对应的session,则返回该session,否则重新创建一个session,并把新的JSESSIONID返回给前端。
create为false表示,若可以根据前端cookie中的JSESSIONID找到对应的session,则返回该session,否则返回null。
request.getSession()等价于request.getSession(true)
session是http协议无状态问题的常见解决方案之一,但在用户量大,或者分布式系统等场景下,该方案有许多弊端。
1.session默认储存在服务端内存,用户量大时占用内存多
2.需要处理session共享,用户在一台服务器登录后,集群内其他机器没有该用户的session,需要用某些方式实现session共享,并保持一致性,即同步修改所有机器的session
3.同样的数据保存在多台服务器,数据冗余
4.如果使用cookie发送JSESSIONID到服务端,则不支持跨域请求
5.如果浏览器cookie被禁用,就需要用其余方式保存JSESSIONID
6.如果session没有持久化,重启服务器后session就没了
修改负载均衡策略为按ip负载(即同一个ip只访问同一台机器),这样就绕开了session共享的问题(默认策略一般是轮询)
弊端
按ip负载策略和轮询策略,本质上是按用户负载和按请求负载,这两种策略的区别在于, 按请求负载更加均衡 ,比如A、B服务器都有20个用户,A服务器的20个用户相比B服务器更加活跃,那么A服务器的压力就更大。
集成spring-session-redis(网上很多教程),先集成redis,然后在启动类加上@EnableRedisHttpSession注解,这样操作session时,会自动把数据持久化到redis集群
tomcat 配置session复制(未做了解)
同时使用token+session,token用于接口鉴权,session用于保存用户信息。
增加一个拦截器,在找不到session时,根据token反解析出用户信息,然后存入session。
(一般公司会有统一的用户中心,提供校验token并返回用户身份的接口)
严格来说,本方案不算是session共享方案,因为不同服务端的session id不一致,每次请求不同服务器,带上来的session id在本服务器找不到,就产生新的session,直到有效期到期才销毁,严重浪费内存
1.最常见的方式: cookie
2.如果cookie被禁止,可以用URL重写技术,把session id拼接到URL中
3.在表单添加隐藏字段,提交表单时把session id传到服务端
先说结论:如果服务器是集群,且没有配置会话保持,同一个浏览器窗口的JSESSIONID就会变化
用户在A服务器登录成功后,A服务器把key为JSESSIONID的cookie返回给用户,然后携带该JSESSIONID请求B服务器,B服务器找不到该JSESSIONID对应的session,就会创建新的session,把新的JSESSIONID返回给用户。
取决于JSESSIONID的保存方式
如果保存在cookie,要看cookie有没有设置有效期,如果没设有效期,重启浏览器cookie就没了,如果设了有效期,重启浏览器cookie还在。
如果使用URL重写或表单隐藏字段的方式,要看JSESSION具体保存在哪
对于单机应用,JSESSIONID可以用于校验接口(类似于token),后端如果能根据JSESSIONID获取到对应session(即request.getSession(false)不为空),说明该请求有效。但是服务器一旦重启,用户登录就失效了,因为session放在内存中。
如果使用token做接口校验,不仅可以适用于分布式应用,后端重启也不会影响用户的登录态。
Session在浏览器重新打开后,是不是失效了
先说结论:
重新打开浏览器,原来的session,还是保留在服务器端,只不过再也找不到了。
新打开的浏览器,会创建一个新的session,保存到服务器。浏览器不关闭,则这个session只要没销毁,就可以一直访问到,比如新开标签页。
当用户第一次访问Web应用中支持Session的某个网页时,就会开始一个新的Session,
那么接下来当用户浏览这个Web应用的不同网页时,始终处于一个Session中
再详细些:
当一个Session开始时,Servlet容器会创建一个HttpSession对象,那么在HttpSession对象中,可以存放用户状态的信息
Servlet容器为HttpSession对象分配一个唯一标识符即Sessionid,Servlet容器把Sessionid作为一种Cookie保存在客户端的 浏览器 中
用户每次发出Http请求时,Servlet容器会从HttpServletRequest对象中取出Sessionid,然后根据这个Sessionid找到相应的HttpSession对象,从而获取用户的状态信息
以上就是Session的运行机制,但是还没有提到Session的生命周期,再往下了解!
其实让Session结束生命周期,有以下两种办法:
一个是Session.invalidate()方法,不过这个方法在实际的开发中,并不推荐,可能在强制注销用户的时候会使用;
一个是当前用户和服务器的交互时间超过默认时间后,Session会失效
我们知道Session是存在于服务器端的,当把浏览器关闭时,浏览器并没有向服务器发送
任何请求来关闭Session,自然Session也不会被销毁,但是可以做一点努力,在所有的
客户端页面里使用js的window.onclose来监视浏览器的关闭动作,然后向服务器发送一
个请求来关闭Session,但是这种做法在实际的开发中也是不推荐使用的,最正常的办法
就是不去管它,让它等到默认的时间后,自动销毁
那么为什么当我们关闭浏览器后,就再也访问不到之前的session了呢?
其实之前的Session一直都在服务器端,而当我们关闭浏览器时,此时的Cookie是存在
于浏览器的进程中的,当浏览器关闭时,Cookie也就不存在了。
其实Cookie有两种:
一种是存在于浏览器的进程中;
一种是存在于硬盘上
而session的Cookie是存在于浏览器的进程中,那么这种Cookie我们称为会话Cookie,
当我们重新打开浏览器窗口时,之前的Cookie中存放的Sessionid已经不存在了,此时
服务器从HttpServletRequest对象中没有检查到sessionid,服务器会再发送一个新的存
有Sessionid的Cookie到客户端的浏览器中,此时对应的是一个新的会话,而服务器上
原先的session等到它的默认时间到之后,便会自动销毁。
ps:
当在同一个浏览器中同时打开多个标签,发送同一个请求或不同的请求,仍是同一个session;
当不在同一个窗口中打开相同的浏览器时,发送请求,仍是同一个session;
当使用不同的浏览器时,发送请求,即使发送相同的请求,是不同的session;
当把当前某个浏览器的窗口全关闭,再打开,发起相同的请求时,就是本文所阐述的,是不同的session,但是它和session的生命周期是没有关系的.