出处:http://www.cnblogs.com/newP/p/6518918.htmlhtml
1、Sessionnginx
一、Session 介绍git
我相信,搞Web开发的对Session必定再熟悉不过了,因此我就简单的介绍一下。程序员
Session:在计算机中,尤为是在网络应用中,称为“会话控制”。 每一个用户(浏览器)首次与web服务器创建链接时,就会产生一个Session,同时服务器会分配一个SessionId给用户的浏览器。咱们能够用Fiddler查看cookies中,会看到有一个ASP.Net_SessionId的cookie。你们都知道Http是无状态请求,可是ASP.Net中的Session仿佛又让Http请求变得有状态,其核心就在于这个叫ASP.Net_SessionId的cookie。你们能够想象一下,这个至关于数据库的Key,服务器那边再有个Session内容缓存表,是否是Session的内容就很容易获得了?固然Session不是那么简单,但Session原理不是本文介绍重点,因此请你们自行度娘。github
二、又爱又恨的Sessionweb
刚接触程序开发的人必定爱死Session了,由于Session让Http从无状态变成有状态了,页面之间传值、用户相关信息、一些不变的数据、甚至于查出来的DataTable也能够放进去,取值的时候只须要Session[Key]便可,真是方便极了。Session真是个利器,人挡杀人佛挡杀佛,但任何事物被封为利器基本也是双刃剑,Session的许多问题咱们不得不去面对。redis
【常见问题请见下图】数据库
我相信一见到这个问题,老程序员都会内心一哆嗦,Session是致使这个缘由之一,你们也会想到这个情景,“我去,是否是Session又丢了,让用户从新登陆”,事故报告中会填写:.NET规定,用户登录后长时间没操做致使的。解决方案为:把Session时间调到9999。编程
结果该发生的仍是继续发生着,Session照样丢失。windows
【常见Session丢失缘由】
一、Session超时,用户打开页面,页面长时间不操做会致使此缘由
二、IIS应用程序池回收,或者重启
三、Web.Config修改,即IIS应用程序池重启
四、dll被替换或者动态页面修改,即IIS应用程序池重启
五、杀毒软件对.config文件进行扫描,可能会致使IIS应用程序池回收
六、用户浏览器禁用cookie
七、其余缘由
其余缘由有点不负责,可是好多程序员没法查明是什么缘由致使Session丢失,但Session丢失我归结为两大类,一个是数据的Key丢了,一个是Session内容数据库的丢了,你们这样就好理解了,用户浏览器禁用cookie必定是Key没了。IIS应用程序池回收一定会致使Session的内容缓存表丢失,固然还有一些其余缘由。
三、解决Session丢失的漫长路
解决过Session丢失的都会用到这几种方法
一、InProc:将Session存到进程内。
二、StateServer:将Session存到独立的状态服务中(Asp.Net State Service)。
三、SqlServer:将Session存到SqlServer中。
四、Cookieless:设置客户端Session存储的方式。
用了这些方法以后,有的是该丢还丢,有的是稳定了速度却慢了。
你们也注意到了,还有个这个Custom自定义模式,有人会说:“除了大牛,有几个敢写的啊,写出来有问题怎么办,算了算了。” 等等,你们不要还停留在非开源模式下解决问题的思想,找找开源项目,必定能找到的,有人说ASP.NET上哪里找开源啊,很是简单NuGet,若是想了解开源,必定要学会使用NuGet。
2、Redis
一、前言
上文说了那么多,有人必定会说我是来解决Session丢失的,上哪里来的Session分布式共享,标题党,我仍是继续用个人cookie吧。
我要说的是,几年前,在Stack Overflow上找到了这个方法解决了丢失问题,以后,发现这种方法还能够实现Session分布式共享。那就是运用Custom自定义模式,将Session持久化到Memcache和Redis中。Session丢失、以及持久化到SqlServer数据的性能问题也随之解决。
此种方法很适合老项目中大量应用Session而致使法搞成分布式而苦恼的.NET开发人员使用。由于颇有可能老项目维护过程当中,身边的JAVA团队、PHP团队,正在重构你的项目。
二、RedisSessionProvider
正文开始,首先,沿着咱们的思路Session持久化到Memcache或者Redis中,经过nuget下载 RedisSessionProvider(别问我怎么找到的,由于我英文过了四级,我会使用度娘,嘿嘿)
【web.config配置以下】
<system.web> <sessionState mode="Custom" customProvider="RedisSessionProvider"> <providers> <add name="RedisSessionProvider" type="RedisSessionProvider.RedisSessionStateStoreProvider, RedisSessionProvider"/> </providers> </sessionState> </system.web>
【Global.asax】
void Application_Start(object sender, EventArgs e) { StackExchange.Redis.ConfigurationOptions redisConfigOpts = StackExchange.Redis.ConfigurationOptions.Parse("192.168.8.138:6379"); RedisSessionProvider.Config.RedisConnectionConfig.GetSERedisServerConfig = (HttpContextBase context) => { return new KeyValuePair<string, StackExchange.Redis.ConfigurationOptions>( "DefaultConnection", redisConfigOpts); }; }
【存储方法】
Session["Test"] = "aa";
【调用方法】
string str = Session["Test"].ToString()
!前方坑,请注意!
若是你配置好Redis,而且作好上面这些配置,运行会出现如下问题,请更新RedisSessionProvider的依赖包StackExchange.Redis到最新。
三、Redis安装
3-一、Redis for windows下载
若是会配置Redis的同窗,请略过此章节,直接进入Nginx。
Redis下载:https://github.com/MSOpenTech/redis
!此处为坑,请注意!
修改Redis.windows.conf,若是不修改,远程不能访问Redis
一、将bind 127.0.0.1 改为了bind 0.0.0.0。注意:进入生产环境时候,要启用密码,不然会是Redis漏洞,具体请自行度娘和本身公司的运维阿牛
2、protected-mode yes 改为 protected-mode no
详细修改的传送门: redis开启远程访问
3-二、启动Redis
redis-server redis.windows.conf
上图为redis启动成功,默认6379,能够经过redis-cli进行测试,看别的机子可否访问。还能够在找个redis可视化工具看看里面存了啥,也能够监控Session是否持久化到Redis中了。
3-三、验证Session是否持久化到Redis
运行RedisSessionProvider这个项目。同一个IIS下,同域名,不一样IP,同一浏览器,不一样端口一个是2459,一个是2490。
【注意】
不一样浏览器SessionId是不一样的。必须保证SessionId,测试必须是同一个浏览器进程分出的不一样子标签才能够,这样SessionId是共享的。
感受成功了,让咱们看看这样的拓扑图:
囧……这是啥玩意?个人分布式呢?这个拓扑图很显然不是分布式啊,还两个IP,我还要在前面作个路由登陆页面?这时Nginx该登场了。
3、Ngnix
一、Ngnix安装&下载
下载地址:http://nginx.org/
二、nginx.conf配置修改
2-一、【接口修改】
listen 80; 改为 listen 1100; 由于通常都被80都被使用。
2-二、【增长负载均衡】
upstream Jq_one { server 127.0.0.1:8770; server 192.168.8.138:7777; } server { ..... }
2-三、【location节点修改】
location / { root html; index index.aspx index.html index.htm; #其中jq_one 对应着upstream设置的集群名称 proxy_pass http://Jq_one; #设置主机头和客户端真实地址,以便服务器获取客户端真实IP proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
2-四、【Nginx启动命令】
C:\server\nginx-1.0.2>start nginx
或
C:\server\nginx-1.0.2>nginx.exe
2-五、【Nginx从新载入命令】
C:\server\nginx-1.0.2>nginx.exe -s reload
2-六、【参考文章】
详细配置传送门:nginx+iis实现负载均衡
4、Session分布式共享
一、拓扑图
经过Nginx+Redis实现对Session的分布式共享功能。经过测试,发现Session分布式共享共有两种解决方案。
二、利用Nginx的Ip_Hash进行Session分布式共享
使用nginx将同一ip的请求分配到固定服务器,修改以下。ip_hash会计算ip对应hash值,而后分配到固定服务器
upstream Jq_one{ server 127.0.0.1:8770;
server 192.168.8.138:7777;
ip_hash;
}
效果能够理解为就是一个Ip,经过Nginx路由到IIS_1上面,在屡次请求,会一直在IIS_1上,不会路由到IIS_2上面。
三、利用MachineKey进行Session分布式共享
Ip_Hash在必定程度上解决了Session分布式共享的问题,可是总感受没有发挥出nginx均衡负载的功能,继续改造
3-一、现将Ip_Hash去掉
去掉Ip_Hash重启Nginx,打开网站,点击设置Session按钮,结果报错
3-二、web.config添加MachineKey
<machineKey validationKey="86B6275BA31D3D713E41388692FCA68F7D20269411345AA1C17A7386DACC9C46E7CE5F97F556F3CF0A07159659E2706B77731779D2DA4B53BC47BFFD4FD48A54" decryptionKey="9421E53E196BB56DB11B9C25197A2AD470638EFBC604AC74CD29DBBCF79D6046" validation="SHA1" decryption="AES" />
【注意】
负载均衡的两个网站的MachineKey必须同样,不然出问题。
3-三、演示
下图,你们能够看到,服务器的Ip在不断变化,而Session却没有丢失,至此实现了Session分布式共享。
5、后记&感悟
但愿能经过本文,解决有的项目中Session分布式共享和Session丢失的难题,给你们一些解决问题、分析问题启发。
ASP.Net给咱们带来了新的一种编码体验,现在.Net已经15岁了,.Net的在企业中发展中扮演最多的角色是快枪手和背锅侠的角色,在企业刚起步时候选择易上手的.Net无非是最好的选择之一,可是由于.Net的高度封装,让.Net高级人才在市场上十分稀少,并且企业在创立之初应用.net的时候也不会考虑架构之类的问题。但是随着业务愈来愈复杂,.Net开发人员没法解决和知足市场的需求和项目中出现的技术难题,技术债随之产生,解决不了问题随之一些程序员便让.Net背锅,再加上.Net的新技术推陈出新(有好多人说微软瞎折腾,囧),WebForm、mvc、silverlight、sharepoint、wpf、window phone、wcf等等。但是中国大环境并不买帐,慢慢成长的企业发现.Net现有架构没法知足,.Net开发人员又没法解决现有问题,又找不到.Net架构师之类的角色,又看到了京东等大厂转JAVA的成功,其余企业家便会想咱也转个JAVA试试,招聘Java架构师,结果一大堆人应聘(高级的、中级的、技术总监),企业家高兴坏了,很快JAVA便组建了一支精英团队准备重构.net项目。JAVA发展的历史比Net要长不少,早些作JAVA开发早已转型为管理,你会发现如今市场上,挖过来的其中一些CTO很喜欢组建JAVA、PHP团队,NET团队不多,缘由多数是.Net不开源、不跨平台、解决方案不成熟,背后的缘由就不得而知了。但不得不说,JAVA语言很容易培养牛人,由于当你学了JAVA中的Spring,你就开始接触了IOC容器,你就在慢慢的面向接口编程,当你学会了的AOP,你就开始在面向方面编程的道路上迈出了一小步。语言只是一个工具,干了这么多年.Net,看看招聘信息或多或少有了些迷茫,路是本身走的,作出的决定就不能后悔,但在十字路口时,仍是多想想。
以上为我的观点,有可能由于知识和阅历的缘由,分析片面,请多谅解。
6、参考文章
.Net分布式架构(二):基于Redis的Session共享
很是感谢上述文章,对本文的启发,谢谢。