欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

asp.net core系列 43 Web应用 Session分布式存储(in memory与Redis)

程序员文章站 2022-03-18 12:01:08
一.概述 HTTP 是无状态的协议。 默认情况下,HTTP 请求是不保留用户值或应用状态的独立消息。 本文介绍了几种保留请求间用户数据和应用状态的方法。下面以表格形式列出这些存储方式,本篇专讲Session会话状态,计划下篇再讲应用状态。 存储方法 存储机制 依赖关系注入 服务器端应用代码 1.1 ......

一.概述

  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是如何工作的:

asp.net core系列 43 Web应用 Session分布式存储(in memory与Redis)

    (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。

asp.net core系列 43 Web应用 Session分布式存储(in memory与Redis)

    

  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系列 43 Web应用 Session分布式存储(in memory与Redis)

 

  参考资料

    asp.net core 中的会话和应用状态

    redis可视化管理

       分布式缓存在 asp.net core 中