基于MongoDB打造.Net的分布式Session子系统

Taobao有她自己的分布式session框架,.net阵营也不能落后了,在下做了个基于MongoDB的支持最多26台MongoDB的分布式Session框架。

创新互联主营大兴安岭网站建设的网络公司,主营网站建设方案,app软件定制开发,大兴安岭h5微信小程序搭建,大兴安岭网站营销推广欢迎大兴安岭等地区企业咨询

先看看配置文件:

 
 
 
 
  1.   SessionDB
  2.   mongodb://localhost
  3.   mongodb://localhost
  4.   mongodb://localhost
  5.   mongodb://localhost
  6.   mongodb://localhost
  7.   mongodb://localhost
  8.   mongodb://localhost
  9.   mongodb://localhost
  10.   mongodb://localhost
  11.   mongodb://localhost
  12.   mongodb://localhost
  13.   mongodb://localhost
  14.   mongodb://localhost
  15.   mongodb://localhost
  16.   mongodb://localhost
  17.   mongodb://localhost
  18.   mongodb://localhost
  19.   mongodb://localhost
  20.   mongodb://localhost
  21.   mongodb://localhost
  22.   mongodb://localhost
  23.   mongodb://localhost
  24.   mongodb://localhost
  25.   mongodb://localhost
  26.   mongodb://localhost
  27.   mongodb://localhost

从Identity A一直到Z,默认分成了26个Map,具体的C#应用代码:

 
 
 
 
  1. protected void btnTest_Click(object sender, EventArgs e)
  2.         {
  3.             Session["A"] = DateTime.Now;
  4.             Session["B"] = 1111111111111;
  5.             Session["C"] = "fffffffffffffff";
  6.         }
  7.         protected void btnGetSession_Click(object sender, EventArgs e)
  8.         {
  9.             Response.Write(Session["A"].ToString());
  10.             Response.Write("");
  11.             Response.Write(Session["B"].ToString());
  12.             Response.Write("");
  13.             Response.Write(Session["C"].ToString());
  14.         }
  15.         protected void btnAbandon_Click(object sender, EventArgs e)
  16.         {
  17.             Session.Abandon();
  18.         }

呵呵,就是普通的Session用法。

这个要配置web.config:

 
 
 
 
  1.     
  2.       
  3.         
  4.       
  5.     
  6.   

这里会牵扯出2个类:

  1. A2DFramework.SessionService.MongoDBSessionIDManager
  2. A2DFramework.SessionService.MongoDBSessionStateStore

 MongoDBSessionIDManager

  • 自定义生成的cookie值(也就是SessionID),在这个sample中,会生成如“E.asadfalkasdfjal”这样的SessionID,其中前缀E代表这个Session的信息会映射到哪台MongoDB上。
  • 关键代码
 
 
 
 
  1. public class MongoDBSessionIDManager : SessionIDManager
  2.     {
  3.         private Random rnd = new Random();
  4.         private object oLock = new object();
  5.         public override string CreateSessionID(System.Web.HttpContext context)
  6.         {
  7.             int index = 0;
  8.             lock(this.oLock)
  9.             {
  10.                 index = rnd.Next(SessionConfiguration.SessionServerIdentities.Length);
  11.             }
  12.             string sessionId = string.Format("{0}.{1}", SessionConfiguration.SessionServerIdentities[index], base.CreateSessionID(context));
  13.             return sessionId;
  14.         }
  15.         public override string Encode(string id)
  16.         {
  17.             return DESEncryptor.Encode(id, SessionConfiguration.DESKey);
  18.         }
  19.         public override string Decode(string id)
  20.         {
  21.             return DESEncryptor.Decode(id, SessionConfiguration.DESKey);
  22.         }
  23.         public override bool Validate(string id)
  24.         {
  25.             string prefix;
  26.             string realId;
  27.             if (!Helper.ParseSessionID(id, out prefix, out realId))
  28.                 return false;
  29.             return base.Validate(realId);
  30.         }
  31.     }

#p#

MongoDBSessionStateStore

  • 自定义Session过程中最核心的一个类,代码如下(较多):
 
 
 
 
  1. public sealed class MongoDBSessionStateStore : SessionStateStoreProviderBase
  2.     {
  3.         private SessionStateSection pConfig;
  4.         private string pApplicationName;
  5.         public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
  6.         {
  7.             base.Initialize(name, config);
  8.             pApplicationName =System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath;
  9.             System.Configuration.Configuration cfg = WebConfigurationManager.OpenWebConfiguration(pApplicationName);
  10.             pConfig =(SessionStateSection)cfg.GetSection("system.web/sessionState");
  11.         }
  12.         public override SessionStateStoreData CreateNewStoreData(System.Web.HttpContext context, int timeout)
  13.         {
  14.             return new SessionStateStoreData(new SessionStateItemCollection(), SessionStateUtility.GetSessionStaticObjects(context), timeout);
  15.         }
  16.         public override void CreateUninitializedItem(System.Web.HttpContext context, string id, int timeout)
  17.         {
  18.             //insert to db
  19.             MongoDBSessionEntity session = new MongoDBSessionEntity();
  20.             session.ApplicationName = this.pApplicationName;
  21.             session.SessionId = id;
  22.             session.Created = DateTime.Now;
  23.             session.Expires = DateTime.Now.AddMinutes(pConfig.Timeout.Minutes);
  24.             session.LockDate = DateTime.Now;
  25.             session.LockId = 0;
  26.             session.Timeout = timeout;
  27.             session.Locked = false;
  28.             session.Flags = (int)SessionStateActions.InitializeItem;
  29.             MongoCollection collection = Helper.GetMongoDBCollection(id);
  30.             collection.Save(session);
  31.         }
  32.         public override void Dispose()
  33.         {
  34.         }
  35.         public override void EndRequest(System.Web.HttpContext context)
  36.         {
  37.         }
  38.         public override SessionStateStoreData GetItem(System.Web.HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions)
  39.         {
  40.             return GetSessionStoreItem(false, context, id, out locked, out lockAge, out lockId, out actions);
  41.         }
  42.         public override SessionStateStoreData GetItemExclusive(System.Web.HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions)
  43.         {
  44.             return GetSessionStoreItem(true, context, id, out locked, out lockAge, out lockId, out actions);
  45.         }
  46.         public override void InitializeRequest(System.Web.HttpContext context)
  47.         {
  48.         }
  49.         public override void ReleaseItemExclusive(System.Web.HttpContext context, string id, object lockId)
  50.         {
  51.             //update locked=0, expired=, where lockId=?
  52.             MongoCollection collection = Helper.GetMongoDBCollection(id);
  53.             var query = Query.And(  Query.EQ("LockId", int.Parse(lockId.ToString())),
  54.                                     Query.EQ("_id", id), 
  55.                                     Query.EQ("ApplicationName", pApplicationName));
  56.             var update = Update.Set("Locked", false)
  57.                                 .Set("Expires", DateTime.Now.AddMinutes(pConfig.Timeout.Minutes));
  58.             collection.Update(query, update);
  59.         }
  60.         public override void RemoveItem(System.Web.HttpContext context, string id, object lockId, SessionStateStoreData item)
  61.         {
  62.             //delete where sessionId=? and lockId=? and applicationname=?
  63.             MongoCollection collection = Helper.GetMongoDBCollection(id);
  64.             var query = Query.And(Query.EQ("LockId", int.Parse(lockId.ToString())),
  65.                                     Query.EQ("_id", id),
  66.                                     Query.EQ("ApplicationName", pApplicationName));
  67.             collection.Remove(query);
  68.         }
  69.         public override void ResetItemTimeout(System.Web.HttpContext context, string id)
  70.         {
  71.             //update expire date
  72.             MongoCollection collection = Helper.GetMongoDBCollection(id);
  73.             var query = Query.And(Query.EQ("_id", id),
  74.                                     Query.EQ("ApplicationName", pApplicationName));
  75.             var update = Update.Set("Expires", DateTime.Now.AddMinutes(pConfig.Timeout.Minutes));
  76.             collection.Update(query, update);
  77.         }
  78.         public override void SetAndReleaseItemExclusive(System.Web.HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem)
  79.         {
  80.             MongoCollection collection = Helper.GetMongoDBCollection(id);
  81.             if (newItem)
  82.             {
  83.                 //delete expired items
  84.                 var query = Query.And(Query.EQ("_id", id),
  85.                                     Query.EQ("ApplicationName", pApplicationName),
  86.                                     Query.LT("Expires", DateTime.Now));
  87.                 collection.Remove(query);
  88.                 //insert new item
  89.                 MongoDBSessionEntity session = new MongoDBSessionEntity();
  90.                 session.ApplicationName = this.pApplicationName;
  91.                 session.SessionId = id;
  92.                 session.Created = DateTime.Now;
  93.                 session.Expires = DateTime.Now.AddMinutes(pConfig.Timeout.Minutes);
  94.                 session.LockDate = DateTime.Now;
  95.                 session.LockId = 0;
  96.                 session.Timeout = item.Timeout;
  97.                 session.Locked = false;
  98.                 session.Flags = (int)SessionStateActions.None;
  99.                 session.SessionItems = Helper.Serialize((SessionStateItemCollection)item.Items);
  100.                 collection.Save(session);
  101.             }
  102.             else
  103.             {
  104.                 //update item
  105.                 var query = Query.And(Query.EQ("_id", id),
  106.                                     Query.EQ("ApplicationName", pApplicationName),
  107.                                     Query.EQ("LockId", int.Parse(lockId.ToString())));
  108.                 MongoDBSessionEntity entity= collection.FindOne(query);
  109.                 entity.Expires = DateTime.Now.AddMinutes(item.Timeout);
  110.                 entity.SessionItems = Helper.Serialize((SessionStateItemCollection)item.Items);
  111.                 entity.Locked = false;
  112.                 collection.Save(entity);
  113.             }
  114.         }
  115.         public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback)
  116.         {
  117.             return false;
  118.         }
  119.         private SessionStateStoreData GetSessionStoreItem(bool lockRecord, System.Web.HttpContext context, 
  120.                                                             string id,
  121.                                                             out bool locked,
  122.                                                             out TimeSpan lockAge,
  123.                                                             out object lockId,
  124.                                                             out SessionStateActions actions)
  125.         {
  126.             SessionStateStoreData item = null;  
  127.             lockAge = TimeSpan.Zero;
  128.             lockId = null;
  129.             locked = false;
  130.             actions = 0;
  131.             bool foundRecord = false;
  132.             bool deleteData = false;
  133.             MongoCollection collection = Helper.GetMongoDBCollection(id);
  134.             if (lockRecord)
  135.             { 
  136.                 //update db, set locked=1, lockdate=now
  137.                 var query1 = Query.And(Query.EQ("_id", id),
  138.                                     Query.EQ("ApplicationName", pApplicationName),
  139.                                     Query.EQ("Locked", MongoDB.Bson.BsonValue.Create(false)),
  140.                                     Query.GT("Expires", DateTime.UtcNow));
  141.                 long count = collection.Find(query1).Count();
  142.                 if (count == 0)
  143.                 {
  144.                     locked = true;
  145.                 }
  146.                 else
  147.                 {
  148.                     var update = Update.Set("Locked", true).Set("LockDate", DateTime.Now);
  149.                     collection.Update(query1, update);
  150.                     locked = false;
  151.                 }
  152.             }
  153.             //get item by id
  154.             var query2 = Query.And(Query.EQ("_id", id),
  155.                                     Query.EQ("ApplicationName", pApplicationName));
  156.             MongoDBSessionEntity entity=collection.FindOne(query2);
  157.             if (entity != null)
  158.             {
  159.                 if (entity.Expires < DateTime.Now)
  160.                 {
  161.                     locked = false;
  162.                     deleteData = true;
  163.                 }
  164.                 else
  165.                 {
  166.                     foundRecord = true;
  167.                 }
  168.             }
  169.             //delete item if session expired
  170.             if (deleteData)
  171.             {
  172.                 var query3 = Query.And(Query.EQ("_id", id),
  173.                                     Query.EQ("ApplicationName", pApplicationName));
  174.                 collection.Remove(query3);
  175.             }
  176.             if (!foundRecord)
  177.                 locked = false;
  178.             if (foundRecord && !locked)
  179.             {
  180.                 if (lockId == null)
  181.                     lockId = 0;
  182.                 lockId = (int)lockId + 1;
  183.                 var query4 = Query.And(Query.EQ("_id", id),
  184.                                     Query.EQ("ApplicationName", pApplicationName));
  185.                 var update4 = Update.Set("LockId", (int)lockId)
  186.                                         .Set("Flags", (int)SessionStateActions.None);
  187.                 collection.Update(query4, update4);
  188.                 if (actions == SessionStateActions.InitializeItem)
  189.                     item = CreateNewStoreData(context, pConfig.Timeout.Minutes);
  190.                 else
  191.                     item = Helper.Deserialize(context, entity.SessionItems, entity.Timeout);
  192.             }
  193.             return item;
  194.         }
  195.     }

由于很多方法会用到MongoCollection,因此写了个static公用函数,如下:

 
 
 
 
  1. public static MongoCollection GetMongoDBCollection(string sessionId)
  2.         {
  3.             IPartitionResolver resolver = new MongoDBSessionPartitionResolver();
  4.             string mongoDbConnectionString = resolver.ResolvePartition(sessionId);
  5.             MongoClient client = new MongoClient(mongoDbConnectionString);
  6.             MongoServer srv = client.GetServer();
  7.             MongoDatabase db = srv.GetDatabase(SessionConfiguration.MongoDBName);
  8.             if (!db.CollectionExists(SessionConfiguration.MongoDBCollectionName))
  9.                 db.CreateCollection(SessionConfiguration.MongoDBCollectionName);
  10.             MongoCollection collection = db.GetCollection(SessionConfiguration.MongoDBCollectionName);
  11.             return collection;
  12.         }

#p#

运行效果:

 点击Set Session后:

点击Get Session后:

点击Abandon后:

 源代码已经更新到A2D Framework中了。

分享题目:基于MongoDB打造.Net的分布式Session子系统
当前路径:http://www.hantingmc.com/qtweb/news3/211603.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联