zoukankan      html  css  js  c++  java
  • asp.net core系列 43 Web应用 Session分布式存储(in memory与Redis)

    一.概述

      HTTP 是无状态的协议。 默认情况下,HTTP 请求是不保留用户值或应用状态的独立消息。 本文介绍了几种保留请求间用户数据和应用状态的方法。下面以表格形式列出这些存储方式,本篇专讲Session会话状态,计划下篇再讲应用状态。

    存储方法

    存储机制

    Cookie HTTP Cookie(可能包括使用服务器端应用代码存储的数据)
    Session 状态 HTTP Cookie 和服务器端应用代码
    TempData HTTP Cookie 或Session状态
     查询字符串 HTTP 查询字符串
    隐藏字段 HTTP 窗体字段
    HttpContext.Items 服务器端应用代码
    Cache 服务器端应用代码

    依赖关系注入

    服务器端应用代码

      1.1 Cookie

        Cookie是服务器产生ID的标签。是识别用户,实现持久会话的最好方式。Cookie分为两类:会话Cookie和持久Cookie。二者唯一区别是设置过期时间。

        (1)会话Cookie是临时的,当用户退出浏览器时,就会被删除。

        (2)持久Cookie生存时间更长,存储在硬盘上,当浏览器退出或计算机重启时它们仍然存在。

        Cookie跨请求存储数据,每次请求都会发送Cookie。Cookie的大小应该保持在最低限度。理想情况下,仅标识符存储在 Cookie 中。大多数浏览器 Cookie 大小限制为 4096 个字节。每个域仅有有限数量的 Cookie 可用,比如IE6.0每个域cookie个数最多为20个。

        下面看Cookie是如何工作的:

        (a) 客户端首次Request请求Web站点时,Web服务器对客户端一无所知。

        (b) Web服务器通过Response报文的 Set-Cookie或Set-Cookie2产生标识Cookie id=”34294”,返回给客户端,客户端浏览器会存储该Cookie。

        (c) 当客户端再次Request请求时,带上Cookie,Web服务器就能识别该客户端,实现会话。

      1.2 Session (会话)介绍

        Session数据由缓存支持并被视为临时数据Session状态是用户浏览Web应用程序时,存储用户数据的ASP.NET Core方案。Session状态使用应用维护的存储,来保存客户端所有请求的数据ASP.NET Core通过向客户端提供包含Session ID的cookie来维护Session状态,该Session ID随每个请求一起发送到应用程序(Web服务器)。该应用程序使用Session ID来获取Session数据(Session数据存储在Web服务器上)Session会话状态以下主要行为:

             (1) 由于cookie Session是特定于浏览器的,因此不能跨浏览器共享会话。

        (2) 应用在上次请求后保留Session的时间有限。 应用程序可以设置Session超时,或者使用 20 分钟的默认值。

        (3) 建议不使用粘性会话, 更好的方法是使用Redis或SQL Server分布式缓存,它不需要粘性会话。

      

      1.3  Session会话选项

        若要替代Session默认值,使用 SessionOptions (services.AddSession)。下面是主要选项,以及示例:

    选项 说明
    Cookie 确定用于创建 Cookie 的设置。名称默认为.AspNetCore.Session
    IdleTimeout 空闲多长时间Session重置。 此设置仅适用于Session内容,不适用于 Cookie。 默认为 20 分钟。
    IOTimeout 允许从存储加载会话或者将其提交回存储的最大时长。 此设置可能仅适用于异步操作。 可以使用 InfiniteTimeSpan 禁用超时。 默认值为 1 分钟
         //选项配置
         services.AddSession(options =>
          {
              options.Cookie.Name = ".AdventureWorks.Session";
              options.IdleTimeout = TimeSpan.FromSeconds(10);
          });

       1.4 Session设置和获取值

        在 Microsoft.AspNetCore.Session 包中提供中间件来管理Session状态。 若要启用Session中间件,Startup 必须包含如下:

        (1) 任何IDistributedCache内存缓存。该IDistributedCache实现用作Session的后备存储,下面会讲到分布式缓存在 ASP.NET Core 中。

        (2) 对 ConfigureServices 方法中 AddSession 的调用。

        (3) 对 Configure 中 UseSession(); 的调用。

    二. Session存储 in memory

      在 ASP.NET Core中,分布式缓存无论使用in memory、SQL Server、Redis都需要应用程序使用IDistributedCache接口与缓存进行交互。Session存储在in memory中,称为”分布式内存缓存”(AddDistributedMemoryCache)。是框架提供的IDistributedCache实现。注意:分布式内存缓存不是实际的分布式缓存,该缓存是存储在运行应用程序的服务器上。

       运用场景一般用在开发或测试中。也可以用在生产环境下,但必须是内存消耗不高并且应用程序是单个节点(没有Web分发负载)。

      2.1 Startup文件配置session

    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
               //..
                services.AddDistributedMemoryCache();
                services.AddHttpContextAccessor();
                services.AddSession(options =>
                {
                    //空闲10秒后, session自动清空
                    options.IdleTimeout = TimeSpan.FromSeconds(10);
                    options.Cookie.HttpOnly = true;
                });
                services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        }
    
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
           //..
           //顺序很重要,必须放在UseMvc之前。配置后HttpContext.Session可用
            app.UseSession();
            app.UseMvc();
        }
    }

      2.2 使用属性 HttpContext.Session 从 Razor Pages PageModel 类或 MVC 控制器类访问会话状态。

      public class HomeController : Controller
        {
            private readonly IHttpContextAccessor _accessor;
            public HomeController( IHttpContextAccessor httpContextAccessor)
            {
                this._accessor = httpContextAccessor;
            }
    
            public IActionResult Index()
            {
                HttpContext.Session.SetString("SessionTest", "Ben Rules!");
                return View();
            }
            
            public IActionResult Privacy()
            {
                ViewData["SessionTest"] = _accessor.HttpContext.Session.GetString("SessionTest");
                return View();
            }
        }

         先运行index页设置Session后,再运行Privacy页读取该Session。如下图:Session会话设置和获取值成功,再查看浏览器中的Cookies名称默认为.AspNetCore.Session。

        

      2.3 Session数据序列化

        必须对所有Session数据进行序列化以启用分布式缓存方案,即使是在使用in memory缓存的时候。对于字符串和数据序列化以由ISession 扩展方法实现了。对于复杂类型,添加以下扩展方法以设置和获取可序列化的对象。

    public static class SessionExtensions
    {
        public static void Set<T>(this ISession session, string key, T value)
        {
            session.SetString(key, JsonConvert.SerializeObject(value));
        }
    
        public static T Get<T>(this ISession session, string key)
        {
            var value = session.GetString(key);
    
            return value == null ? default(T) : 
                JsonConvert.DeserializeObject<T>(value);
        }
    }
        //以下示例演示如何使用扩展方法设置和获取可序列化的对象:
        HttpContext.Session.Set<DateTime>(SessionKeyTime, currentTime);

    三.Session存储Redis

      Redis缓存比SQL Server缓存提供更高的吞吐量和更低的延迟。这里不在演示SQL Server存储,如果要用SQL Server存储,建议为分布式缓存提供专用的SQL Server实例(与应用程序的数据库实例分开)。

       3.1 Redis服务器

        关于redis的安装,这里不在介绍。

    #启动redis服务成功
    [root@localhost bin]# ./redis-server redis.conf
    
    #启动redis客户端测试成功
    [root@localhost bin]# ./redis-cli -h 172.168.18.200  -a 123456
    127.0.0.1:6379> set msg "hello"
    OK
    127.0.0.1:6379> get msg
    "hello"

       

      3.2 asp.net core应用端

        (1)演示项目是基于上面的in memory案例,先安装redis中间件。

        PM> Install-Package Microsoft.Extensions.Caching.Redis

        (2)将in memory改为redis存储,代码改动如下:

                //services.AddDistributedMemoryCache();
                services.AddDistributedRedisCache(options =>
                {
                    options.Configuration = "172.168.18.200:6379,allowAdmin=true,password=123456,defaultdatabase=0";
                });
                services.AddHttpContextAccessor();
                services.AddSession(options =>
                {
                    options.IdleTimeout = TimeSpan.FromSeconds(10);
                    options.Cookie.HttpOnly = true;
                });
                services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

        (3)设置和获取Session

          在HomeController类中,设置和获取Session,代码不变,可参考上面2.2。运行index页后,再运行Privacy页,Session会话设置和获取值成功,再使用redis工具查看已存储到了redis服务中(空闲10秒后,redis存储的session将自动清空)如下图所示:

      参考资料

        ASP.NET Core 中的会话和应用状态

        Redis可视化管理

           分布式缓存在 ASP.NET Core 中

        

  • 相关阅读:
    bash 中有效建立锁
    go 语言 Makefile 指定依赖包位置
    在 mysql 中对特定的库禁用 DDL 语句
    go 语言并发机制 goroutine 初探
    Google和facebook如何应用R进行数据挖掘
    数据应用催生商业模式
    4款语音播报来电短信应用[Android]
    让 php 用 nginx 打包 zip
    10个关于 Dropbox 的另类功用(知乎问答精编)[还是转来了]
    分析以数据挖掘技术预测用户流失情况的方法
  • 原文地址:https://www.cnblogs.com/MrHSR/p/10544167.html
Copyright © 2011-2022 走看看