• 扩展Session机制


    分布式缓存扩展Session机制

     

    为什么要把Session放在缓存中

      Session是我们常用的状态保持的对象,它通常会生成一个唯一的SessionId以Cookie的方式存在浏览器端,而Session本身会保存在服务器端。

      虽说我们用Session很方便的实现状态保持,但是Session也带来了很多弊端,下面我们一步一步来分析Session的一些弊端以及用什么方式去改变它:

      

      一、当mode="InProc"时:

        1.因为网站会因为各种原因重启,照成数据丢失,在线用户全部下线。

        2.Session保存的东西越来越多,占用服务器内存也就越来越大,服务器内存压力也会越来越大。

        3.Session存在服务器内存中,不能在多台服务器之间共享,扩展性收到了影响。

        -----解决方案:model="SQLServer"或者model="StateServer"...

      二、当model="SQLServer"或者model="StateServer"时:

        1.无论我们是否要使用SessionState,SessionStateModule一直在工作,每一个用户请求都会去处理SessionState,执行一些列的调用,其中还可能涉及到序列化和反序列化,这样造成了资源浪费,影响性能。

        2.每个用户对应一个SessionId,当一个用户同时打开两个页面的时候、或者一个页面中夹杂着IFrame、或者带着异步请求,这样算属于单个用户并发吧?!HttpHandler处理的时候是会对Session进行加锁的,当一个页面处理慢的时候会锁住当前的Session,后面的页面是不是也在等待当前Session的释放,就这样就照成一个问题——Session影响并发(单个用户并发)。虽说这种情况很少会出现,但是我们在处理一些特殊请求的时候,确实需要注意一下这个细节。对于上面所说的相信大家都有所理解,Session影响并发,可能没有太过关注过,下面举个例子试一试是不是这样的情况!

        先创建一个主窗体,三个父窗体,我注册了HttpModule来看一下执行的流程,Test_2页面线程睡眠5秒...

        

        在未使用Session的情况下...

        

        

         然后我在主窗体后台类中使用了Session    Session["test"]="test"; 会发现Test_3被阻塞了...

        

        

         解决方案:使用分布式缓存,最近有很多比较火热的分布式缓存系统,如:Memcached、Redis...

        因为Redis可以实现数据持久化,支持多重数据类型,可能应用场景更广泛一些,所以之前用了Redis,这次就那Redis来做例子,不过其他的实现方式也一样一样了...

        

      ------------------------------------------------------------------------------------------------------------------------------------------------------

        首先分析一下我们怎么来设计这个Session,我的想法是每个SessionId对应一个Dictionary<string,Object>,SessionId用Guid表示,也是以Cookie的形式发送在客户端,Session为键,Dictionary为值存放在Redis里...

        Session——SessionId{Dictionary<string,Object>}

              SessionId{Dictionary<string,Object>}

              SessionId{Dictionary<string,Object>}

    复制代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Web;
    
    //使用Redis的命名空间
    namespace ServiceStack.Redis {
      //把Session作为Redis的扩展方法: 三要素——静态类、静态方法、this关键字
    public static class RedisHelper { //private static RedisClient Redis = new RedisClient("127.0.0.1", 6379);     
    //设置Session public static bool SetSession(this RedisClient Redis, string key, object value) { var requestCookie = HttpContext.Current.Request.Cookies["SessionId"]; string sessionId; if (requestCookie == null) { sessionId = Guid.NewGuid().ToString(); } else { sessionId = requestCookie.Value; } Redis.Expire(sessionId, 20 * 60); HttpContext.Current.Response.SetCookie(new HttpCookie("SessionId", sessionId)); if (Redis.Exists(sessionId) == 1 ? true : false) { var newDir = Redis.Get<Dictionary<string, object>>(sessionId) as Dictionary<string, object>; if (newDir == null) { return false; } if (newDir.ContainsKey(key)) { newDir.Remove(key); } newDir[key] = value; Redis.Set<Dictionary<string, object>>(sessionId, newDir); return true; } else { Dictionary<string, object> dic = new Dictionary<string, object>(); dic.Add(key, value); Redis.Set<Dictionary<string, object>>(sessionId, dic); return true; } }

         //删除Session
    public static bool DeleteSession(this RedisClient Redis, string key) { var requestCookie = HttpContext.Current.Request.Cookies["SessionId"]; string sessionId; if (requestCookie == null) { return false; } sessionId = requestCookie.Value; Redis.Expire(sessionId, 20 * 60); Dictionary<string, object> dic = Redis.Get<Dictionary<string, object>>(sessionId); if (dic == null) { return false; } if (dic.ContainsKey(key)) { dic.Remove(key); Redis.Set<Dictionary<string, object>>(sessionId, dic); } return true; }

          //获取Session
    public static object GetSession(this RedisClient Redis, string key) { var requestCookie = HttpContext.Current.Request.Cookies["SessionId"]; string sessionId; if (requestCookie == null) { return null; } sessionId = requestCookie.Value; Dictionary<string, object> dic = Redis.Get<Dictionary<string, object>>(sessionId); if (dic == null) { return null; } if (dic.ContainsKey(key)) { Redis.Expire(sessionId, 20 * 60); return dic[key]; } return null; } } }
    复制代码

        优点:  

            1.解决了session的性能问题;

            2.解决了应用程序的可扩展性;

            3.内存之间的共享;

            4.Session丢失的问题;

              

        这是自己对Redis的一个扩展Session,不知道是否算优,欢迎大牛拍砖纠正;

  • 相关阅读:
    洛谷 P4317
    洛谷 P6218
    洛谷 P4999
    洛谷 P2657
    CSP 2020-S2 题解
    2020CSP-S2游记
    Spring Boot中使用WebSocket总结
    防盗链
    JVM JRE和JDK的区别和联系
    Java 注解学习
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3420504.html
Copyright © 2020-2023  润新知