Key/Value之王Memcached初探:三、Memcached解決Session的分布式存儲場景的應(yīng)用

一笋熬、高可用的Session服務(wù)器場景簡介

1.1 應(yīng)用服務(wù)器的無狀態(tài)特性

  應(yīng)用層服務(wù)器(這里一般指Web服務(wù)器)處理網(wǎng)站應(yīng)用的業(yè)務(wù)邏輯浩聋,應(yīng)用的一個(gè)最顯著的特點(diǎn)是:應(yīng)用的無狀態(tài)性。

PS:提到無狀態(tài)特性,不得不說下Http協(xié)議躯喇。我們常常聽到說硝枉,Http是一個(gè)無狀態(tài)協(xié)議妻味,同一個(gè)會話的連續(xù)兩個(gè)請求互相不了解,他們由最新實(shí)例化的環(huán)境進(jìn)行解析焦履,除了應(yīng)用本身可能已經(jīng)存儲在全局對象中的所有信息外嘉裤,該環(huán)境不保存與會話有關(guān)的任何信息凿将。之所以我們在使用ASP.NET WebForm開發(fā)中會感覺不到Http的無狀態(tài)特性牧抵,完全是因?yàn)镸icrosoft幫我們實(shí)現(xiàn)了ViewState犀变,它是ASP.NET WebForm中保存頁面信息的基本單位获枝,本質(zhì)是一個(gè)HTML中的隱藏域骇笔,回調(diào)時(shí)會將這個(gè)隱藏域中的數(shù)據(jù)提交到服務(wù)器端笨触。?

  在很多場景中芦劣,用戶都需要和我們的網(wǎng)站系統(tǒng)進(jìn)行多次的信息交互,這時(shí)就需要一種解決方案來克服無狀態(tài)特性所帶來的困境寸认。還好偏塞,在巨人的肩膀上邦鲫,我們已經(jīng)有了很好的解決方案掂碱,那就是瀏覽器端的Cookie和服務(wù)器端的Session疼燥。在一般的單機(jī)開發(fā)中(這里一般是指只有一臺Web服務(wù)器的情況)醉者,服務(wù)器端我們通常使用Session來存儲用戶登錄狀態(tài)(一般是一個(gè)自定義對象實(shí)例),在多數(shù)的管理信息系統(tǒng)開發(fā)中(畢竟內(nèi)部系統(tǒng)用戶量不多立磁,一臺Web服務(wù)器既提供Web服務(wù)又存儲Session對象內(nèi)存還算是夠用的)這是很常見的唱歧。

  但是颅崩,在大用戶量下蕊苗,單機(jī)版的Session就會顯得效率低下朽砰,甚至?xí)侠踂eb服務(wù)器的性能瞧柔。這是因?yàn)椋好總€(gè)用戶的Http請求發(fā)到服務(wù)器端后造锅,每臺Web服務(wù)器的服務(wù)器軟件(例如:IIS、Tomcat等)都會為該請求創(chuàng)建一個(gè)線程來進(jìn)行處理和響應(yīng)券坞,但是一臺服務(wù)器同一時(shí)間可以接收的請求數(shù)畢竟是有限的(這個(gè)根據(jù)服務(wù)器的配置而定恨锚,例如CPU中i3猴伶、i5和i7類型分別可以創(chuàng)建的線程數(shù)都各不相同)他挎,當(dāng)某個(gè)時(shí)間段出現(xiàn)高并發(fā)請求數(shù)的時(shí)候(比如:網(wǎng)購秒殺系統(tǒng)中經(jīng)常同一時(shí)間會出現(xiàn)海量的并發(fā)數(shù))捡需,那這臺應(yīng)用服務(wù)器將會接收前所未有的請求負(fù)載站辉,最終可能會因?yàn)槌惺懿涣烁哓?fù)載而導(dǎo)致宕機(jī),網(wǎng)站不得不停止服務(wù)摧阅。

  這時(shí)棒卷,又想起了那句話:當(dāng)一頭牛拉不動車的時(shí)候祝钢,不要去尋找一頭更強(qiáng)壯的牛太颤,而是用兩頭牛來拉車龄章。于是,我們可以采用服務(wù)器集群的技術(shù)來對Web服務(wù)器進(jìn)行改進(jìn)岗憋,增加N臺Web服務(wù)器部署相同的Web應(yīng)用構(gòu)成Web服務(wù)器集群來對外提供服務(wù)仔戈,通過負(fù)載均衡設(shè)備或軟件將海量的并發(fā)請求數(shù)平均地分?jǐn)偟矫颗_Web服務(wù)器监徘,例如:假設(shè)某系統(tǒng)在促銷活動期間同一時(shí)刻涌入了10萬個(gè)請求凰盔,而服務(wù)器集群中有5臺Web服務(wù)器同時(shí)提供服務(wù)户敬,這時(shí)負(fù)載均衡設(shè)備就將這個(gè)10萬請求通過某種算法較為均衡地分配給其中的Web服務(wù)器尿庐,平均下來每臺服務(wù)器最多就只承擔(dān)2萬個(gè)請求呢堰。

  通過服務(wù)器集群暮胧,已經(jīng)較好地解決了請求負(fù)載問題往衷,這時(shí)新的問題又來了:由于Session默認(rèn)是屬于進(jìn)程內(nèi)(InProc)的席舍,也就是說它是存儲在Web服務(wù)器的內(nèi)存里邊的来颤。當(dāng)構(gòu)建好集群之后,用戶的Session會建立在負(fù)載均衡設(shè)備所分配的其中一臺Web服務(wù)器里邊萝毛。但是當(dāng)用戶下一次訪問或者訪問系統(tǒng)中的其他子系統(tǒng)(比如:我首先在百度百科進(jìn)行登錄了笆包,然后訪問百度貼吧)庵佣,由于Session會話還存儲在上一次提供服務(wù)的Web服務(wù)器里邊巴粪,系統(tǒng)校驗(yàn)規(guī)則(現(xiàn)在這臺Web服務(wù)器里邊檢測到?jīng)]有該用戶的Session)會造成用戶的重復(fù)登錄(比如:都是在百度的網(wǎng)頁肛根,它卻讓你登錄好幾次晶通,你爽嗎哟玷?很明顯巢寡,不爽吧)抑月。這時(shí)谦絮,就需要我們解決Web服務(wù)器集群的Session管理,下面我們就來看看如何進(jìn)行Web服務(wù)器集群的Session管理赠潦。

1.2 應(yīng)用服務(wù)器集群的Session管理

  我們現(xiàn)在來看看在集群環(huán)境中她奥,Session管理的幾種常見手段:

 ×蟆①Session復(fù)制:該方案簡單易行拳恋,集群中的幾臺服務(wù)器之間同步Session對象谬运,任何一臺服務(wù)器宕機(jī)都不會導(dǎo)致Session對象的丟失吩谦,服務(wù)器也只需要從本機(jī)獲取即可式廷。但是滑废,該方案只適合集群規(guī)模較小的情況下蠕趁。當(dāng)規(guī)模較大時(shí)俺陋,大量的Session復(fù)制操作會占用服務(wù)器和網(wǎng)絡(luò)的大量資源,系統(tǒng)不堪重負(fù)腊状。

?

 〈②Session綁定:利用負(fù)載均衡的源地址Hash算法苟鸯,總是將源于同一IP地址的請求分發(fā)到同一臺服務(wù)器上早处。這樣的話,在整個(gè)會話期間卵蛉,用戶所有的請求都在同一臺服務(wù)器上進(jìn)行處理,即Session綁定在某臺特定服務(wù)器上诉儒,保證Session總能在這臺服務(wù)器上獲取忱反。(這種方案又叫做會話粘滯)温算。

?

  但是,這種方案不符合高可用的需求巩割。因?yàn)橐坏┠撑_服務(wù)器宕機(jī)付燥,那么該機(jī)器上得Session也就不復(fù)存在了键科,用戶請求切換到其他機(jī)器后因?yàn)闆]有Session而無法完成業(yè)務(wù)處理勋颖。因此牙言,很少有網(wǎng)站采用此方案進(jìn)行Session管理。

 ⊥搅怠③Cookie記錄Session:利用瀏覽器支持的Cookie記錄Session簡單易行入挣,可用性高径筏,并且支持服務(wù)器的線性伸縮滋恬,因此恢氯,許多網(wǎng)站都或多或少地使用了Cookie來記錄Session勋拟。但是Cookie記錄Session有缺點(diǎn):比如受Cookie大小限制敢靡、每次請求響應(yīng)都要傳輸Cookie影響性能啸胧、用戶關(guān)閉了Cookie會造成訪問不正常等吓揪。

?

 ∧恰④Session服務(wù)器:利用獨(dú)立部署的Session服務(wù)器(集群)統(tǒng)一管理Session,應(yīng)用服務(wù)器每次讀寫Session時(shí)焙格,都訪問Session服務(wù)器眷唉。這種方案實(shí)際上是將應(yīng)用服務(wù)器的狀態(tài)分離冬阳,分為無狀態(tài)的應(yīng)用服務(wù)器和有狀態(tài)的Session服務(wù)器肝陪。

?

從上面的幾種方式來看氯窍,各有利弊狼讨,但Session服務(wù)器是最符合高可用需求的方案熊楼,也是企業(yè)中經(jīng)常用到的方案鲫骗。那么执泰,對于有狀態(tài)的Session服務(wù)器术吝,一種較簡單的方法是利用分布式緩存(如Memcached排苍、Redis等淘衙,有關(guān)Redis的簡單介紹可以閱讀我的博文:NoSQL初探之人人都愛Redis)、數(shù)據(jù)庫等具垫,在這些產(chǎn)品的基礎(chǔ)上進(jìn)行封裝筝蚕,使其符合Session的存儲和訪問要求起宽。綜合上述介紹燎含,我們今天就采用Memcached來構(gòu)建我們的Session服務(wù)器屏箍,解決Web服務(wù)器集群的Session的共享訪問赴魁。

PS:為什么要采用分布式緩存方案而不采用數(shù)據(jù)庫來存儲Session榄棵?這個(gè)就得要分析一下數(shù)據(jù)訪問的性能瓶頸了疹鳄,一般來說芦岂,磁盤IO讀寫的速度是最慢的腺怯,因?yàn)?a href="http://www.reibang.com/writer" target="_blank">數(shù)據(jù)庫數(shù)據(jù)其實(shí)是存儲在文件中的呛占,雖然目前大多數(shù)的數(shù)據(jù)庫都采用了B+樹結(jié)構(gòu)晾虑,讀取一條數(shù)據(jù)最多都還是需要4次的數(shù)據(jù)讀寫(三次磁盤訪問獲得數(shù)據(jù)索引及行ID,一次數(shù)據(jù)文件讀操作坠狡,終于知道數(shù)據(jù)庫操作多麻煩了)遂跟。而分布式緩存例如Memcached是以Key/Value這種簡單的形式存儲在服務(wù)器的內(nèi)存里邊的逃沿,內(nèi)存的隨機(jī)讀寫速度是完爆磁盤IO的婴渡,因此內(nèi)網(wǎng)+內(nèi)存的雙內(nèi)模式是比較完美的方案。

磁盤又分為兩種類型:

 】痢①機(jī)械硬盤:通過馬達(dá)驅(qū)動磁頭臂边臼,帶動磁頭到指定的磁盤位置訪問數(shù)據(jù)。它能夠?qū)崿F(xiàn)快速順序讀寫假消,慢速隨機(jī)讀寫。

 「晦帧②固態(tài)硬盤(又稱SSD):無機(jī)械裝置臼予,數(shù)據(jù)存儲在可持久記憶的硅晶體上,因此可以像內(nèi)存一樣快速隨機(jī)訪問啃沪。

  在目前的網(wǎng)站應(yīng)用中粘拾,大部分應(yīng)用訪問數(shù)據(jù)都是隨機(jī)的,這種情況下SSD具有更好的性能表現(xiàn)创千,但是性價(jià)比有待提升(蠻貴的缰雇,么么嗒)。

二追驴、Memcached實(shí)現(xiàn)Session的分布式存儲

2.0 案例總體預(yù)覽

 ⌒涤础(1)模擬的登錄案例場景

    假設(shè)我們有一個(gè)基于ASP.NET的信息系統(tǒng),這個(gè)系統(tǒng)使用一個(gè)統(tǒng)一的系統(tǒng)登錄頁面進(jìn)行用戶登錄氯檐,登陸后默認(rèn)跳轉(zhuǎn)到一個(gè)用戶中心主頁戒良,并顯示:歡迎您体捏,{用戶賬號名稱}冠摄。

    ①系統(tǒng)登錄頁面效果:

?

   〖哥浴②用戶主頁效果:

?

 『佑尽(2)模擬的技術(shù)體系選擇

    ASP.Net MVC+EF Code First+MySQL+Memcached

2.1 初始準(zhǔn)備工作

  (1)新建一個(gè)ASP.NET MVC4的空項(xiàng)目年栓,視圖引擎選擇為“Razor”即可拆挥;

  (2)在項(xiàng)目中新建一個(gè)文件夾某抓,取名為“Lib”纸兔,主要存放一些必要的DLL文件;

?

 》窀薄(3)在項(xiàng)目中添加對這幾個(gè)DLL的引用汉矿,注意這里引入EntityFramework.dll是為了支持后面的CodeFirst開發(fā)方式,EF版本必須在4.1及以上备禀。PS:你也可以通過Package Manager來安裝EntityFramework洲拇。到此奈揍,我們的準(zhǔn)備工作就做好了,接下來就可以開始正式的工作了赋续。

2.2 借助EF CodeFirst生成MySQL數(shù)據(jù)庫

首先男翰,EF是一種ORM(Object-relational mapping)框架,它能把我們在編程時(shí)使用對象映射到底層的數(shù)據(jù)庫結(jié)構(gòu)纽乱。ORM框架負(fù)責(zé)把從數(shù)據(jù)庫傳回的記錄集轉(zhuǎn)換為對象蛾绎,也可以依據(jù)對象當(dāng)前所處的具體狀態(tài)生成相應(yīng)的SQL命令發(fā)給數(shù)據(jù)庫,完成數(shù)據(jù)的存取工作(常見的數(shù)據(jù)存取操作可簡稱為CRUD:Create鸦列、Read秘通、Update、Delete)敛熬。

EF給數(shù)據(jù)庫應(yīng)用系統(tǒng)開發(fā)帶來了更高的效率肺稀,使用它能更容易地寫出易維護(hù)、易擴(kuò)展的系統(tǒng)应民,而且性能雖然比不上ADO.NET话原,但也足夠好,能滿足大多數(shù)開發(fā)場景的需求诲锹。與ADO.NET不一樣繁仁,EF的抽象層次較高:它把數(shù)據(jù)庫映射為DbContext,把數(shù)據(jù)庫中存取的數(shù)據(jù)直接映射為實(shí)體(Entity)對象归园,屏蔽了底層的數(shù)據(jù)庫內(nèi)部結(jié)構(gòu)黄虱,無需直接使用下層數(shù)據(jù)存取引擎所提供的底層對象(比如ADO.NET所提供的DbConnection,DbCommands等)完成CRUD庸诱。

EF支持三種開發(fā)模式:Code First捻浦、Database First和Model First。這里我們使用Code First模式桥爽,它能幫助我們實(shí)現(xiàn)快速開發(fā)迭代的目標(biāo)朱灿。最后,EF不是本文的重點(diǎn)钠四,如果你還不了解EF或者Code First盗扒,可以參閱金旭亮老師的《EF走馬觀花》系列文章,這里就不再贅述了缀去。

(1)在Models文件夾新建一個(gè)類侣灶,取名為“UserInfo”。它作為我們的實(shí)體類缕碎,映射到MySQL數(shù)據(jù)庫中的UserInfo表(這里MySQL數(shù)據(jù)庫中還未創(chuàng)建這樣的數(shù)據(jù)表)

?View Code

?View Code

(3)在Web.config中新增一個(gè)數(shù)據(jù)庫連接字符串褥影,database設(shè)置為“MySqlDemo”,與上面的MyDbContext中的構(gòu)造函數(shù)中的name保持一致阎曹。

?View Code

網(wǎng)絡(luò)異常取消重新上傳

至此伪阶,因?yàn)槲覀冎挥玫経serInfo這一個(gè)表煞檩,所以現(xiàn)在我們有關(guān)數(shù)據(jù)庫與EF的代碼就到此結(jié)束。

2.3 自己封裝Memcached幫助類對外提供服務(wù)接口

 ≌ぬ(1)在Web.config中新增一個(gè)AppSetting斟湃,保存Memcached服務(wù)器的地址列表:

? ? <!-- 設(shè)置Memcached服務(wù)器集群列表 -->

? ? <add key="MemcachedServers" value="192.168.80.10:11211,192.168.80.11:11211"/>

  (2)在Models中新建一個(gè)類檐薯,取名為“MemcachedHelper”凝赛,我們將其設(shè)置為靜態(tài)類,所以方法全是靜態(tài)的坛缕,我們無需實(shí)例化便可直接調(diào)用墓猎。可以看到赚楚,我們這里使用了靜態(tài)構(gòu)造函數(shù)來初始化全局靜態(tài)對象毙沾,它不屬于任何一個(gè)實(shí)例,所以這個(gè)構(gòu)造函數(shù)只會被執(zhí)行一次宠页,而且是在創(chuàng)建此類的第一個(gè)實(shí)例或引用任何靜態(tài)成員之前左胞,由.NET自動調(diào)用。

?View Code

  這里我們沒有對SockIOPool進(jìn)行一列的配置举户,采用其默認(rèn)的配置即可烤宙。但是要注意的是:SockIOPool的PoolName和MemcacheClient的PoolName必須保持一致。

2.4 用戶登錄時(shí)調(diào)用Memcached幫助類接口存儲用戶登錄狀態(tài)

 〖筻摇(1)在Controller中新建一個(gè)控制器躺枕,取名為“LogonController”。主要用來顯示系統(tǒng)登陸頁和進(jìn)行用戶驗(yàn)證的AJAX操作(將用戶Session存入Memcached也在此操作中)供填。至于登錄頁面的HTML和JS腳本在此就不再贅述拐云,請自行下載Demo文件查看。

?View Code

  現(xiàn)在來看下這個(gè)控制器的核心代碼:

 〔端洹①Index這個(gè)Action主要用于顯示登錄視圖慨丐,頁面代碼不再貼出來,只看看下面這個(gè)AJAX請求代碼:借助JQuery AJAX向ValidateUserInfo這個(gè)Action提交用戶名和密碼泄私,如果服務(wù)器端校驗(yàn)成功則返回一個(gè)JSON對象,瀏覽器端判斷success屬性是否為true备闲,如果為true則跳轉(zhuǎn)到系統(tǒng)主頁晌端。

?View Code

②ValidateUserInfo這個(gè)Action則是根據(jù)瀏覽器提交過來的AJAX請求,判斷用戶名和密碼是否正確恬砂。這里用到了我們剛剛寫的MyDbContext咧纠,首先對它進(jìn)行實(shí)例化。(這一步非常重要泻骤,這時(shí)我們的MySQL數(shù)據(jù)庫中還木有MySqlDemo這個(gè)數(shù)據(jù)庫漆羔,當(dāng)?shù)谝淮螌?shí)例化MyDbContext時(shí)梧奢,EF會幫我們在MySQL中創(chuàng)建MySqlDemo這個(gè)數(shù)據(jù)庫,其本質(zhì)其實(shí)就是幫我們生成一串:crate databasemysqldemo;之類的SQL語句)演痒,然后使用Lambda表達(dá)式這種優(yōu)美的語法去進(jìn)行校驗(yàn)亲轨。如果你對Lambda表達(dá)式不熟悉,可以參閱MSDN的《Lambda表達(dá)式(C#編程指南)》一文來學(xué)習(xí)下鸟顺。

③就是最核心的部分惦蚊,我們采用Guid(保證作為Key的唯一性)作為SessionId寫入瀏覽器端的Cookie中,并以此作為Key存入Memcached分布式緩存中讯嫂,還給它設(shè)置了默認(rèn)失效時(shí)間(這里為20分鐘)蹦锋。之后,每次瀏覽器向服務(wù)器端提交請求時(shí)欧芽,在HTTP報(bào)文中都會附帶上這個(gè)Cookie莉掂,服務(wù)器端就可以通過這個(gè)Cookie作為Key去Memcached服務(wù)器中查找Session對象。

PS:一般來說千扔,Memcached的數(shù)據(jù)Key的命名是有講究的巫湘,這里傳智的老馬推薦了一個(gè)命名規(guī)則:{命名空間}-{部門名稱}-{項(xiàng)目名稱}。我們這里就簡單一點(diǎn)昏鹃,使用Guid來作為Key尚氛,因?yàn)槊看紊傻腉uid是唯一的。

2.5 封裝BaseController解決Action觸發(fā)前的校驗(yàn)規(guī)則

 《床场(1)在以往的信息系統(tǒng)項(xiàng)目開發(fā)中阅嘶,我們在系統(tǒng)里邊會做一個(gè)全局的校驗(yàn)器,判斷用戶的每次操作請求是否具有相應(yīng)的權(quán)限载迄,這里我們主要是校驗(yàn)用戶是否登錄讯柔,以便我們在具體的模塊中獲取用戶的Session對象。單機(jī)情況下护昧,我們一般就存入本機(jī)進(jìn)程內(nèi)的Session魂迄,因此就主要判斷Session中是否存在登錄狀態(tài)。這里我們使用Memcached來存儲Session對象惋耙,那么我們就在每個(gè)Action執(zhí)行前加一段規(guī)則:判斷Memcached中是否有當(dāng)前用戶的登錄狀態(tài)捣炬,如果有,則繼續(xù)執(zhí)行Action绽榛。如果木有湿酸,那么對不起,請進(jìn)行登錄灭美。

 ⊥评!(2)在WebForm中我們可以通過寫一個(gè)BasePage,使其繼承于Page届腐,重寫OnLoad事件铁坎,再讓其他頁面繼承于BasePage蜂奸,就可以對用戶是否登錄這個(gè)校驗(yàn)應(yīng)用到所有繼承了BasePage的Page類中。那么硬萍,在MVC模式中恰画,請求對象不再是xxx.aspx頁面類型员萍,而是/ControllerName/ActionName的路由椒惨,因此我們需要尋找一種針對Action的全局過濾方法翁都。額,在此我們不禁想到了一個(gè)高大上的英文:AoP(Aspect Oriented Programming)寒砖,它是軟件開發(fā)中一個(gè)較為熱門的話題赐劣,利用AOP可以對業(yè)務(wù)邏輯的各個(gè)部分進(jìn)行隔離,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低哩都,提高程序的可重用性魁兼,同時(shí)提高了開發(fā)的效率。因此漠嵌,我們對Action增加全局校驗(yàn)規(guī)則就是將Action的校驗(yàn)方法與Action的業(yè)務(wù)處理相分離咐汞,使其耦合度降低,也提高了Action的校驗(yàn)方法的重用性儒鹿,符合了AoP的思想化撕。那么,扯了大半天约炎,在ASP.NET MVC中到底如何實(shí)現(xiàn)呢植阴?別擔(dān)心,我們可以像寫B(tài)asePage一樣圾浅,寫一個(gè)BaseController來進(jìn)行處理掠手,使其繼承于Controller,然后將其他需要使用用戶登錄狀態(tài)校驗(yàn)的Controller都繼承于BaseController即可狸捕。

?View Cod ∨绺搿①從瀏覽器提交過來的HTTP請求報(bào)文中取得Cookie(也就是SessionId),如果沒有Cookie那么肯定還沒有登錄灸拍,將進(jìn)行重定向到登陸頁面做祝;

  ②如果有Cookie那么就去Memcached服務(wù)器中查詢是否有這個(gè)Key的數(shù)據(jù)內(nèi)容株搔,如果沒有沒有內(nèi)容剖淀,那么還是重定向到登陸頁面;如果有內(nèi)容纤房,則返回這個(gè)對象,由于返回的是Object類型翻诉,所以需要我們轉(zhuǎn)換一下賦給全局的用戶對象實(shí)例炮姨。

 “乒巍③獲取到UserInfo對象之后,再次將其重新存儲到Memcached中舒岸,這里其實(shí)是將Session延長失效時(shí)間绅作,實(shí)現(xiàn)了一個(gè)Session的滑動時(shí)間機(jī)制的效果。

PS:因?yàn)槲覀冊诘卿涷?yàn)證的Action里面給這個(gè)緩存設(shè)置的過期時(shí)間是一個(gè)絕對的時(shí)間蛾派,而非滑動過期時(shí)間俄认。所謂絕對時(shí)間是指到了指定時(shí)間以后便會失效,而滑動時(shí)間是指在指定時(shí)間內(nèi)無訪問請求便失效洪乍。

2.6 測試運(yùn)行用戶登錄與Session存儲

 ∶行印(1)到此,大部分的代碼都已完畢壳澳。這里我們需要進(jìn)行一個(gè)小測試岂贩,新建一個(gè)Controller,取名為“HomeController”巷波,將Index頁面用作登陸后的主頁萎津,顯示Session對象中的UserName屬性。代碼很簡單抹镊,只有兩行:

? ? ? ? public ActionResult Index()

? ? ? ? { // 從Memcached中獲取Session并傳給View ViewBag.UserName = CurrentUser.UserName; return View();

? ? ? ? }

  至于View锉屈,請參考Demo文件,此處就不在贅述了垮耳,就一堆HTML而已颈渊。

  (2)①開啟虛擬機(jī)中的兩臺Windows Server服務(wù)器氨菇,確保Memcached服務(wù)都已成功開啟儡炼。(如果你是裝在本機(jī)的,直接開啟服務(wù)即可)

②開啟MySQL數(shù)據(jù)庫服務(wù)查蓉,這里我的MySQL是裝在本機(jī)的乌询,所以只需要開啟服務(wù)即可。

(3)點(diǎn)擊調(diào)試豌研,開始運(yùn)行IIS Express服務(wù)器妹田,進(jìn)行測試吧騷年(這里需要說明的是:你需要首先隨便輸入一個(gè)賬號和密碼進(jìn)行數(shù)據(jù)庫的創(chuàng)建,因?yàn)槲覀儾捎玫氖荂ode First的方式鹃共,然后再進(jìn)入MySQL添加幾行測試用戶數(shù)據(jù)鬼佣,這里我已經(jīng)添加了幾行,開始進(jìn)行測試霜浴。)我在數(shù)據(jù)庫里邊添加了一行{賬號:edisonchou晶衷,密碼:123456},因此我輸入賬號和密碼,點(diǎn)擊登錄晌纫,會出現(xiàn)一個(gè)友好的提示:“正在驗(yàn)證中税迷,請稍候...”(如果你是第一次運(yùn)行,那么需要創(chuàng)建數(shù)據(jù)庫锹漱,這個(gè)時(shí)間會比較長箭养,不要擔(dān)心)。


 「珉埂(4)等待系統(tǒng)驗(yàn)證完成后毕泌,便會跳轉(zhuǎn)到系統(tǒng)主頁,顯示歡迎界面嗅辣『撤海可以看到,下圖中的兩處是根據(jù)Session的UserName來顯示的辩诞。

 】餐洹(5)現(xiàn)在我們手動修改URL,輸入/Logon/Index译暂,跳轉(zhuǎn)到登陸頁面抠忘。然后,再修改URL為/Home/Index外永,看看是否需要重新登錄崎脉,由于我們已經(jīng)將Session存入了Memcached,所以再次進(jìn)入/Home/Index這個(gè)Action時(shí)會進(jìn)行判斷伯顶,通過瀏覽器端傳過去的Cookie去Memcached中取Session囚灼,如存在則繼續(xù)執(zhí)行。這里祭衩,我們之前已經(jīng)登錄了灶体,所以不再需要重新登錄。下面是再次跳轉(zhuǎn)/Home/Index的HTTP報(bào)文信息掐暮,可以看出登錄之后已經(jīng)寫入了Cookie蝎抽,之后的請求都會帶上Cookie傳遞到服務(wù)器端,服務(wù)器端也就可以通過Cookie作為Key獲取Session對象路克。


 ≌两帷(6)新開一個(gè)瀏覽器,再使用另一個(gè)用戶數(shù)據(jù)進(jìn)行登錄:


 【恪(7)登陸后瓢宦,查看HTTP報(bào)文,獲取Cookie中的sessionId:


(8)根據(jù)兩個(gè)用戶的sessionId作為Key灰羽,在Memcached服務(wù)器中查看存儲情況:經(jīng)查看驮履,兩個(gè)Session都存儲到了192.168.80.11這臺服務(wù)器里邊鱼辙。為何沒有平均分配,這是因?yàn)樗惴ㄊ歉鶕?jù)計(jì)算Hash值來的疲吸,剛好這兩個(gè)sessionId計(jì)算后的Hash值都是要分配到192.168.80.11這臺服務(wù)器里邊座每,所以就都存到了這里邊前鹅。(需要注意的是:這里僅僅是在我的機(jī)器上跑的測試結(jié)果摘悴,網(wǎng)友們的測試結(jié)果可能會跟我的不一樣,這是正常的)

? ? ? ? 至此舰绘,我們的小測試到此結(jié)束蹂喻,我們的案例也到此為止

? ? ? ??歡迎學(xué)Java和大數(shù)據(jù)的朋友們加入java架構(gòu)交流:736925717?

加群鏈接:https://jq.qq.com/?_wv=1027&k=5XXrrMk

群內(nèi)提供免費(fèi)的架構(gòu)資料還有:Java工程化、高性能及分布式捂寿、高性能口四、深入淺出。高架構(gòu)秦陋。性能調(diào)優(yōu)蔓彩、Spring,MyBatis驳概,Netty源碼分析和大數(shù)據(jù)等多個(gè)知識點(diǎn)高級進(jìn)階干貨的免費(fèi)直播講解??可以進(jìn)來一起學(xué)習(xí)交流哦~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末赤嚼,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子顺又,更是在濱河造成了極大的恐慌更卒,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件稚照,死亡現(xiàn)場離奇詭異蹂空,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)果录,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進(jìn)店門上枕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人弱恒,你說我怎么就攤上這事辨萍。” “怎么了斤彼?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵分瘦,是天一觀的道長。 經(jīng)常有香客問我琉苇,道長嘲玫,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任并扇,我火速辦了婚禮去团,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己土陪,他們只是感情好昼汗,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著鬼雀,像睡著了一般顷窒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上源哩,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天鞋吉,我揣著相機(jī)與錄音,去河邊找鬼励烦。 笑死谓着,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的坛掠。 我是一名探鬼主播赊锚,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼屉栓!你這毒婦竟也來了舷蒲?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤系瓢,失蹤者是張志新(化名)和其女友劉穎阿纤,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體夷陋,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡欠拾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了骗绕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片藐窄。...
    茶點(diǎn)故事閱讀 39,711評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖酬土,靈堂內(nèi)的尸體忽然破棺而出荆忍,到底是詐尸還是另有隱情,我是刑警寧澤撤缴,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布刹枉,位于F島的核電站,受9級特大地震影響屈呕,放射性物質(zhì)發(fā)生泄漏微宝。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一虎眨、第九天 我趴在偏房一處隱蔽的房頂上張望蟋软。 院中可真熱鬧镶摘,春花似錦、人聲如沸岳守。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽湿痢。三九已至涝缝,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蒙袍,已是汗流浹背俊卤。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留害幅,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓岂昭,卻偏偏與公主長得像以现,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子约啊,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容