zoukankan      html  css  js  c++  java
  • Session分布式共享 = Session + Redis + Nginx

    一、Session


    1、Session 介绍

          我相信,搞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原理不是本文介绍重点,所以请大家自行度娘。

    image

    2、又爱又恨的Session

          刚接触程序开发的人一定爱死Session了,因为Session让Http从无状态变成有状态了,页面之间传值、用户相关信息、一些不变的数据、甚至于查出来的DataTable也可以放进去,取值的时候只需要Session[Key]即可,真是方便极了。Session真是个利器,人挡杀人佛挡杀佛,但任何事物被封为利器基本也是双刃剑,Session的许多问题我们不得不去面对。

    【常见问题请见下图】

          image

          我相信一见到这个问题,老程序员都会心里一哆嗦,Session是导致这个原因之一,大家也会想到这个情景,“我去,是不是Session又丢了,让用户重新登录”,事故报告中会填写:.NET规定,用户登陆后长时间没操作导致的。解决方案为:把Session时间调到9999。

          结果该发生的还是继续发生着,Session照样丢失。

    常见Session丢失原因】

          1、Session超时,用户打开页面,页面长时间不操作会导致此原因

          2、IIS应用程序池回收,或者重启

          3、Web.Config修改,即IIS应用程序池重启

          4、dll被替换或者动态页面修改,即IIS应用程序池重启

          5、杀毒软件对.config文件进行扫描,可能会导致IIS应用程序池回收

          6、用户浏览器禁用cookie

          7、其他原因

          其他原因有点不负责,但是好多程序员无法查明是什么原因导致Session丢失,但Session丢失我归结为两大类,一个是数据的Key丢了,一个是Session内容数据库的丢了,大家这样就好理解了,用户浏览器禁用cookie一定是Key没了。IIS应用程序池回收必定会导致Session的内容缓存表丢失,当然还有一些其他原因。

    3、解决Session丢失的漫长路

          解决过Session丢失的都会用到这几种方法

              1、InProc:将Session存到进程内。

              2、StateServer:将Session存到独立的状态服务中(Asp.Net State Service)。

              3、SqlServer:将Session存到SqlServer中。

              4、Cookieless:设置客户端Session存储的方式。

         用了这些方法之后,有的是该丢还丢,有的是稳定了速度却慢了。

         大家也注意到了,还有个这个Custom自定义模式,有人会说:“除了大牛,有几个敢写的啊,写出来有问题怎么办,算了算了。” 等等,大家不要还停留在非开源模式下解决问题的思想,找找开源项目,一定能找到的,有人说ASP.NET上哪里找开源啊,非常简单NuGet,如果想了解开源,一定要学会使用NuGet。

    二、Redis


    1、前言  

         上文说了那么多,有人一定会说我是来解决Session丢失的,上哪里来的Session分布式共享,标题党,我还是继续用我的cookie吧。

         我要说的是,几年前,在Stack Overflow上找到了这个方法解决了丢失问题,之后,发现这种方法还可以实现Session分布式共享。那就是运用Custom自定义模式,将Session持久化到Memcache和Redis中。Session丢失、以及持久化到SqlServer数据的性能问题也随之解决。

         此种方法很适合老项目中大量应用Session而导致法搞成分布式而苦恼的.NET开发人员使用。因为很有可能老项目维护过程中,身边的JAVA团队、PHP团队,正在重构你的项目。

    2、RedisSessionProvider

         正文开始,首先,沿着我们的思路Session持久化到Memcache或者Redis中,通过nuget下载 RedisSessionProvider(别问我怎么找到的,因为我英文过了四级,我会使用度娘,嘿嘿)

    image

    【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到最新。

    imageimage

    3、Redis安装

    3-1、Redis for windows下载

         如果会配置Redis的同学,请略过此章节,直接进入Nginx。

         Redis下载:https://github.com/MSOpenTech/redis

    image

    !此处为坑,请注意!

         修改Redis.windows.conf,如果不修改,远程不能访问Redis

         1、将bind 127.0.0.1 改成了bind 0.0.0.0。注意:进入生产环境时候,要启用密码,否则会是Redis漏洞,具体请自行度娘和自己公司的运维阿牛

         2protected-mode yes 改成 protected-mode no

         详细修改的传送门: redis开启远程访问

    3-2、启动Redis

    redis-server redis.windows.conf

    image     上图为redis启动成功,默认6379,可以通过redis-cli进行测试,看别的机子能否访问。还可以在找个redis可视化工具看看里面存了啥,也可以监控Session是否持久化到Redis中了。

    3-3、验证Session是否持久化到Redis

         运行RedisSessionProvider这个项目。同一个IIS下,同域名,不同IP,同一浏览器,不同端口一个是2459,一个是2490。

         1[6]

    注意

         不同浏览器SessionId是不同的。必须保证SessionId,测试必须是同一个浏览器进程分出的不同子标签才可以,这样SessionId是共享的。

    image

         感觉成功了,让我们看看这样的拓扑图:

    image

         囧……这是啥玩意?我的分布式呢?这个拓扑图很显然不是分布式啊,还两个IP,我还要在前面做个路由登录页面?这时Nginx该登场了。

    三、Ngnix 


    1、Ngnix安装&下载

          下载地址:http://nginx.org/

    2、nginx.conf配置修改

    image

    2-1、【接口修改】

           listen   80; 改成  listen   1100; 因为一般都被80都被使用。

    image

    2-2、【增加负载均衡】

    upstream  Jq_one {  
    
         server 127.0.0.1:8770;
         server 192.168.8.138:7777;
    } 
    server {
    .....
    }

    image

    2-3、【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-4、【Nginx启动命令】

            C:server ginx-1.0.2>start nginx

            或

            C:server ginx-1.0.2>nginx.exe

    2-5、【Nginx重新载入命令】

            C:server ginx-1.0.2>nginx.exe -s reload

    2-6、【参考文章】

             详细配置传送门:nginx+iis实现负载均衡

    四、Session分布式共享

    1、拓扑图

    image

             通过Nginx+Redis实现对Session的分布式共享功能。通过测试,发现Session分布式共享共有两种解决方案。

    2、利用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上面。

    2

    3、利用MachineKey进行Session分布式共享

         Ip_Hash在一定程度上解决了Session分布式共享的问题,但是总感觉没有发挥出nginx均衡负载的功能,继续改造

    3-1、现将Ip_Hash去掉

        去掉Ip_Hash重启Nginx,打开网站,点击设置Session按钮,结果报错

    image

    3-2、web.config添加MachineKey

    <machineKey
       validationKey="86B6275BA31D3D713E41388692FCA68F7D20269411345AA1C17A7386DACC9C46E7CE5F97F556F3CF0A07159659E2706B77731779D2DA4B53BC47BFFD4FD48A54"
       decryptionKey="9421E53E196BB56DB11B9C25197A2AD470638EFBC604AC74CD29DBBCF79D6046"
       validation="SHA1"
       decryption="AES"
    />

    【注意

         负载均衡的两个网站的MachineKey必须一样,否则出问题。

    3-3、演示

         下图,大家可以看到,服务器的Ip在不断变化,而Session却没有丢失,至此实现了Session分布式共享。3[8]

    、参考文章

            redis开启远程访问

            nginx+iis实现负载均衡

             ASP.NET性能优化之分布式Session

            .Net分布式架构(一):Nginx实现负载均衡

            .Net分布式架构(二):基于Redis的Session共享

    非常感谢上述文章,对本文的启发,谢谢。

  • 相关阅读:
    ASP.NET 表单验证 Part.1(理解表单验证)
    Silverlight 简介 Part.3(设计 Siverlight 页面)
    ASP.NET 成员资格 Part.3(LoginStatus、LoginView、PasswordRecovery)
    ASP.NET 网站部署 Part.1(安装IIS、复制文件部署网站)
    ASP.NET Dynamic Data Part.1(创建动态数据应用程序)
    ASP.NET 安全模型 Part.2(SSL)
    ASP.NET MVC Part.2(扩展基本的 MVC 应用程序)
    ASP.NET 网站部署 Part.2(使用 Web 部署)
    开发高级 Web 部件
    创建 Web 部件(WebPart 类、简单的 Web 部件)
  • 原文地址:https://www.cnblogs.com/newP/p/6518918.html
Copyright © 2011-2022 走看看