1. 程式人生 > >Memcache+cookie實現模擬session

Memcache+cookie實現模擬session

first 登陸 prot 集群配置 hello1 端口 lob 修改 image

  上一片講到Memcached在Windows上的安裝,和用Telnet工具進行命令操作,在稍微了解了原理之後,我也就開始嘗試著用程序來對Memcached進行操作。這一篇分為兩個部分,第一部分是用.net程序對Memcached進行操作,第二部分是結合mvc實現一個分布式的緩存系統。

一、.net程序對Memcached進行操作

  想要用.net操作Memcached,首先我們的去下載.NET客戶端類庫:https://sourceforge.net/projects/memcacheddotnet,下載完成之後,會發現裏面有一些Demo,而需要引用的程序集就只有ICSharpCode.SharpZipLib.dll,Memcached.ClientLibrary.dll,log4net.dll(可有可無)。


  技術分享

  技術分享

  上圖就是創建了一個控制臺應用程序,將這三個程序集引入項目。之後,將Memcached服務打開。再之後,就是代碼。  

  

            string[] serverlist = { "127.0.0.1:11211" };
            SockIOPool sock = SockIOPool.GetInstance();   
            sock.SetServers(serverlist);//添加服務器列表 
            sock.InitConnections = 5;//設置連接池初始數目
            sock.MinConnections = 3
;//設置最小連接數目 sock.MaxConnections = 6;//設置最大連接數目 sock.SocketTimeout = 3000;//設置套接字超時讀取 sock.MaintenanceSleep = 30; //設置維護線程運行的睡眠時間。如果設置為0,那麽維護線程將不會啟動; sock.Failover = true; //獲取或設置池的故障標誌。 sock.MaxBusy = 1000 * 10; //socket單次任務的最大時間(單位ms),超過這個時間socket會被強行中斷,當前任務失敗
sock.Initialize(); MemcachedClient mc = new MemcachedClient(); //清除所有的緩存數據 mc.FlushAll(); //增加 mc.Add("k","hello"); //增加一個鍵k1,值是hello1,有效時間是30s mc.Add("k1", "hello1", DateTime.Now.AddSeconds(30)); // 將k的值重新設置為123 ,用set時,假如鍵存在,就直接修改,鍵不存在,就直接創建,再賦值 mc.Set("k","123"); //將k的值重置為456 , 用Replace時,假如鍵存在,就直接修改,鍵不存在,報錯 mc.Replace("k", "456"); //刪除 mc.Delete("k");

  到這裏,我們用程序操作Memcached已經成功,我們程序運行完成之後,可以用telnet鏈接,看看數據是否加載進去了。這個比較簡單,下面看個復雜點的。

二、Memcache+cookie實現模擬session

  1.session的使用原理

  以前在開發系統中,像用戶這些基本信息,是直接保存在session中的,原理就是如下圖所示,用戶第一次訪問時,服務器創建session,並把sessionid寫回瀏覽器的cookie中,之後,瀏覽器每次訪問服務器時,就把這個sessionid一同和其他數據發送到服務器端,這樣就解決了Http協議是無狀態鏈接這個問題了。簡單原理就是這樣,更加詳細的session介紹詳見http://www.cnblogs.com/lyzg/p/6067766.html(圖也是人家的*-*)。

  技術分享

  2.Memcache+cookie代替session

  總的來說,session也不是完美的,會有易丟失,耗資源,單臺服務器時還好,一遇到集群,就有點尷尬了,所以現在就模擬一下這個情況。這個例子的整體結構是這樣子,搭建兩個web服務器,同樣也搭建兩個Memcached服務器,好吧,雙集群。

  1-6這個過程是,當用戶從web1站點登陸,先去查詢Memcached集群裏是否有用戶信息,這個肯定沒有,之後就去數據庫查,查到之後,就把用戶的信息給存到Memcached中,具體存到哪個,這個先不做談論。

  7-10過程,用戶通過web2站點 訪問數據,先去Memcached集群裏查是否有信息(這個如何查的也先不做談論),查到後,就直接把信息返回。

技術分享

  接下來,我們就新建項目,添加引用,項目的結構如圖所示,一個mvc4的框架,數據庫鏈接用的是dapper。項目用了過濾器,寫在BaseController裏面,並且在Global.asax文件裏要進行註冊,其中UserLoginController沒有繼承BaseController,HomeController繼承了BaseController。

  技術分享

  重要的代碼有兩段,一段就是登陸時候成功後,用guid生成隨機數,將這個隨機數作為seeionid寫到瀏覽器的cookie中,同時把該用戶的信息,sessionid這些信息存到Memcached中。

   string sql = "select * from UserInfo where [email protected] and [email protected]";
            using (var conn = SqlHelper.Connection)
            {
                 var  loginUser1 = conn.QueryFirstOrDefault<UserInfo>(sql, new  { UName = user.UName, UPwd = user.UPwd });
                var loginUser = SqlMapper.QueryFirstOrDefault<UserInfo>(conn,sql, new  { UName = user.UName, UPwd = user.UPwd });
                if (loginUser == null)
                {
                    return Content("用戶名密碼錯誤!");
                }
                else
                {
                    Guid sessionId = Guid.NewGuid();//申請了一個模擬的GUID:SessionId

                    //把sessionid寫到客戶端瀏覽器裏面去了(一定要把sessionid寫到客戶端,這樣用戶在訪問其他web資源的時候,
// 就會把cookie中的信息傳給服務器,然後通過sessionid的key到Memcached中去取對應的值)
Response.Cookies["sessionId"].Value = sessionId.ToString(); //再把用戶的信息插入到Memcached中 MemcacheHelper.Set(sessionId.ToString(), loginUser, DateTime.Now.AddMinutes(20)); return Content("ok"); } }

  而另一段比較重要的代碼就寫在過濾器裏,根據瀏覽器發過來的sessionid來去memcache中查詢數據,查到的話,表示校驗成功,否則跳轉回登陸界面。

 
 protected override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            base.OnActionExecuting(filterContext);

            //從cookie中獲取咱們的 登錄的sessionId
            string sessionId = Request["sessionId"];
            //如果sessionid為空值,則跳轉到登錄頁面
            if (string.IsNullOrEmpty(sessionId))
            {
                //return RedirectToAction("Login", "Logon");
                Response.Redirect("/UserLogin/Index");
                return;
            }

            object obj = MemcacheHelper.Get(sessionId);
            UserInfo user = obj as UserInfo;
            if (user == null)
            {
                 //用戶長時間不操作,。超時。
                Response.Redirect("/UserLogin/Index");
            }

            LoginUser = user;
            //實現session的滑動機制
            MemcacheHelper.Set(sessionId, user, DateTime.Now.AddMinutes(20));
}

關於memcached集群的配置很簡單,寫在MemcacheHelper中,只需要將Memcache的服務地址寫進去就行,以逗號分開,之後再設置一下權重就好了。

   //通過客戶端來進行memcached的集群配置,在插入數據的時候,使用一致性哈希算法,將對應的value值存入Memcached
            String[] serverlist = { "127.0.0.1:11211" , "127.0.0.1:11212" };

            // 初始化Memcached的服務池
            SockIOPool pool = SockIOPool.GetInstance("test");
            //設置服務器列表
            pool.SetServers(serverlist);
            //各服務器之間負載均衡的設置比例
            pool.SetWeights(new int[] { 1 });
            pool.Initialize();
            //創建一個Memcached的客戶端對象
            mc = new MemcachedClient();
            mc.PoolName = "test";
            //是否啟用壓縮數據:如果啟用了壓縮,數據壓縮長於門檻的數據將被儲存在壓縮的形式
            mc.EnableCompression = false;

  之後,將網站發布到iis上的不同的端口號上就行了。要是想有調試效果, 直接將項目復制兩份,其中一個端口號改下,啟動就好了。

最後發現,當登陸一個網站成功後,我們再去訪問另一個網站(不要換瀏覽器,cookie),發現也能直接訪問了。

  這樣一個關於memcached的分布式緩存系統就完成了,再寫的過程,又是知識加深的過程,書常讀常新,加油??。

代碼地址

碼雲:http://git.oschina.net/sdadx/leiku/tree/master/WebMemcache

參考:1.memcached安裝及.NET中的Memcached.ClientLibrary使用詳解

   2.使用緩存的9大誤區(上)

   3.3種web會話管理的方式

4.memcached全面剖析–4. memcached的分布式算法

5.ASP.Net MVC4+Memcached+CodeFirst實現分布式緩存

Memcache+cookie實現模擬session