如何通过Session共享实现数据之间的交互呢??

基于 六种方法实现 Session共享

Posted by MasterJen on December 4, 2018

Hey Session

A strong man can save himself ,a grate man can save another.–强者自救,圣者渡人.

Session

    相信每位开发者都会经历这个阶段,那就是登录注册,用来实现用户的管理,

那么关键来了,当我们想要存储用户信息的时候, 往往我们的第一选择就是Session

在今天的 Blog 开始之前 首先向大家介绍几个问题

1、session在何时被创建

      一个常见的误解是以为session在有客户端访问时就被创建,然而事实是直到某server端程序调用HttpServletRequest.getSession(true)这样的语句时才被创建,
  
  注意如果JSP没有显示的使用 <%@page session="false"%> 关闭session,则JSP文件在编译成Servlet时将会自动加上这样一条语句HttpSession session = HttpServletRequest.getSession(true);
  
  这也是JSP中隐含的session对象的来历.由于session会消耗内存资源,因此,如果不打算使用session,应该在所有的JSP中关闭它. 

2、session何时被删除

      session在下列情况下被删除
        
  a.程序调用HttpSession.invalidate();
        
  b.距离上一次收到客户端发送的session id时间间隔超过了session的超时设置;
        
  c.服务器进程被停止(非持久session)

3、如何做到在浏览器关闭时删除session

       严格的讲,做不到这一点.可以做一点努力的办法是在所有的客户端页面里使用javascript
        
  代码window.oncolose来监视浏览器的关闭动作,然后向服务器发送一个请求来删除session.
   
  但是对于浏览器崩溃或者强行杀死进程这些非常规手段仍然无能为力.      

4、有个HttpSessionListener是怎么回事

       你可以创建这样的listener去监控session的创建和销毁事件,
    
   使得在发生这样的事件时你可以做一些相应的工作.注意是session的创建和销毁动作触发listener,而不是相反.
    
   类似的与HttpSession有关的listener还有HttpSessionBindingListener,HttpSessionActivationListener和HttpSessionAttributeListener.  

5、存放在session中的对象必须是可序列化的吗

         不是必需的.要求对象可序列化只是为了session能够在集群中被复制或者能够持久保存或者在必要时server能够暂时把session交换出内存.
     
     在Weblogic Server的session中放置一个不可序列化的对象在控制台上会收到一个警告.                    

了解完了这些,那么进入我们今天的主题,如何实现分布式开发中的Session共享?

        当使用多台服务器架设成集群之后,我们通过负载均衡的方式,同一个用户(或者ip)访问时被分配到不同的服务器上,
    
   假设在A服务器登录,如果在B服务器拿不到用户的登录信息session.这时访问到B服务器时就出现未登录情况.
    
   所以如何对于这种情况做到共享session至关重要.

1.通过数据库mysql共享session

    a.采用一台专门的mysql服务器来存储所有的session信息.

        用户访问随机的web服务器时,会去这个专门的数据库服务器check一下session的情况,以达到session同步的目的. 

        缺点就是:依懒性太强,mysql服务器无法工作,影响整个系统;

    b.将存放session的数据表与业务的数据表放在同一个库.如果mysql做了主从,需要每一个库都需要存在这个表,并且需要数据实时同步.

        缺点:用数据库来同步session,会加大数据库的负担,数据库本来就是容易产生瓶颈的地方,如果把session还放到数据库里面,无疑是雪上加霜.

上面的二种方法,第一点方法较好,把放session的表独立开来,减轻了真正数据库的负担 .但是session一般的查询频率较高,放在数据库中查询性能也不是很好,不推荐使用这种方式.

2.通过cookie共享session

       把用户访问页面产生的session放到cookie里面,就是以cookie为中转站.
    
   当访问服务器A时,登录成功之后将产生的session信息存放在cookie中;当访问请求分配到服务器B时,服务器B先判断服务器有没有这个session,
      
   如果没有,在去看看客户端的cookie里面有没有这个session,如果cookie里面有,就把cookie里面的sessoin同步到web服务器B,这样就可以实现session的同步了. 

缺点:cookie的安全性不高,容易伪造、客户端禁止使用cookie等都可能造成无法共享session.

3.通过服务器之间的数据同步session

    使用一台作为用户的登录服务器,当用户登录成功之后,会将session写到当前服务器上,

我们通过脚本或者守护进程将session同步到其他服务器上,这时当用户跳转到其他服务器,session一致,也就不用再次登录.

缺陷:速度慢,同步session有延迟性,可能导致跳转服务器之后,session未同步.而且单向同步时,登录服务器宕机,整个系统都不能正常运行.

4.通过NFS共享Session

    选择一台公共的NFS服务器(Network File Server)做共享服务器,所有的Web服务器登陆的时候把session数据写到这台服务器上,

那么所有的session数据其实都是保存在这台NFS服务器上的,不论用户访问那太Web服务器,都要来这台服务器获取session数据,那么就能够实现共享session数据了.

缺点:依赖性太强,如果NFS服务器down掉了,那么大家都无法工作了,当然,可以考虑多台NFS服务器同步的形式.

5.通过memcache同步session

      memcache可以做分布式,如果没有这功能,他也不能用来做session同步.他可以把web服务器中的内存组合起来,
    
 成为一个"内存池",不管是哪个服务器产生的sessoin都可以放到这个"内存池"中,其他的都可以使用. 

优点:以这种方式来同步session,不会加大数据库的负担,并且安全性比用cookie大大的提高,把session放到内存里面,比从文件中读取要快很多.

缺点:memcache把内存分成很多种规格的存储块,有块就有大小,这种方式也就决定了,memcache不能完全利用内存,会产生内存碎片,如果存储块不足,还会产生内存溢出.

6.通过redis共享session

    redis与memcache一样,都是将数据放在内存中.区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,

并且在此基础上实现了master-slave(主从)同步.                         

以上六种方式就可以说完成此次需求,但是主观来说,根据性能,以及安全还有效率来说,最后的两种方法,还是现在的企业比较常用的.

即通过memcache缓存和通过Redis 实现Session共享.当然如果大家还有别的想法,可以留言哦.