大家都知道用系统默认的session 会存在这样的问题 如果用户过多的话 session 会自动消亡,而且不能支持分布式和集群。
这系列博客主要讲解 怎样 解决用户过多的session自动消亡,和分布式集群
使用例子
Session["test"] = "啄木鸟";
完全不改变系统的使用风格,可以直接升级系统;
在这里我们主要用的 HttpRuntime.cache 和 memcache。 希望读者这跟着我的思路,一步一步来设计自定义Session
首先,我们想既然有两个数据存取工具,就必须有一个接口 来解耦使用的他的类,从而可以轻而易举的切换数据存储工具,而不影响使用它的类
接口如下:
public interface ICache { /// <summary> /// 数据加入缓存,并使用全局配置的过期时间 /// </summary> /// <param name="key">键</param> /// <param name="obj">数据</param> void Put(string key, object obj); /// <summary> /// 数据加入缓存,并指定过期时间(分钟) /// </summary> /// <param name="key">键</param> /// <param name="obj">数据</param> /// <param name="expireMinutes">过期时间</param> void Put(string key, object obj, int expireMinutes); /// <summary> /// 拿出缓存数据 /// </summary> /// <param name="key"></param> /// <returns></returns> object Get(string key); /// <summary> /// 手动删除缓存数据 /// </summary> /// <param name="key"></param> void Delete(string key); }
接下来 我们来实现这两个数据存储工具类
一个是系统自带的HttpRuntime.cache
public class RuntimeCache:ICache { readonly static System.Web.Caching.Cache httpRuntimeCache = System.Web.HttpRuntime.Cache; readonly static int _expireMinutes = 20; //ConfigConstants.ConfigManager.Config.Cache_ExpireMinutes;配置默认多少秒过时 public void Put(string key, object obj) { httpRuntimeCache.Insert(key,obj); } public void Put(string key, object obj, int expireMinutes) { httpRuntimeCache.Insert(key, obj, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(expireMinutes)); } public object Get(string key) { return httpRuntimeCache.Get(key); } public void Delete(string key) { httpRuntimeCache.Remove(key); } }
上面这个工具我想大家多知道,如果不知道的可以百度 HttpRuntime.Cache 来学习 ,在这里我就不讲解了(其实里面有很多的设计思路可以学习)
另一个的就是memcache,redis 我会在后面加上去
public class MemcacheCache:ICache { private static readonly MemcachedClient m_memcachedClient; private static string m_memcacheStr = ConfigConstants.FrameConfigManager.Config.MemcacheStr ?? "127.0.0.1:11211"; static MemcacheCache() { string[] servers = m_memcacheStr.Split(',');// try { //初始化池 SockIOPool pool = SockIOPool.GetInstance(); pool.SetServers(servers); pool.InitConnections = 3; pool.MinConnections = 3; pool.MaxConnections = 5; pool.SocketConnectTimeout = 1000; pool.SocketTimeout = 3000; pool.MaintenanceSleep = 30; pool.Failover = true; pool.Nagle = false; pool.Initialize(); m_memcachedClient = new Memcached.ClientLibrary.MemcachedClient(); m_memcachedClient.EnableCompression = false; } catch (Exception ex) { int i = 0; } } public void Put(string key, object obj) { m_memcachedClient.Set(key, obj); } public void Put(string key, object obj, int expireMinutes) { m_memcachedClient.Set(key, obj, DateTime.Now.AddMinutes(expireMinutes)); } public object Get(string key) { return m_memcachedClient.Get(key); } public void Delete(string key) { m_memcachedClient.Delete(key); } }
memcache的详细配置,可以找其他资料学习
到这里为止,是不是感觉有点像我们的工厂模式 前段,没错就要用到工厂模式
我们再新建一个类 叫做
/// <summary> /// 缓存管理者 /// </summary> public class CacheManager :Singleton<CacheManager>,ICache { #region 私有变量 private static string _cacheProvider = ConfigConstants.FrameConfigManager.Config.Cache_Provider ?? "runtimecache"; private ICache _iCache; #endregion #region 构造方法 /// <summary> /// 类构造方法,对外不支持创建它的实例对象 /// </summary> static CacheManager() { } private CacheManager() { switch (_cacheProvider.ToLower()) { case"runtimecache": _iCache = new RuntimeCache(); break; case "memcachecache": _iCache = new MemcacheCache(); break; default: throw new ArgumentException("缓存提供者只支持RunTimeCache和RedisCache"); } } #endregion public void Put(string key, object obj) { _iCache.Put(key, obj); } public void Put(string key, object obj, int expireMinutes) { _iCache.Put(key,obj,expireMinutes); } public object Get(string key) { return _iCache.Get(key); } public void Delete(string key) { _iCache.Delete(key); } }
我想这个类 大家都能看的懂,唯有这个Singleton<CacheManager> 大家可能有点 不能明白,因为这个是我自己分装的单例模式,只要继承了他,这个类就是单利了,我会再下一次博客讲明白怎样分装的。到这里我们就实现了使用和提供解耦,我想告诉大家的就是设计模式会根据你的代码量来循循渐进,不要特意看设计模式
我们有了这些准备,下一篇就好讲如何自定义session