首页 > 程序开发 > 软件开发 > C# > 正文
c# ASP.NET 关于分布式Session的实践 架构
2017-02-02       个评论    来源:gzy11的专栏  
收藏    我要投稿
c# ASP.NET 关于分布式Session的实践 架构:由于公司域名全部要加CDN,原来的运维是把N台机器的Session写到一台机器上。索引用C#原生的Session不会产生任何问题。 由于业务上用session的地方较多,想重写原Session。

把Session存储在Memcached或Redis中。先了解下ASP.NET——SessionID 知识点: HTTP 是一种无状态协议。这意味着 Web 服务器会将针对页面的每个 HTTP 请求作为独立的请求进行处理。服务器不会保留以前的请求过程中所使用的变量值的任何信息。 ASP.NET通过会话标识符来判断是否是同一个客户端。简单点说就是依赖ASP.NET的SessionID值来判断,而默认情况下,SessionID 值存储在 Cookie 中。 Session是依赖于cookie的 如图下图: \ 会话标识符
会话由一个唯一标识符标识,可使用 SessionID 属性读取此标识符。为 ASP.NET 应用程序启用会话状态时,将检查应用程序中每个页面请求是否有浏览器发送的 SessionID 值。如果未提供任何 SessionID 值,则 ASP.NET 将启动一个新会话,并将该会话的 SessionID 值随响应一起发送到浏览器。
默认情况下,SessionID 值存储在 Cookie 中。但也可以将应用程序配置为在“无 Cookie”会话的 URL 中存储 SessionID 值。
只要一直使用相同的 SessionID 值来发送请求,会话就被视为活动的。如果特定会话的请求间隔超过指定的超时值(以分钟为单位),则该会话被视为已过期。使用过期的 SessionID 值发送的请求将生成一个新的会话。 ASP.NET客户端与服务端一般是2种情景 一:客服端Cookie中无ASP.NET SessionID。

ASP.NET服务端会检测客户端ASP.NET SessionID是否有值,如没有,服务端会回写客户端的ASP.NET SessionID。(注意:ASP.NET的SessionID是只读的,Cookie中默认的ASP.NET_SessionID为永不过期。) 二:ASP.NET 客户端每次访问服务端,会带着Cookie中ASP.NET SessionID值,跟服务端交互。当客户端中如有ASP.NET SessionID值,那么服务端的SessionID值就是跟客户端的一致。 如图所示: \ 分布式Session改造 1、原来的IIS中的Session使用集群的Redis或MemCached替代。
2、替代原则客户端通过cookie存一个唯一标识的值。类似于上图ASP.NET_SessionID.
3、利用cookie建立对应关系,实现Session的存取。实现存取时原Session的KEY值+cookie中唯一标识,对应Cache中的KEY。
如情景①中需要使用session["UserID"]=18 Cache中对应key如下kutroxgrm2eslsmdwz2nemvbfSL516+UserID=18   \ 知识点: HTTP 是一种无状态协议。这意味着 Web 服务器会将针对页面的每个 HTTP 请求作为独立的请求进行处理。服务器不会保留以前的请求过程中所使用的变量值的任何信息。 ASP.NET通过会话标识符来判断是否是同一个客户端。简单点说就是依赖ASP.NET的SessionID值来判断,而默认情况下,aspx" target="_blank">SessionID 值存储在 Cookie 中。 Session是依赖于cookie的 如图下图: \ 会话标识符
会话由一个唯一标识符标识,可使用 SessionID 属性读取此标识符。为 ASP.NET 应用程序启用会话状态时,将检查应用程序中每个页面请求是否有浏览器发送的 SessionID 值。如果未提供任何 SessionID 值,则 ASP.NET 将启动一个新会话,并将该会话的 SessionID 值随响应一起发送到浏览器。
默认情况下,SessionID 值存储在 Cookie 中。但也可以将应用程序配置为在“无 Cookie”会话的 URL 中存储 SessionID 值。
只要一直使用相同的 SessionID 值来发送请求,会话就被视为活动的。如果特定会话的请求间隔超过指定的超时值(以分钟为单位),则该会话被视为已过期。使用过期的 SessionID 值发送的请求将生成一个新的会话。 参考资料:https://msdn.microsoft.com/zh-cn/library/ms178581.aspx 在了解其本质后,改造现有的Session,经过筛选实现下图功能。(选择最常用的功能。红框)   \   核心代码如下: 运行不了的,请屏蔽用,自行补全Memcached的存取。
     public sealed class Session
    {
        #region
        private System.Web.HttpContext current = null;//System.Web.HttpContext.Current;
        private MemcachedContainer _cacheContainer = new MemcachedContainer();
        private readonly string company = "BX_Session_";
        private readonly string sessionId = "CCTV_SessionId"; //"ASP.NET_SessionId";//  //"ASP.NET_SessionId"
        public bool IsDebug = false;
        #endregion
        public Session()
        {
            current = System.Web.HttpContext.Current;
        }
        public Session(bool isDebug)
        {
            IsDebug = isDebug;
            current = System.Web.HttpContext.Current;
        }
        //public HttpSessionState Session;
        //public int Timeout = 20 * 1000;
        /// 
        /// 添加
        /// 
        ///
        ///
        ///
        public void Add(string key, object value, int timeOut = 20*60)
        {
            // memcachedClient.get (current.Session.SessionID + key); 

            if (current == null)
            {
                if (IsDebug) Logs.WriteLogInfo("[Add]SessionID=", "debug");
                _cacheContainer.Add(company + key, value, timeOut);
            }
            else
            {
                if (!current.Request.Cookies.AllKeys.Contains(sessionId))
                {
                    //current.Response.Cookies.Add(new HttpCookie("ASP.NET_SessionId", current.Session.SessionID));
                    current.Response.Cookies.Add(new HttpCookie(sessionId, current.Session.SessionID));
                }
                else
                {
                    //current.Response.Cookies.Add(new HttpCookie("ASP.NET_SessionId", current.Session.SessionID));
                    current.Response.Cookies.Add(new HttpCookie(sessionId, current.Session.SessionID));
                    current.Request.Cookies.Add(new HttpCookie(sessionId, current.Session.SessionID));
                }
                if (IsDebug) Logs.WriteLogInfo("[Add]SessionID=" + current.Request.Cookies[sessionId].Value, "debug");
                //_cacheContainer.Add(company + current.Session.SessionID + "_" + key, value, timeOut);               
                _cacheContainer.Add(company + current.Request.Cookies[sessionId].Value + "_" + key, value, timeOut);
            }
            //_cacheContainer.Get(key)
        }

        /// 
        /// 获取key值
        /// 
        ///
        /// 
        public object Get(string key)
        {
            if (current == null)
            {
                if (IsDebug) Logs.WriteLogInfo("[Get]SessionID=", "debug");
                return _cacheContainer.Get(company + key);
            }
            else
            {
                if (current.Request.Cookies.AllKeys.Contains(sessionId))
                {
                    if (IsDebug) Logs.WriteLogInfo("[Get]SessionID=" + sessionId, "debug");
                    return _cacheContainer.Get(company + current.Request.Cookies[sessionId].Value + "_" + key);
                }
                return null;
            }


        }
        /// 
        /// 移除
        /// 
        ///
        public void Remove(string name)
        {

            if (current == null)
            {
                if (IsDebug) Logs.WriteLogInfo("[Remove]SessionID=", "debug");
                _cacheContainer.Remove(company + name);
            }
            else
            {
                if (current.Request.Cookies.AllKeys.Contains(sessionId))
                {
                    if (IsDebug) Logs.WriteLogInfo("[Remove]SessionID=" + current.Session.SessionID, "debug");
                    _cacheContainer.Remove(company + current.Request.Cookies[sessionId].Value + "_" + name);
                }
            }

        }

        //
        // 摘要: 
        //     按名称获取或设置会话值。
        //
        // 参数: 
        //   name:
        //     会话值的键名。
        //
        // 返回结果: 
        //     具有指定名称的会话状态值;如果该项不存在,则为 null。
        public object this[string name]
        {
            get { return Get(name); }
            set
            {
                Add(name, value);
            }
        }

    }
点击复制链接 与好友分享!回本站首页
上一篇:C# 7.0新功能
下一篇:C#中stringBuilder和string的区别
相关文章
图文推荐
文章
推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训
版权所有: 红黑联盟--致力于做实用的IT技术学习网站