前言
近来系统从 net framework472 升级到 net8,因为是分布式部署,而且以前代码大量运用了会话,所以要弄分部署会话。
网上找资料发现没有太多深入一点的,所以整理一下记录。
ASP.NET Core 中的会话 | Microsoft Learn
原理说明
关键概念
cookie、持久化、数据保护、
关键概念介绍
- cookie:用于存储加密后的 SessionKey
- 持久化:用于 session 的内容存储到进程内存还是别的什么地方,
可以用默认实现 调用 IDistributedCache 的实现来存储,
也可以自定义 ISession、ISessionStore 来实现存储。 - 数据保护:cookie 加解密处理器
源码分析、原理介绍
- 总体流程
当用户访问网站发起请求到服务端的时候,请求首先会经过 SessionMiddleware 中间件,
该中间件会先尝试读取 cookie,并用 IDataProtector 的实现来解密得到 SessionKey,
期间如果 cookie 为空或者解密失败拿不到 SessionKey,会随机生成 SessionKey,
接下来通过 ISessionStore 的实现来 Create 一个 ISession 的实现,并把 SessionKey 传递给 ISession,
后续该请求内的所有 Session 相关的操作,都是通过这个 ISession 来操作的。
- 数据存储
ISession 的默认存储方式,就是调用 IDistributedCache 的实现来存储的,具体实现看具体配置,默认就是进程内存。
- ISession 接口
这个接口最主要的 LoadAsync、CommitAsync、TryGet、Set、Remove、Clear
其中,CommitAsync 方法是个请求离开时自动执行的。
另外,这里只有 Load 和 Commit 是异步的,
所以默认实现是 Load 的时候把 Session 信息全加载出来,
然后中间同步的 Get、Set、Remove、Clear 操作都是在内存里运行记录,
最后再通过 Commit 方法一次持久化。
他们会把所有session数据塞到统一个Redis-Key里面。
但是我们旧的代码给 Session 存了大的对象,每个请求都要存取Redis并且序列化,比较消耗资源,
所以我们自己重新实现了 ISession 和 ISessionStore,每个Session的Key对应一个Redis Hash Field,
并且要用才读单个field,要用才写单个field,节省资源。
一般不要搞大对象session,就不需要重写也可以了。
注意事项
如果你已经看完原理了。
- cookie 跨域
我们多个子域名要跨域共享 Session 信息,就要在服务启动类配置一下支持 cookie 的跨域访问,否则这个 SessionKey 就不一致了。 - 数据加解密
SessionKey 是一定要进行加解密算法的,如果你是分布式,你应该要注意这一点并且配置好。
ASP.NET Core 中的密钥存储提供程序 | Microsoft Learn
发表回复