session和cookie的机制详解以及相关应用

    先注明出处:看了Java知音的公众号文章,自己稍加总结。(侵删)

    1. session概念:

        现阶段的网站要求软件对一个事务处理要有一个记忆功能,也就是常说的状态。实现Web应用的技术核心http协议是一个无状态的协,为了让Web应用开发保持状态,就出现了保持http链接的状态的两种技术:一个是cookie技术,另一个是session技术。

        cookie技术是客户端解决方案(HTML5之后有了更好的替代品),其主要的特点是,服务器发给客户端的特殊信息以文本的形式存放在客户端,之后客户端每次向服务端发送请求时都会带上这些信息。具体例子:客户发送一个HTTP请求,提供一些用户名等的身份信息并提交到服务端;之后服务端返回相应的数据,并发回这些身份信息(存放在HTTP相应头Response Header);客户端接收返回来的相应后,浏览器就会将这些信息保存到一个特定的统一位置;之后当客户端再想服务端发送请求时就会自动把相应的cookie信息(身份信息)再次发送到服务器,cookie信息存放在HTTP请求头(Request Header)。从而避免重复而繁琐的输入,浏览器中的“记住密码”就是通过这种方式实现的。

        而session技术是服务端的解决方案,通过服务器来保存状态的。我们可以把服务器和客户端浏览器的一系列动作称为一个Session,而Session是服务器端为客户端所开辟的存储空间,其中保存的信息就是为了保存状态。

        那么如何使用session呢?不同的编程语言创建session的方式不同,而Java大概原理是这样的,通过调用HttpServletRequest的getSession()方法创建的。在创建成功session后服务器会创建一个叫Session id的东西,这个Session id是唯一的,他的作用是当客户端再次发送请求时会携带这个Session id用来在服务端重新获取相应的Session,在Session被创建后就可以调用相关的方法来往Session中添加相关的内容了,这些内容均保存在服务端,而Session id会发送到客户端保存,这样用户状态就会得以保存下来。

       cookie和session都是保存状态的方法,其主要差异在cookie用在客户端保存,session是在服务端保存,但是服务端的session的实现对客户端的cookie是有依赖关系的,前面说的那个session id就是保存的容器就是客户端的cookie。如果浏览器禁用了cookie,绝大多数情况下cookie也是不可用的。

    2. session实现原理:

        java web容器都是实现了session机制的,其逻辑思想是一样的。Tomcat是最常用的容器之一,我们来看下他的session实现机制。

        Tomcat中session的实现包在org.apache.catalina.session中,而对外提供调用接口的包却在javax.servlet.http下的HttpSession中,实现包中的StandardSession是Tomcat提供的标准实现。Tomcat也不允许用户直接操作StandarSession,而是提供了一个StandarSessionFacade类,Tomcat容器具体操作session的组件是servlet,而servlet操作session是通过StandarSessionFacade进行的,从而防止直接操作StandardSession所带来的安全问题。(StandardSessionFacad使用了设计模式中的Facad外观模式,外观模式能让不同的逻辑层进行解耦)。

        实现类里面有Manager类是用来管理session的创建和销毁的对象,其中ManagerBase是所有session的管理工具类的基类,是一个抽象类,具体实现管理session的管理功能的类都要继承这个方法。其中有一个受保护的特殊方法,就是创建sessionId值的方法。(Tomcat的sessionId值的生成机制是一个随机数加时间加JVM的id值,不同JVM的id值都是一定的)。StandardManager类是Tomcat容器里默认的session管理实现类,他会将session信息存放在Web容器所在的服务器的内存里。

扫描二维码关注公众号,回复: 144933 查看本文章

    3. session所带来的问题

        引入session机制来弥补http协议的无状态的特点,服务端会占据一定的内存和cpu来处理存储和处理session的计算开销,会导致web容器的并发连接较低(tomcat的官方文档显示默认连接数是200)。比较常见的解决方案是,在生产环境的web容器前面加一个静态资源服务器,静态资源服务器没有处理http无状态问题的功能,也就不会让出内存和cpu计算资源去处理session这样的功能,这些内存和cpu可以更有效的去处理每个http请求,从而加大了并发的连接数量。所以,我们可以让没有状态保持要求的请求在静态服务器内处理,而有状态保存要求的在web容器内进行处理。提高了网站的运行效率。

        还有一个问题就是,一般互联网公司为了提高安全性和并发量,在服务端部署的服务器数量往往是大于2台的,多个服务器提供的服务是等价的,但是服务器上肯定会有不同的web容器,从而导致session在web容器中所生成的sessionId 值是不相同的。这样会导致,保存在A服务器的session不会被B服务器所识别,客户端再次发送请求时,如若是B服务器接收将导致找不到之前保存的信息。解决方法是,两个web容器间进行session的同步,但这样的操作是非常耗费系统资源的,当访问量增加时,会严重影响到网站的效率和稳定性。

        当然还可以在讲服务分发给服务器之前使用负载均衡设备,该设备可以截获session id从而进行判断和分发,但这将会导致系统变为单点系统,如果一个web容器挂掉了,相应的请求也不能被执行了。而且这种做法还干扰了分发的公平性。大型互联网公司会存在跨站点的session同步问题,而目前时使用单点登录(SSO)的解决方案,但是仍旧逃脱不了session跨站点的共享问题。

    综上,session存在两个问题需要解决:

  • session的存储应该独立于web容器,也要独立于部署web容器的服务器;
  • 如何进行高效的session同步。

        session数据存储到内存时最佳的选择,因为硬盘的操作方式是IO操作,IO操作的效率远小于操作内存数据。因此最好的解决方案就是使用分布式缓存技术,比如:memcached和redis,将session信息的存储独立起来也是解决session同步问题的方法。分享两个参考网址:

    点击打开链接:使用memcache的解决方案;

 http://blog.sina.com.cn/s/blog_5376c71901017bqx.html

    点击打开链接:使用zookeeper实现分布式session方案。

 http://www.open-open.com/lib/view/open1378556537303.html

    

猜你喜欢

转载自blog.csdn.net/victoryshen/article/details/80198283
今日推荐