MainForm构建分布式架构

 

 1  /// <summary>
 2     /// Login扩展类
 3     /// </summary>
 4     public class UserLoginExtend
 5     {
 6 
 7         public static string HashSessionKey = "Hash_SessionIds";
 8         public static string CookieName = "Sid";
 9 
10         public static T BaseSession<T>(HttpContextBase context) where T : class,new()
11         {
12             //获取cookie中的token
13             var cookie = context.Request.Cookies.Get(CookieName);
14             if (cookie == null) { return default(T); }
15 
16             //使用toke去查询缓存工厂是否有对应的session信息,如果有自动把缓存工厂的时间往后延nAddCookieExpires分钟
17             //return CacheRepository.Current(CacheType.RedisCache).GetHashValue<T>(HashSessionKey, cookie.Value);
18             return CacheRepository.Current(CacheType.RedisCache).GetCache<T>(cookie.Value);
19         }
20 
21         public static RedirectResult BaseCheckLogin<T>(
22             HttpContextBase context,
23             out T t,
24             int nAddCookieExpires = 30,
25             string loginUrl = "/User/Login") where T : class,new()
26         {
27             var returnUrl = context.Request.Path;
28             var result = new RedirectResult(string.Format("{0}?returnUrl={1}", loginUrl, returnUrl));
29             t = default(T);
30             try
31             {
32 
33                 //获取cookie中的token
34                 var cookie = context.Request.Cookies.Get(CookieName);
35                 if (cookie == null) { return result; }
36 
37                 //使用toke去查询缓存工厂是否有对应的session信息,如果有自动把缓存工厂的时间往后延nAddCookieExpires分钟
38                 //t = CacheRepository.Current(CacheType.RedisCache).GetHashValue<T>(HashSessionKey, cookie.Value);
39                 t = CacheRepository.Current(CacheType.RedisCache).GetCache<T>(cookie.Value, true);
40                 if (t == null)
41                 {
42                     //清空cookie
43                     cookie.Expires = DateTime.Now.AddDays(-1);
44                     context.Response.SetCookie(cookie);
45                     return result;
46                 }
47 
48                 //登陆验证都成功后,需要重新设置cookie中的toke失效时间
49                 cookie.Expires = DateTime.Now.AddMinutes(nAddCookieExpires);
50                 context.Response.SetCookie(cookie);
51 
52                 //设置session失效时间
53                 CacheRepository.Current(CacheType.RedisCache).AddExpire(cookie.Value, nAddCookieExpires);
54             }
55             catch (Exception ex)
56             {
57                 return result;
58             }
59             return null;
60         }
61 
62         public static RedirectResult BaseLoginOut(HttpContextBase context, string redirectUrl = "/")
63         {
64             var result = new RedirectResult(string.IsNullOrEmpty(redirectUrl) ? "/" : redirectUrl);
65             try
66             {
67                 //获取cookie中的token
68                 var cookie = context.Request.Cookies.Get(CookieName);
69                 if (cookie == null) { return result; }
70 
71                 var key = cookie.Value;
72 
73                 //设置过期cookie(先过期cookie)
74                 cookie.Expires = DateTime.Now.AddDays(-1);
75                 context.Response.SetCookie(cookie);
76 
77                 //移除session
78                 //var isRemove = CacheRepository.Current(CacheType.RedisCache).RemoveHashByKey(HashSessionKey, key);
79                 var isRemove = CacheRepository.Current(CacheType.RedisCache).Remove(key);
80             }
81             catch (Exception ex)
82             {
83 
84                 throw new Exception(ex.Message);
85             }
86             //跳转到指定地址
87             return result;
88         }
89     }

BaseCheckLogin方法主要用来验证是还是不是登入,未有登陆跳转到重定向地址中;借使证实是登陆情况,会自行重新安装redis存款和储蓄的session保质期,并再一次设置cookie保藏期;看代码的话实际就那一点首要之处都有备注说明;

见状的redis里的key和大家浏览器截图中的key是同等的,所以本章要将的内容大概将要结束了,若是感到小说让您抱有收获,请多多点"",谢谢。

图片 1

 1 public class BaseController : Controller
 2     {
 3 
 4         protected StageModel.MoUserData userData;
 5 
 6         protected override void Initialize(System.Web.Routing.RequestContext requestContext)
 7         {
 8 
 9             //使用登录扩展,验证登陆,获取登陆信息
10             var redirectResult = UserLoginExtend.BaseCheckLogin(requestContext.HttpContext, out userData,2);
11             //验证失败,跳转到loginUrl
12             if (redirectResult != null)
13             {
14                 requestContext.HttpContext.Response.Redirect(redirectResult.Url, true);
15                 return;
16             }
17 
18             //验证成功,添加视图访问登陆信息数据
19             ViewBag.UserData = userData;
20             base.Initialize(requestContext);
21         }
22     }

. nginx+iis营造服务集群

 

. 分析遍布式session的漂流进程

 

图片 2

末尾,既然要满意分享session,那么session要么纵然保存在同一个地点,读取的时候也在同二个地点读取;要么就redis集群这种方法落实即时同步到差异服务器上或分化端口达成数据读写分离;那样就能够保障统大器晚成数据源;

. 客户要去的应和的session,正是经过cookie存储的key传递给每台遍布式的站点,站点获取cookie再去钦定的session读取的地点得到是还是不是有相应的key并赢得session保存的数额;只要顾客有实用的cookie就会登入布满式系统;假设自身用ie浏览器登入系统后,再选拔google浏览器访问系统,那样使用google浏览器时候登入不成功的,因为cookie没有跨域,不过只要您手动依然经过别的人为方式利用ie登入成功后重回的cookie的key出席到google中,那么相近登录也是没难点的,能够试试根据规律深入分析是没难题的

. Redis存款和储蓄遍及式session的登入实例(这里是.net mvc代码操作卡塔尔(قطر‎

上面敬小慎微的来分享:

. 剖析分布式session的漂泊进度

View Code

. 发生session其实正是保存session数据,在客户使用分布式站点率先次登录时,从数据库检查此账号运转登入,在回去登陆成功消息给客户前,会先生成一个布满式系统中独占鳌头的叁个key,这几个key平日接纳的平整是布满式站点Id(每种遍布式子站点对应的Id卡塔尔(قطر‎+时间戳+顾客登入唯黄金年代的账号+加密串+Guid组合而成(也是有其它分歧的保障唯意气风发key的艺术吗卡塔尔,然后用md5或hash等加密,再把顾客的根底音信和key一齐保存到钦赐的Redis服务(姑且用redis存session,平常是键值没有错关系卡塔尔中,而且会回到key到客商的cookie中

 

. 系统怎么发生分享session

. 掌握遍布式的session(个人精晓卡塔尔

图片 3图片 4

. 顾客依据何种数据得到风流倜傥致的session

其次,session的读写分离经常都对应站点有极大的访谈量了,借使访谈量如此之大那么站点的公告对应的相应也是集群的章程(名叫分布式结构),布满式架议和单站点情势比较最显眼的在于布满式对应的八个站点只供给利用在那之中某三个登录入口登录后,别的站点分享此session,无需再做登入操作,其实这里就足以看做是单点登入,只是分布式集群平日访谈的都以同二个域名或同生龙活虎ip段而已;而单站点方式平常正是本身那边登入了,就只可以作者本系统能应用,此外的系统不能运用(常规来说);

此番要享用的是使用windows+nginx+iis+redis+Task.MainForm构建布满式结构,上风华正茂篇共享随笔制作是在windows上利用的nginx,常常标准发布的时候是在linux来布署nginx,笔者那边测量检验分享内容只是起教导功效;上面将先交给整个布局的基本节点简要介绍,希望各位多多点赞:

首先,操作session格局,这里要说的是登陆的session,精通是依据个人观点来的,并且这里的知晓大概不是那么深切哈;平常大家建设的网址大概管理体系都有顾客登录,登入后会有二个存款和储蓄客商基本消息的session保存在服务器,保存session的办法有多中,这里要享受的是利用redis来囤积session;随着登录客商扩展,存款和储蓄在服务器上的session也越来越多,即使某台服务器上行使内部存款和储蓄器保存的sesssion那服务器的内部存款和储蓄器据有会比较的进级换代,最后可能平昔接奔向溃,严重的是因为长日子百分之百内部存款和储蓄器占用率恐怕变成硬盘烧坏,由此发生了多样囤积格局如:使用同步session到不相同服务器方式做读写抽离,数据仓库储存款和储蓄session等情势;其实大家要用到的redis集群存款和储蓄操作session的法子也主假设分派读写;

BaseLoginOut方法主要用来清空顾客注销后的session数据和cookie数据;那多少个方式都以兴味索然登陆验证供给的内容,两方法重回的是RedirectResult,适用于.net的mvc版本;

. 驾驭布满式的session(个人通晓卡塔尔(قطر‎

. redis存款和储蓄布满式分享的session及分享session运作流程

. 定期框架Task.MainForm提供数据给redis集群积攒

浅紫框里面包车型地铁正是咋们本人生育的Sid也正是上面说的key,接着咋们在张开四个浏览器tab,来看下系统02的Sid,如图:

. 分享session生存的周期

先是,看下登入的action代码:

. redis主从构造及Sentinel管理八个Redis集群

 

透过上海体育场所能够看来系统01和系统02,对应的sid都以平等的值,每回那样布满式站点的session使用和创设就水到渠成了,好那咋们通过redis-cli.exe顾客端看下大家登录后保存在redis服务中的数据图如:

第生龙活虎,上边的原委也基本介绍了下布满式session(session数据源统黄金年代),这里要说的是布满式登陆时几个问号:

上边来交给对应上边难点的答问及注解:

 1 [HttpPost]
 2         //[ValidateAntiForgeryToken]
 3         public ActionResult Login([Bind(Include = "UserName,UserPwd", Exclude = "Email")]MoUserInfo model, string returnUrl)
 4         {
 5 
 6             if (ModelState.IsValid)
 7             {
 8                 //初始化数据库读取数据  nginx+iis+redis+Task.MainForm组建分布式架构 - (nginx+iis构建服务集群)
 9                 model.Email = "841202396@qq.com";
10                 model.Id = 1;
11                 model.Introduce = "专注web开发二十年";
12                 model.Sex = false;
13                 model.Tel = "183012787xx";
14                 model.Photo = "/Content/ace-master/assetsvatars/profile-pic.jpg";
15 
16                 model.NickName = "神牛步行3";
17                 model.Addr = "北京-亦庄";
18                 model.Birthday = "1991-05-31";
19                 model.Blog = "http://www.cnblogs.com/wangrudong003/";
20 
21                 var role = new StageModel.MoRole();
22                 role.Name = "系统管理员";
23                 role.Des = "管理整个系统";
24 
25                 //根据角色Id获取对应菜单Id,这里构造成List<int>形式
26                 var menus = new List<StageModel.MoMenu>{
27                   new  StageModel.MoMenu{
28                       Id = 1001,
29                       Link="/User/UserCenter"
30                   },
31                    new  StageModel.MoMenu{
32                       Id = 1002,
33                       Link="/User/ChangeUser1"
34                   },
35                   new  StageModel.MoMenu{
36                       Id = 1003,
37                       Link=""
38                   },
39 
40                    new  StageModel.MoMenu{
41                       Id = 2001001,
42                       Link=""
43                   },
44                    new  StageModel.MoMenu{
45                       Id = 2001002,
46                       Link=""
47                   }
48                 };
49 
50                 //赋值个人信息
51                 var userData = new StageModel.MoUserData();
52                 userData.Email = model.Email;
53                 userData.Id = model.Id;
54                 userData.Introduce = model.Introduce;
55                 userData.Sex = model.Sex;
56                 userData.Tel = model.Tel;
57                 userData.Photo = model.Photo;
58 
59                 userData.UserName = model.UserName;
60                 userData.NickName = model.NickName;
61                 userData.Addr = model.Addr;
62                 userData.Birthday = model.Birthday;
63                 userData.Blog = model.Blog;
64 
65                 //能访问菜单的Ids  
66                 userData.Menus = menus;
67 
68                 //获取唯一token
69                 var token = CacheRepository.Current(CacheType.BaseCache).GetSessionId(userData.UserName);
70                 var timeOut = 2; //分钟
71                 //if (CacheRepository.Current(CacheType.RedisCache).SetHashCache<StageModel.MoUserData>("Hash_SessionIds", token, userData,2))
72                 if (CacheRepository.Current(CacheType.RedisCache).SetCache<StageModel.MoUserData>(token, userData, 2, true))
73                 {
74                     var cookie = new HttpCookie(UserLoginExtend.CookieName, token);
75                     cookie.Expires = DateTime.Now.AddMinutes(timeOut);
76                     HttpContext.Response.AppendCookie(cookie);
77 
78                     return new RedirectResult(returnUrl);
79                 }
80             }
81 
82             return View(model);
83         }

图片 5

里头用到了 var token = CacheRepository.Current(CacheType.BaseCache).GetSessionId(userData.UserName卡塔尔(قطر‎ 方法,这一个方法主假诺用来博取上边说的布满式唯风姿浪漫的key,参数只供给传递顾客登入的独一账号就能够了(底层用的是Md5hash值算法,文字结尾给出所以代码);获取key后接受 CacheRepository.Current(CacheType.RedisCache卡塔尔(قطر‎.SetCache<StageModel.MoUserData>(token, userData, 2, true卡塔尔(英语:State of Qatar) 方法来设置登入的宗旨音信到redis服务中,假诺保存redis数据成功再通过 HttpContext.Response.AppendCookie(cookie卡塔尔国; 吧key输出到顾客的cookie中保存;

接下来,登入后经常会跳转到客商后台,客商后台的部分页面供给报到验证,作者那边是应用后台多少个Controller来世襲同二个父级BaseController,父级里面重写Initialize方法来注脚登入新闻;代码如下:

先是,将在发出去的多少个C#方法都进过测量检验了,我们可以向来拿来接纳,当然此方法用到了前方分享的CacheRepository缓存工厂,因为本身保留session是在redis中,上面先来贴出方法内容:

. 封装session登入验证和抽离的共用艺术

BaseCheckLogin方法正是大家地点分享的公物验证登录的艺术,具体参数能够看下参数描述表达;代码写好后,来看下运转的页面效果(小编这里运用的是前意气风发章我们的nginx集群来演示):

. session的生命周期大家应该都很关心,平时叁个session不容许设置成有线久的生命周期,那个时候就须求遵守每一回客户触发验证登入的时候,自动从新安装session失效时间(经常就当前时刻以后推你session定义的晚点时间);由于遍布式用到了cookie所以那个时候还须要再一次更新设置下cookie的key过期时间,那样使用cookie+seesion来保存客商的登录有效性,直到客商抢先了session保藏期还并未有接触过登入验证也许特殊措施消逝了cookie,那那个时候过期的cookie或session就能申明客户须要报到才具访谈要求权限的页面

. 封装session登入验证和退出的公物艺术

以上是一切结构的本人觉着基本的局地,在那之中未有满含有数据库方面包车型地铁设计(请忽视),上边来标准分享今天的篇章吧(redis存款和储蓄布满式分享的session及分享session运作流程):

. Redis存储遍及式session的登陆实例

. 布局划杜撰计图展现

 

本文由银河网址发布于银河网址,转载请注明出处:MainForm构建分布式架构

您可能还会对下面的文章感兴趣: