.Net 基于Memcache集群的分布式Session
简述
基于Memcache的Session大家都各有各的说法,比方说:当memcached集群发生故障(比如内存溢出)或者维护(比如升级、增加或减少服务器)时,用户会无法登录,或者被踢掉线等等,每种技术各有优缺点,只是适应的场景不同罢了。
知识点补充
服务器Memcache配置:https://www.cnblogs.com/chenyanbin/p/11415368.html
Memcache集群配置:https://www.cnblogs.com/chenyanbin/p/11441490.html
Mvc校验用户是否登陆:https://www.cnblogs.com/chenyanbin/p/11397576.html
演示代码使用的其他完整类库:https://www.cnblogs.com/chenyanbin/p/11186495.html
代码演示(.Net的Mvc架构):
登陆页控制器
1 IBllSession bllSession = BllSessionFactory.GetCurrentBllSession(); //业务层基类 2 /// <summary> 3 /// 处理登陆的表单 4 /// </summary> 5 /// <returns></returns> 6 public ActionResult ProcessLogin() 7 { 8 try 9 { 10 string user_name = Request["LoginId"]; //用户名 11 string user_pwd = Request["LoginPwd"]; //密码 12 UserInfo model = new UserInfo(); //实体类 13 model.UName = user_name; //实体类赋值 14 model.UPwd = user_pwd; 15 if (bllSession.UserInfo.Select(model).Count > 0) //判断用户名密码是否正确 16 { 17 //旧方法 18 //Session["loginUser"] = user_name; 19 20 //新方法 21 //Memcache+Cookie替代Session登陆 22 //立即分配一个标志GUID,把标志作为Memcache存储数据的key,把用户对象放到Memcache,把GUID写到客户端cookie里面去 23 string userLoginId = Guid.NewGuid().ToString(); //生成一个随机GUID 24 //将用户的数据写入Memcache 25 MemcacheHelper.AddCache(userLoginId, user_name, DateTime.Now.AddMinutes(20)); //Memcache帮助类 26 //往客户端写入Cookie 27 Response.Cookies["userLoginId"].Value= userLoginId; //将GUID写入Cookie 28 return Content("ok"); 29 } 30 else 31 { 32 return Content("用户名或密码错误!你会登陆吗?"); 33 } 34 } 35 catch (Exception ex) 36 { 37 throw ex; 38 } 39 }
过滤器基类(判断用户是否登陆)
1 using Sam.OA.Common; 2 using System; 3 using System.Web.Mvc; 4 5 namespace Sam.OA.WEBAPP.Controllers 6 { 7 /// <summary> 8 /// 控制器基类帮助类 9 /// 作者:陈彦斌 10 /// 更新时间:2019年9月1日17:43:10 11 /// </summary> 12 public class BaseController:Controller 13 { 14 public bool IsCheckedUserLogin = true; 15 protected override void OnActionExecuted(ActionExecutedContext filterContext) 16 { 17 base.OnActionExecuted(filterContext); 18 //校验用户是否已登录 19 if (IsCheckedUserLogin ) 20 { 21 //新方法 22 //使用Memcache+Cookie代替Session 23 if (Request.Cookies["userLoginId"] == null) 24 { 25 filterContext.HttpContext.Response.Redirect("/UserLogin/Index"); 26 return; 27 } 28 string userGuid = Request.Cookies["userLoginId"].Value; //拿到用户的GUID 29 object obj = MemcacheHelper.GetCache(userGuid); 30 if (obj == null || obj.ToString() == "") 31 { 32 //用户长时间不操作,超时 33 filterContext.HttpContext.Response.Redirect("/UserLogin/Index"); 34 } 35 //滑动窗口机制 36 MemcacheHelper.SetCache(userGuid, obj, DateTime.Now.AddMinutes(20)); 37 38 //旧方法Session 39 //if (filterContext.HttpContext.Session["loginUser"] == null) 40 //{ 41 // filterContext.HttpContext.Response.Redirect("/UserLogin/Index"); 42 //} 43 } 44 } 45 } 46 }
Memcache帮助类(MemcacheHelper.cs)
1 using Memcached.ClientLibrary; 2 using System; 3 4 namespace Sam.OA.Common 5 { 6 /// <summary> 7 /// Memcache缓存帮助类 8 /// 作者:陈彦斌 9 /// 时间:2019年9月1日15:48:12 10 /// </summary> 11 public sealed class MemcacheHelper 12 { 13 private static MemcachedClient memcachedClient; 14 static MemcacheHelper() 15 { 16 //分布式Memcached服务器ip 端口 17 string strAppMemcached = DbUtil.memcacheServiceList; 18 if (strAppMemcached==""|| strAppMemcached==null) 19 { 20 throw new Exception("Memcache远程服务器Ip和端口未配置"); 21 } 22 string[] servers = strAppMemcached.Split(','); //Memcache机器IP 23 //初始化池 24 SockIOPool pool = SockIOPool.GetInstance(); 25 pool.SetServers(servers); //关联连接池 26 pool.InitConnections = 3; //初始化链接 27 pool.MinConnections = 3; //最小连接数 28 pool.MaxConnections = 5; //最大连接数 29 pool.SocketConnectTimeout = 1000; //Socket超时连接时间 30 pool.SocketTimeout = 3000; //Socket超时时间 31 pool.MaintenanceSleep = 30; //Socket休眠时间 32 pool.Failover = true; 33 pool.Nagle = false; 34 pool.Initialize(); //初始化 35 //客户端实例 36 if (memcachedClient == null) 37 { 38 memcachedClient = new MemcachedClient(); 39 } 40 memcachedClient.EnableCompression = false; //启动压缩 41 } 42 /// <summary> 43 /// 获取Memcache缓存数据 44 /// </summary> 45 /// <param name="CacheKey">键</param> 46 /// <returns></returns> 47 public static object GetCache(string CacheKey) 48 { 49 return memcachedClient.Get(CacheKey); 50 } 51 /// <summary> 52 /// 设置Memcache缓存数据 53 /// </summary> 54 /// <param name="CacheKey">键</param> 55 /// <param name="CacheValue">值</param> 56 public static void AddCache(string CacheKey, object CacheValue) 57 { 58 memcachedClient.Add(CacheKey, CacheValue); 59 } 60 /// <summary> 61 /// 设置Memcache缓存数据 62 /// </summary> 63 /// <param name="CacheKey">键</param> 64 /// <param name="CacheValue">值</param> 65 /// <param name="expDate">过期时间</param> 66 public static void AddCache(string CacheKey, object CacheValue, DateTime expDate) 67 { 68 memcachedClient.Add(CacheKey, CacheValue,expDate); 69 } 70 /// <summary> 71 /// 设置Memcache缓存数据,key存在则更新,否则新增 72 /// </summary> 73 /// <param name="CacheKey">键</param> 74 /// <param name="CacheValue">值</param> 75 public static void SetCache(string CacheKey, object CacheValue) 76 { 77 memcachedClient.Set(CacheKey, CacheValue); 78 } 79 /// <summary> 80 /// 设置Memcache缓存数据,key存在则更新,否则新增 81 /// </summary> 82 /// <param name="CacheKey">键</param> 83 /// <param name="CacheValue">值</param> 84 /// <param name="expDate">过期时间</param> 85 public static void SetCache(string CacheKey, object CacheValue, DateTime expDate) 86 { 87 memcachedClient.Set(CacheKey, CacheValue, expDate); 88 } 89 } 90 }
觉得对你有帮助的话,帮忙推荐下,还有不懂的地方,欢迎下方留言,明天继续更新Redis!~~