Memcache+cookie实现模拟session

  上一片讲到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实现分布式缓存

时间: 2024-08-11 21:41:20

Memcache+cookie实现模拟session的相关文章

[MVC学习笔记]6. 使用Memcache+Cookie解决分布式系统共享登录状态

      为了解决单机处理的瓶颈,增强软件的可用性,我们需要将软件部署在多台服务器上启用多个二级子域名以频道化的方式,根据业务功能将网站分布部署在独立的服务器上,或通过负载均衡技术(如:DNS轮询.Radware.F5.LVS等)让多个频道共享一组服务器.当我们将网站程序分部到多台服务器上后,由于Session受实现原理的局限,无法跨服务器同步更新Session,使得登录状态难以通过Session共享.       我们使用MemCache+Cookie方案来解决分布式系统共享登录状态的问题.

利用Node.js实现模拟Session验证的登陆

1.身份验证和用户登陆 在一般的Web应用上,如果要实现用户登陆,最常用,也是最简单的方法就是使用Session,基本的思路是在Session中保留一些用户身份信息,然后每次在Session中取,如果信息不正确或不存在,那么身份验证失败,正确则成功. Session和Cookie是两个很相似的东西,都是字符串,只不过Session是保存在服务器上的,而Cookie是保存在本地的,所以Cookie是不能用作身份验证的.Session故名思议,肯定和客户端与服务器间建立的会话相关,Session的工

Cookie &amp;amp;&amp;amp; Session &amp;amp;&amp;amp; Token

Cookies Cookie的由来: HTTP 本身是一个无状态的 request/response 协议. server接收一个来自client的request, 处理完以后返回一个response. 可是这个过程中, server差点儿没有什么信息能够用来判定是哪个client(用户)发来的request, 也无法记录用户的请求顺序. Cookie是眼下识别用户.实现持久会话最好的方式.Cookie通常会跟User-Agent.Referer.X-Forwarded-For,JS等技术共同使

什么是Cookie对象,Session对象,Application对象。

Cookie是: 一个由网页服务器放在您硬盘上的非常小的文本文件. 它本质上就像您的身份证明一样,并且不能像代码那样被执行或被用来散布病毒.它只能被您使用并且只能由提供的服务器读取. 使用Cookie的目的是: 告诉服务器您再次的访问该服务器. Cookie能为您做什么?: 帮您节约时间.如果您自定义页面,或注册产品或服务.cookie帮助微软记住您的身份.当下一次您再次访问的时候,我们将显示您需要的信息.或者当您注册另一个产品或服务的时候,您只需要键入您的E-mail和密码.我们将帮您填入任何

什么是Cookie对象,Session对象,Application对象等问题

1.什么是Cookie对象,Session对象,Application对象 Application对象应用程序状态:Web 应用程序的所有用户都可以访问该应用程序的状态信息Session对象,会话状态:只有特定会话中的用户可以访问该信息不同的用户正在使用某个应用程序,则每个用户都将有一个不同的会话状态客户端状态管理:Cookie对象Cookie:使用文本文件存储信息来维护状态Cookie对象也可以保存客户信息,与Session 对象相似,分别保存不同用户的信息.和Session的区别是:Sess

什么是Cookie对象,Session对象,application对象?

(1)Cookie对象是: 一个由网页服务器放在您硬盘上的非常小的文本文件. 它本质上就像您的身份证明一样,并且不能像代码那样被执行或被用来散布病毒.它只能被您使用并且只能由提供的服务器读取. 使用Cookie的目的是: 告诉服务器您再次的访问该服务器. Cookie能为您做什么?: 帮您节约时间.如果您自定义页面,或注册产品或服务.cookie帮助微软记住您的身份.当下一次您再次访问的时候,我们将显示您需要的信息.或者当您注册另一个产品或服务的时候,您只需要键入您的E-mail和密码.我们将帮

cookie编码乱码问题与cookie禁用后session操作

Cookie传输的值只能是ASCII码,该编码表相对老旧不含有很多符号与文字 特别是中文,所以在cookie传值过程中需要先转成相应的ASCII编码再解析 如下 URLEncoder.encode("小米", "utf-8") URLDecoder.decode(value,"utf-8") cookie禁用后无法使用cookie来传送session操作 所以需要通过url的方式进行传递 response.sendRedirect(respons

cookie机制和session机制的区别

一.cookie机制和session机制的区别 具体来说cookie机制采用的是在客户端保持状态的方案,而session机制采用的是在服务器端保持状态的方案.同时我们也看到,由于才服务器端保持状态的方案在客户端也需要保存一个标识,所以session机制可能需要借助于cookie机制来达到保存标识的目的,但实际上还有其他选择 二.会话cookie和持久cookie的区别 如果不设置过期时间,则表示这个cookie生命周期为浏览器会话期间,只要关闭浏览器窗口,cookie就消失了.这种生命期为浏览会

【转】PHP cookie禁用时session 方案

转载地址:PHP cookie禁用时session 方案 在PHP中使用过SESSION的朋友可能会碰到这么一个问题,SESSION变量不能跨页传递.这令我苦恼了好些日子,最终通过查资料思考并解决了这个问题.我认为,出现这个问题的原因有以下几点:1.客户端禁用了cookie2.浏览器出现问题,暂时无法存取cookie3.php.ini中的session.use_trans_sid = 0或者编译时没有打开--enable-trans-sid选项 为什么会这样呢?下面我解释一下: Session储