网站首页 文章专栏 关于session的一些使用总结
关于session的一些使用总结


一、session作用


首先我们知道HTTP协议是无状态的,也就是说每一次请求都是独立的,和上一次请求没有关系,也不会携带信息,那么我们访问网站经常需要存储用户信息,怎么办呢,cookie/ session机制就是一种在客户端与服务器之间保持状态的解决方案。

session中文意思为“回话”,代表服务器与浏览器的一次会话过程,这个过程是连续的,也可以时断时续的,它保存了本次客户端与服务端的通信信息。且session数据是存放在服务端的。



二、session由谁创建?什么样的结构?谁来维护


    当浏览器一次请求时,服务器会从检查cookie里面是否包含sessionId,如果包含说明我们之前创建过session了,就去查找相应的session,如果没查到就创建一个新的;如果cookie里面不包含sessionId,说明之前没有创建过,就开始创建session,创建后的session由tomcat来维护。






创建:当我们浏览器第一次访问服务器时,tomcat的ManagerBase类提供创建sessionid的方法,ManagerBase是所有session管理工具类的基类,它是一个抽象类,所有具体实现session管理功能的类都要继承这个类,该类有一个受保护的方法,该方法就是创建sessionId值的方法:tomcat的session的id值生成的机制是一个随机数加时间加上jvm的id值,jvm的id值会根据服务器的硬件信息计算得来,因此不同jvm的id值都是唯一的,创建完session和sessionId后,将sessionId返回给cookie,下次请求时,通过sessionId来查找相应的session信息,就找到了之前保存的用户信息了。


销毁:当回话过期,过着需要销毁时,程序调用HttpSession.invalidate();程序关闭。并且session并不会因浏览器的关闭直接销毁,迫使服务器为seesion设置了一个失效时间,当距离客户端上一次使用session的时间超过这个失效时间时,服务器就可以认为客户端已经停止了活动,才会把session删除以节省存储空间。


存储结构:创建的session存储在服务器tomcat内存里,当服务器进程被停止或者重启的时候,内存里的session也会被清空,那么我们session相关的信息怎么存储呢,首先它必须被同步操作,因为在多线程环境下session是线程间共享的,而web服务器一般情况下都是多线程的(为了提高性能还会用到池技术);其次,这个数据结构必须容易操作,最好是传统的键值对的存取方式,而且我们也会经常使用setAttribute(String name, Object value, boolean notify),查看源码可以发现其存储结构为concurrentHashMap。


protected Map attributes = new ConcurrentHashMap();

   

     就很明确了,原来tomcat使用了一个ConcurrentHashMap对象存储数据,这是java的concurrent包里的一个类。它刚好满足了我们所猜测的两点需求:同步与易操作性。

    那么tomcat又是用什么数据结构来存储所有的session对象呢?果然还是ConcurrentHashMap(在管理session的org.apache.catalina.session. ManagerBase类里):


protected Map sessions = new ConcurrentHashMap();



当浏览器禁用cookie则么办呢?


tomcat内部也做了处理,就是url重写,URL回写是指tomcat在发送给浏览器页面的所有链接中都携带JSESSIONID的参数,这样客户端点击任何一个链接都会把JSESSIONID带回tomcat。如果直接在浏览器输入服务端资源的url来请求该资源,那么Session是匹配不到的。

tomcat对Session的实现,是一开始同时使用Cookie和URL回写机制,如果发现客户端支持Cookie,就继续使用Cookie,停止使用URL回写。如果发现Cookie被禁用,就一直使用URL回写。




三、分布式集群下的session处理


如果我们业务量很大,部署了分布式tomcat集群,那么由于session是存放于单独tomcat的内存中,如果访问到其他tomcat,我们的session就查不到了,此时就需要将session再做处理,一般的处理方式有几下几种:


1,广播session复制,即每次session发生变化时,创建或者修改,就广播给所有集群中的服务器,使所有的服务器上的session相同,这样每台tomcat上都有着全部且相同的session信息

2,session共享,使用缓存,比如redis,将全部session缓存在redis中,每次请求都从redis中查询,这样每次访问不同的tomcat也不会丢失信息,开源项目tomcat-redis-session-manager已经实现该方案

3,session持久化,原理和缓存相似,将session持久化到mysql或其他数据库,查询从数据库查询

4,在nginx层做ip哈希,将用户请求与tomcat绑定,用户固定从该tomcat下获取session,缺点是,如果该tomcat挂了,该用户就不能访问其他tomcat了,违背了集群的初衷

实现上来说,2和4方案最容易,也是我自己使用过的,修改相应配置即可,有小伙伴想了解,后面可再写一篇文章。




三,cookie/session机制的缺点


1)Cookie将状态保存在客户端(默认在本地的硬盘里),Session将状态保存在服务器端(默认在tomcat的内存中,当然tomcat自己也有机制会往硬盘里放,session.ser。也有童鞋使用msm组件放到memcached里的);

2)网络服务器用HTTP头向客户端set-cookie,在客户终端,浏览器解析这些cookie并将它们保存为一个本地文件,保存在客户端本机的硬盘里,

它会自动将同一服务器的任何请求缚上这些cookie。

3)Session是针对每一个用户的,变量的值保存在服务器上,用一个sessionID来区分是哪个用户session变量。

4)session比cookie更安全些。



根据以上特点我们也能看出:

    1,如果我们有其他客户端,并非浏览器,比如安卓/ios,车载,其他应用,我们的cookie/session机制就不能使用了,其他客户端并不会完全对这套体系适用

    2,面对分布式集群时需要session共享

    3,sessionId可以伪造欺骗



改进

    现在项目都讲究前后端分离,认证方式从之前的cookie/session改进为token令牌,在登录后生成一个随机token,每次请求携带token,客户端接收到请求后验证该token,通过则放行查询。成熟的技术方案有jwt等。





版权声明:本文由Sanshi-Blog原创出品,转载请注明出处!

本文链接:http://www.sanshi30.cn/blog/articles/93.html





赞助本站,网站的发展离不开你们的支持!
来说两句吧
最新评论