自定义session Provider随笔[由多个请求阻塞排队处理发现]
using IDH.Common.BaseInfoCacheManagement; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Collections.Specialized; using System.Web; using System.Web.SessionState; namespace IdhWebApplication.Extensions.SessionProvider { /// <summary> /// 使用Redis实现SessionStateStoreProviderBase /// </summary> public class RedisSessionStateStore : SessionStateStoreProviderBase { /// <summary> /// 创建新的Session执行 /// </summary> public override SessionStateStoreData CreateNewStoreData(HttpContext context, int timeout) { return CreateLegitStoreData(context, null, null, timeout); } internal static SessionStateStoreData CreateLegitStoreData(HttpContext context, ISessionStateItemCollection sessionItems, HttpStaticObjectsCollection staticObjects, int timeout) { if (sessionItems == null) sessionItems = new SessionStateItemCollection(); if (staticObjects == null && context != null) staticObjects = SessionStateUtility.GetSessionStaticObjects(context); return new SessionStateStoreData(sessionItems, staticObjects, timeout); } public override void CreateUninitializedItem(HttpContext context, string id, int timeout) { RedisSessionState state = new RedisSessionState(null, null, timeout); BaseInfoCache.redisSessionCache.SetItem(id, state.ToJson(), timeout); } /// <summary> /// 从redis获取session数据 /// </summary> /// <param name="context"></param> /// <param name="id"></param> /// <param name="exclusive"></param> /// <param name="locked"></param> /// <param name="lockAge"></param> /// <param name="lockId"></param> /// <param name="actionFlags"></param> /// <returns></returns> private SessionStateStoreData DoGet(HttpContext context, string id, bool exclusive, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags) { locked = false; lockId = null; lockAge = TimeSpan.Zero; actionFlags = SessionStateActions.None; RedisSessionState state = RedisSessionState.FromJson(BaseInfoCache.redisSessionCache.GetItem(id)); if (state == null) { return null; } BaseInfoCache.redisSessionCache.SetItem(id, state.ToJson(), state._timeout); return CreateLegitStoreData(context, state._sessionItems, state._staticObjects, state._timeout); } /// <summary> /// 取值的时候执行 /// </summary> public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags) { return this.DoGet(context, id, false, out locked, out lockAge, out lockId, out actionFlags); } public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags) { return this.DoGet(context, id, true, out locked, out lockAge, out lockId, out actionFlags); } /// <summary> /// 新增 修改 移除键值时执行 /// </summary> /// <param name="item">item.Items为当前所有的键值对</param> public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem) { ISessionStateItemCollection sessionItems = null; HttpStaticObjectsCollection staticObjects = null; if (item.Items.Count > 0) sessionItems = item.Items; if (!item.StaticObjects.NeverAccessed) staticObjects = item.StaticObjects; RedisSessionState state2 = new RedisSessionState(sessionItems, staticObjects, item.Timeout); BaseInfoCache.redisSessionCache.SetItem(id, state2.ToJson(), item.Timeout); } #region "未实现方法" public override void Dispose() { } public override void EndRequest(HttpContext context) { } public override void InitializeRequest(HttpContext context) { } public override void ReleaseItemExclusive(HttpContext context, string id, object lockId) { } public override void RemoveItem(HttpContext context, string id, object lockId, SessionStateStoreData item) { BaseInfoCache.redisSessionCache.RemoveItem(id); } public override void ResetItemTimeout(HttpContext context, string id) { } public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback) { return true; } #endregion } /// <summary> /// 存储在redis的对象 /// </summary> public class SessionStateItem { /// <summary> /// session数据 /// </summary> public Dictionary<string,object> Dict { get; set; } /// <summary> /// 超时时间(分钟) /// </summary> public int Timeout { get; set; } } /// <summary> /// 将session对象数据格式处理 /// </summary> internal sealed class RedisSessionState { internal ISessionStateItemCollection _sessionItems; internal HttpStaticObjectsCollection _staticObjects; internal int _timeout; internal RedisSessionState(ISessionStateItemCollection sessionItems, HttpStaticObjectsCollection staticObjects, int timeout) { this.Copy(sessionItems, staticObjects, timeout); } internal void Copy(ISessionStateItemCollection sessionItems, HttpStaticObjectsCollection staticObjects, int timeout) { this._sessionItems = sessionItems; this._staticObjects = staticObjects; this._timeout = timeout; } /// <summary> /// 序列化 /// </summary> /// <returns></returns> public string ToJson() { if (_sessionItems == null || _sessionItems.Count == 0) { return null; } var dict = new Dictionary<string, object>(); string key; NameObjectCollectionBase.KeysCollection keys = _sessionItems.Keys; for (int i = 0; i < keys.Count; i++) { key = keys[i]; dict.Add(key, _sessionItems[key]); } var item = new SessionStateItem { Dict = dict, Timeout = this._timeout }; return JsonConvert.SerializeObject(item); } /// <summary> /// 反序列化 /// </summary> /// <param name="json"></param> /// <returns></returns> public static RedisSessionState FromJson(string json) { if (string.IsNullOrEmpty(json)) { return null; } try { SessionStateItem item = JsonConvert.DeserializeObject<SessionStateItem>(json); SessionStateItemCollection collections = new SessionStateItemCollection(); foreach (var kvp in item.Dict) { //转换指定类型,要不然从session获取的对象无法强转为指定类型 if(kvp.Key == "CurrentUserPermissions") { var permissionJson = JsonConvert.SerializeObject(kvp.Value); collections[kvp.Key] = JsonConvert.DeserializeObject<Dictionary<Guid,int>>(permissionJson); } else if(kvp.Key == "CurrentUser") { var userJson = JsonConvert.SerializeObject(kvp.Value); collections[kvp.Key] = JsonConvert.DeserializeObject<UserIdentity>(userJson); } else { collections[kvp.Key] = kvp.Value; } } return new RedisSessionState(collections, null, item.Timeout); } catch { return null; } } } }
再配置文件system.web节点下添加代码
<sessionState mode="Custom" customProvider="RedisSessionStateStore"> <providers> <add name="RedisSessionStateStore" type="IdhWebApplication.Extensions.SessionProvider.RedisSessionStateStore"/> </providers> </sessionState>