本篇文章為大家展示了如何利用MongoDB打造.Net的分布式Session子系統(tǒng),內(nèi)容簡(jiǎn)明扼要并且容易理解,絕對(duì)能使你眼前一亮,通過這篇文章的詳細(xì)介紹希望你能有所收獲。
成都創(chuàng)新互聯(lián)公司主要從事網(wǎng)站建設(shè)、成都網(wǎng)站制作、網(wǎng)頁(yè)設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)安陽(yáng),十余年網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專業(yè),歡迎來(lái)電咨詢建站服務(wù):13518219792
Taobao有她自己的分布式session框架,.net陣營(yíng)也不能落后了,在下做了個(gè)基于MongoDB的支持最多26臺(tái)MongoDB的分布式Session框架。
先看看配置文件:
<?xml version="1.0" encoding="utf-8" ?> <MongoDBSession> <DbName>SessionDB</DbName> <IdentityMap Identity="A">mongodb://localhost</IdentityMap> <IdentityMap Identity="B">mongodb://localhost</IdentityMap> <IdentityMap Identity="C">mongodb://localhost</IdentityMap> <IdentityMap Identity="D">mongodb://localhost</IdentityMap> <IdentityMap Identity="E">mongodb://localhost</IdentityMap> <IdentityMap Identity="F">mongodb://localhost</IdentityMap> <IdentityMap Identity="G">mongodb://localhost</IdentityMap> <IdentityMap Identity="H">mongodb://localhost</IdentityMap> <IdentityMap Identity="I">mongodb://localhost</IdentityMap> <IdentityMap Identity="J">mongodb://localhost</IdentityMap> <IdentityMap Identity="K">mongodb://localhost</IdentityMap> <IdentityMap Identity="L">mongodb://localhost</IdentityMap> <IdentityMap Identity="M">mongodb://localhost</IdentityMap> <IdentityMap Identity="N">mongodb://localhost</IdentityMap> <IdentityMap Identity="O">mongodb://localhost</IdentityMap> <IdentityMap Identity="P">mongodb://localhost</IdentityMap> <IdentityMap Identity="Q">mongodb://localhost</IdentityMap> <IdentityMap Identity="R">mongodb://localhost</IdentityMap> <IdentityMap Identity="S">mongodb://localhost</IdentityMap> <IdentityMap Identity="T">mongodb://localhost</IdentityMap> <IdentityMap Identity="U">mongodb://localhost</IdentityMap> <IdentityMap Identity="V">mongodb://localhost</IdentityMap> <IdentityMap Identity="W">mongodb://localhost</IdentityMap> <IdentityMap Identity="X">mongodb://localhost</IdentityMap> <IdentityMap Identity="Y">mongodb://localhost</IdentityMap> <IdentityMap Identity="Z">mongodb://localhost</IdentityMap> </MongoDBSession>
從Identity A一直到Z,默認(rèn)分成了26個(gè)Map,具體的C#應(yīng)用代碼:
protected void btnTest_Click(object sender, EventArgs e) { Session["A"] = DateTime.Now; Session["B"] = 1111111111111; Session["C"] = "fffffffffffffff"; } protected void btnGetSession_Click(object sender, EventArgs e) { Response.Write(Session["A"].ToString()); Response.Write("<br />"); Response.Write(Session["B"].ToString()); Response.Write("<br />"); Response.Write(Session["C"].ToString()); } protected void btnAbandon_Click(object sender, EventArgs e) { Session.Abandon(); }
呵呵,就是普通的Session用法。
這個(gè)要配置web.config:
<system.web> <sessionState mode="Custom" customProvider="A2DSessionProvider" sessionIDManagerType="A2DFramework.SessionService.MongoDBSessionIDManager"> <providers> <add name="A2DSessionProvider" type="A2DFramework.SessionService.MongoDBSessionStateStore"/> </providers> </sessionState> </system.web>
這里會(huì)牽扯出2個(gè)類:
A2DFramework.SessionService.MongoDBSessionIDManager
A2DFramework.SessionService.MongoDBSessionStateStore
MongoDBSessionIDManager
自定義生成的cookie值(也就是SessionID),在這個(gè)sample中,會(huì)生成如“E.asadfalkasdfjal”這樣的SessionID,其中前綴E代表這個(gè)Session的信息會(huì)映射到哪臺(tái)MongoDB上。
關(guān)鍵代碼
public class MongoDBSessionIDManager : SessionIDManager { private Random rnd = new Random(); private object oLock = new object(); public override string CreateSessionID(System.Web.HttpContext context) { int index = 0; lock(this.oLock) { index = rnd.Next(SessionConfiguration.SessionServerIdentities.Length); } string sessionId = string.Format("{0}.{1}", SessionConfiguration.SessionServerIdentities[index], base.CreateSessionID(context)); return sessionId; } public override string Encode(string id) { return DESEncryptor.Encode(id, SessionConfiguration.DESKey); } public override string Decode(string id) { return DESEncryptor.Decode(id, SessionConfiguration.DESKey); } public override bool Validate(string id) { string prefix; string realId; if (!Helper.ParseSessionID(id, out prefix, out realId)) return false; return base.Validate(realId); } }
MongoDBSessionStateStore
自定義Session過程中最核心的一個(gè)類,代碼如下(較多):
public sealed class MongoDBSessionStateStore : SessionStateStoreProviderBase { private SessionStateSection pConfig; private string pApplicationName; public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config) { base.Initialize(name, config); pApplicationName =System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath; System.Configuration.Configuration cfg = WebConfigurationManager.OpenWebConfiguration(pApplicationName); pConfig =(SessionStateSection)cfg.GetSection("system.web/sessionState"); } public override SessionStateStoreData CreateNewStoreData(System.Web.HttpContext context, int timeout) { return new SessionStateStoreData(new SessionStateItemCollection(), SessionStateUtility.GetSessionStaticObjects(context), timeout); } public override void CreateUninitializedItem(System.Web.HttpContext context, string id, int timeout) { //insert to db MongoDBSessionEntity session = new MongoDBSessionEntity(); session.ApplicationName = this.pApplicationName; session.SessionId = id; session.Created = DateTime.Now; session.Expires = DateTime.Now.AddMinutes(pConfig.Timeout.Minutes); session.LockDate = DateTime.Now; session.LockId = 0; session.Timeout = timeout; session.Locked = false; session.Flags = (int)SessionStateActions.InitializeItem; MongoCollection<MongoDBSessionEntity> collection = Helper.GetMongoDBCollection(id); collection.Save(session); } public override void Dispose() { } public override void EndRequest(System.Web.HttpContext context) { } public override SessionStateStoreData GetItem(System.Web.HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { return GetSessionStoreItem(false, context, id, out locked, out lockAge, out lockId, out actions); } public override SessionStateStoreData GetItemExclusive(System.Web.HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { return GetSessionStoreItem(true, context, id, out locked, out lockAge, out lockId, out actions); } public override void InitializeRequest(System.Web.HttpContext context) { } public override void ReleaseItemExclusive(System.Web.HttpContext context, string id, object lockId) { //update locked=0, expired=, where lockId=? MongoCollection<MongoDBSessionEntity> collection = Helper.GetMongoDBCollection(id); var query = Query.And( Query.EQ("LockId", int.Parse(lockId.ToString())), Query.EQ("_id", id), Query.EQ("ApplicationName", pApplicationName)); var update = Update.Set("Locked", false) .Set("Expires", DateTime.Now.AddMinutes(pConfig.Timeout.Minutes)); collection.Update(query, update); } public override void RemoveItem(System.Web.HttpContext context, string id, object lockId, SessionStateStoreData item) { //delete where sessionId=? and lockId=? and applicationname=? MongoCollection<MongoDBSessionEntity> collection = Helper.GetMongoDBCollection(id); var query = Query.And(Query.EQ("LockId", int.Parse(lockId.ToString())), Query.EQ("_id", id), Query.EQ("ApplicationName", pApplicationName)); collection.Remove(query); } public override void ResetItemTimeout(System.Web.HttpContext context, string id) { //update expire date MongoCollection<MongoDBSessionEntity> collection = Helper.GetMongoDBCollection(id); var query = Query.And(Query.EQ("_id", id), Query.EQ("ApplicationName", pApplicationName)); var update = Update.Set("Expires", DateTime.Now.AddMinutes(pConfig.Timeout.Minutes)); collection.Update(query, update); } public override void SetAndReleaseItemExclusive(System.Web.HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem) { MongoCollection<MongoDBSessionEntity> collection = Helper.GetMongoDBCollection(id); if (newItem) { //delete expired items var query = Query.And(Query.EQ("_id", id), Query.EQ("ApplicationName", pApplicationName), Query.LT("Expires", DateTime.Now)); collection.Remove(query); //insert new item MongoDBSessionEntity session = new MongoDBSessionEntity(); session.ApplicationName = this.pApplicationName; session.SessionId = id; session.Created = DateTime.Now; session.Expires = DateTime.Now.AddMinutes(pConfig.Timeout.Minutes); session.LockDate = DateTime.Now; session.LockId = 0; session.Timeout = item.Timeout; session.Locked = false; session.Flags = (int)SessionStateActions.None; session.SessionItems = Helper.Serialize((SessionStateItemCollection)item.Items); collection.Save(session); } else { //update item var query = Query.And(Query.EQ("_id", id), Query.EQ("ApplicationName", pApplicationName), Query.EQ("LockId", int.Parse(lockId.ToString()))); MongoDBSessionEntity entity= collection.FindOne(query); entity.Expires = DateTime.Now.AddMinutes(item.Timeout); entity.SessionItems = Helper.Serialize((SessionStateItemCollection)item.Items); entity.Locked = false; collection.Save(entity); } } public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback) { return false; } private SessionStateStoreData GetSessionStoreItem(bool lockRecord, System.Web.HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { SessionStateStoreData item = null; lockAge = TimeSpan.Zero; lockId = null; locked = false; actions = 0; bool foundRecord = false; bool deleteData = false; MongoCollection<MongoDBSessionEntity> collection = Helper.GetMongoDBCollection(id); if (lockRecord) { //update db, set locked=1, lockdate=now var query1 = Query.And(Query.EQ("_id", id), Query.EQ("ApplicationName", pApplicationName), Query.EQ("Locked", MongoDB.Bson.BsonValue.Create(false)), Query.GT("Expires", DateTime.UtcNow)); long count = collection.Find(query1).Count(); if (count == 0) { locked = true; } else { var update = Update.Set("Locked", true).Set("LockDate", DateTime.Now); collection.Update(query1, update); locked = false; } } //get item by id var query2 = Query.And(Query.EQ("_id", id), Query.EQ("ApplicationName", pApplicationName)); MongoDBSessionEntity entity=collection.FindOne(query2); if (entity != null) { if (entity.Expires < DateTime.Now) { locked = false; deleteData = true; } else { foundRecord = true; } } //delete item if session expired if (deleteData) { var query3 = Query.And(Query.EQ("_id", id), Query.EQ("ApplicationName", pApplicationName)); collection.Remove(query3); } if (!foundRecord) locked = false; if (foundRecord && !locked) { if (lockId == null) lockId = 0; lockId = (int)lockId + 1; var query4 = Query.And(Query.EQ("_id", id), Query.EQ("ApplicationName", pApplicationName)); var update4 = Update.Set("LockId", (int)lockId) .Set("Flags", (int)SessionStateActions.None); collection.Update(query4, update4); if (actions == SessionStateActions.InitializeItem) item = CreateNewStoreData(context, pConfig.Timeout.Minutes); else item = Helper.Deserialize(context, entity.SessionItems, entity.Timeout); } return item; } }
由于很多方法會(huì)用到MongoCollection,因此寫了個(gè)static公用函數(shù),如下:
public static MongoCollection<MongoDBSessionEntity> GetMongoDBCollection(string sessionId) { IPartitionResolver resolver = new MongoDBSessionPartitionResolver(); string mongoDbConnectionString = resolver.ResolvePartition(sessionId); MongoClient client = new MongoClient(mongoDbConnectionString); MongoServer srv = client.GetServer(); MongoDatabase db = srv.GetDatabase(SessionConfiguration.MongoDBName); if (!db.CollectionExists(SessionConfiguration.MongoDBCollectionName)) db.CreateCollection(SessionConfiguration.MongoDBCollectionName); MongoCollection<MongoDBSessionEntity> collection = db.GetCollection<MongoDBSessionEntity>(SessionConfiguration.MongoDBCollectionName); return collection; }
運(yùn)行效果:
點(diǎn)擊Set Session后:
點(diǎn)擊Get Session后:
點(diǎn)擊Abandon后:
源代碼已經(jīng)更新到A2D Framework中了。
上述內(nèi)容就是如何利用MongoDB打造.Net的分布式Session子系統(tǒng),你們學(xué)到知識(shí)或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識(shí)儲(chǔ)備,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
本文標(biāo)題:如何利用MongoDB打造.Net的分布式Session子系統(tǒng)
網(wǎng)站地址:http://jinyejixie.com/article14/jjhpde.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供、ChatGPT、企業(yè)建站、手機(jī)網(wǎng)站建設(shè)、網(wǎng)站收錄、App設(shè)計(jì)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)