宝哥软件园

浅谈分布式会话在ASP.NET核心中间件的实现

编辑:宝哥软件园 来源:互联网 时间:2021-09-03

1.1.中间件原理

1.1.1.什么是中间件

中间件是用于处理请求和响应的一段代码。通常,多个中间件链接在一起形成一个管道,每个中间件决定是否调用下一个中间件。

1.1.2.中间件执行过程

举个例子演示中间件的执行过程(中间件有三种:日志记录、授权验证和路由):当一个请求进入应用时,执行日志记录的中间件记录请求属性,调用链中下一个中间件的授权验证;如果授权验证通过,控制权传递给下一个中间件;如果失败,则设置401 HTTP代码并返回响应,并将响应传递给日志中间件进行返回。

1.1.3.中间件的配置

中间件配置主要使用Run、Map和use方法进行配置;简单的中间件可以通过匿名方法直接完成,如下所示:

app。Run(async (context,next)={ wait context。response . WriteAsync(' env ' env);等待下一个();});如果你想重用中间件,你需要把它打包成一个类来调用。

1.2.依赖注入中间件

在实际项目中,中间件经常需要调用其他对象的方法。因此,要创建对象之间的依赖关系,由于ASP.NET Core内置的依赖注入系统,在编写程序时可以创建更优雅的代码。

第一步是在IOC容器中注册类,即在Startup类中注册ConfigureServices方法,该方法将在Configure方法之前执行。这样在使用中间件的时候所有的依赖都准备好了。

现在有一个迎宾类:

public class Greeter : IGreeter { public string Greeter(){ return ' Hello from Greeter!';} }公共接口IGreeter { string Greet();}第一步是注册ConfigureServices方法

public void ConfigureServices(IServiceCollection services){ services。AddTransientIGreeter,Greeter();}作者使用AddTransient进行注册,每次请求时都会创建这个类的新实例。您可以选择其他方法:添加单例、添加范围或简单添加(都在幕后使用)。整个DI系统在官方文件中有描述。

注册依赖项后,您可以使用它们。IApplicationBuilder实例允许Configure方法中的RequestServices属性获取迎宾器实例。由于这个IGreeter接口已经注册,所以不需要将中间件与具体的Greeter实现相结合。

app。使用(async (ctx,next)={ IGreeter greeter=ctx。request services . GetServiceIGreeter();等待ctx。响应。WriteAsync(迎宾器。问候());等待下一个();});如果迎宾器类具有参数化构造函数,则其依赖项也必须向ConfigureServices注册。

中间件可以轻松解决依赖关系。您可以向中间件构造函数添加其他参数:

公共类MyMiddleware { private readonly request delegate _ next;private readonly IGreeter _ greeter;public MyMiddleware(request delegate next,IGreeter greeter){ _ next=next;问候者=问候者;}公共异步任务调用(HttpContext上下文){ await上下文。Response.WriteAsync(_greeter。问候());wait _next(上下文);}}或者,您可以将此依赖项添加到Invoke方法中:

公共异步任务调用(HttpContext上下文,IGreeter迎宾器){ await上下文。响应。WriteAsync(迎宾器。问候());wait _next(上下文);}如果DI系统知道这些参数的类型,它们将在类实例化时自动解析。很简单!

1.3.Cookies和会话中间件

1.3.1.会议

HTTP是一种无状态协议,Web服务器将每个请求视为一个独立的请求。并且用户在先前请求中的值不会被保存。

会话状态是ASP.NET芯提供的功能,当用户通过应用程序访问网络服务器时,可以保存和存储用户数据。它由服务器上的字典和哈希表组成。会话状态从浏览器的请求中获得,会话数据保存在缓存中。

ASP.NET核心通过包含会话标识的Cookie来维护会话状态,每个请求都携带这个会话标识。

微软提供的中间件。会话包用于管理会话状态。要启用会话中间件,启动类需要执行以下操作:

使用任何实现IDistributedCache接口的服务来启用内存缓存并设置AddSession回调。因为AddSession是在微软实现的。会话包,必须添加微软。会话包使用会话回调来获取。具体的示例代码如下:

使用微软。AspNetCore . Builder使用微软。扩展。依赖注射;使用系统;公共类Startup { public void ConfigureServices(IServiceCollection services){ services }。AddMvc();//添加一个内存缓存服务. adddistributedmemory cache();服务。addSession(options={//将会话设置为10秒后过期,以测试选项。idletimeout=timespan。从秒(10);选项。Cookie . HttpOnly=true});} public void Configure(IApplicationBuilder应用程序){ app。UseSession();app。usemvcwithddefaultroute();}}上面代码中的IdleTimeout属性用于确定当用户不操作时,Session被丢弃的时间。该属性与Cookie超时无关,通过Session中间件的每个请求都会重置超时。

1.3.2.会话保存在Redis中

实现分布式会话方法的官方方式有Redis、Sql Server等。但是在这种按键/值取值的方式下,Sql Server的效率远不如Redis,所以我选择Redis作为例子来实现分布式Session。

准备Redis

由于目前Redis不支持windows,所以大家在安装Redis的时候都要准备一个linux操作系统。这里的系统是ubuntu 16.04;有关下载和安装方法,请参考官方示例。

成功安装后,启动Redis服务。如果看到以下信息,说明Redis启动成功:

相关配置

首先,你需要安装微软。extensions . cache . redis搭配Nuget,安装成功后可以在app.csproj文件中看到。

在Configure方法中添加app . usesession();然后配置服务以添加Redis服务

public void ConfigureServices(IServiceCollection services){ services。adddistributedediscache(options={ options。配置=' 127 . 0 . 0 . 1 ';//多个redis服务器:{ redip } : { Redis端口},{ redip } : { Redis端口} options . instance name=' sample instance ';});服务。AddMvc();服务。addSession();}上述代码中,作者只使用了一台Redis服务器进行测试,实际项目中需要多台Redis服务器;配置方法:选项。配置='地址1:端口,地址2:端口';这里,作者没有给出端口,而是使用了默认端口6379

完全码

Startup.cs

使用系统收藏。通用:使用系统Linq .(消歧义):使用系统。线程。任务:使用微软.aspnetcore。建设者使用微软.aspnetcore。主机;使用微软.扩展名。配置:使用微软.扩展名。依赖项:使用微软.扩展。缓存。Redis:使用微软.扩展。缓存。分布式(扩展。缓存。分布式):app {公共类启动(图标配置)命名空间{配置=配置}公共图标配置{ get } public void configure services(iseries集合服务){ 0服务adddistributedrediscache(选项={选项)。组态=' 127 .0 .0 .1 ';选项包括:instance name=' sample instance });服务部门添加MVC();服务部门添加会话();} public void configure(iaapplicationbuilder应用程序,ihostingvironnenv){ if(env).IsDevelopment()) { app .usedeveloper exception page } else {应用程序。使用异常处理程序("/home/error ");}应用程序.usesession();app(应用程序)。usestattcfiles();app(应用程序)。UseMvc(道路={道路)。地图路线(名称3360 '默认',模板3330“{控制器=主页}/{操作=索引}/{ id?});});} } homecontroler。铯

公共类homecontroller :控制器{ public iactionresult index(){ http context }公用类别家庭控制器3330控制器.会话。Set('apptest ',编码).utf8。get bytes(' apptestalue ');return View():} public iactionresult show Friday(){ byte[]temp;if(HttpContext).会话。TryGetValue('apptest,out temp)){ view data[' redis ']=编码.UTF8。GetString(临时):}返回视图();} }索引范思哲?范思哲会话数阿云“apptestvalue”,星期五希萝会话数魏冄。

周五秀。cshtml网站

Redis会话值:视图数据['Redis']朱庇特先生

不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,星期五的表演希仪,会话1740年

-什么区段会话值-阶段作业值云娥,云娥唔星期五的表演希仪,会话朱塞佩范塞佩

阿叔apptestvalue(应用程序测试)云娥会话数云娥唔再说一遍朱代,绿筠小姐apptestvalue(应用程序测试)朱庇特先生再说一遍朱庇特阿吉卜阿吉卜阿吉卜阿吉卜阿吉卜阿吉卜阿吉卜阿吉卜阿吉卜阿吉卜阿吉卜阿吉卜阿吉卜阿吉卜阿吉卜赛?范思哲范思哲范思哲。

1.3.3 .是吴亚玲会话数

嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨嗨会话数孙悟空啊再说一遍何曰,朱庇特朱庇特朱庇特朱庇特阿齐兹阿齐兹阿齐兹阿齐兹阿齐兹阿齐兹阿齐兹阿齐兹阿齐兹阿齐兹阿齐兹阿齐兹阿齐兹阿齐兹阿齐兹阿齐兹阿齐兹阿齐兹阿齐兹阿齐兹阿齐兹再说一遍朱庇特范思哲范思哲;拜占庭的儿子是拜占庭的儿子(阿力伯阿力伯阿力伯阿力伯)董建安(音同"老"音同"老"音同"老"音同"老"音同"老"音同"老"音同"老"音同"老"音同"老"音同"老"会话,云娥会话,朱庇特先生,你好吗?朱庇特先生,你好吗,朱塞佩朱塞佩朱塞佩朱塞佩,老景http(http)不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不饼干!饼干魏冄。

你是说,我是说,我是说,我是说,我是说,我是说,我是说,我是说,我是说,我是说,我是说,我是说,我是说,我是说,我是说,我是说,我是说,我是说,我是说,我是说.ASP?ASP?ASP?净核心云娥?云娥?云娥,拜占庭的人是拜占庭的人,是拜占庭的人,是拜占庭的人,是拜占庭的人,是拜占庭的人,是拜占庭的人,是拜占庭的人,是拜占庭的人,是拜占庭的人,是拜占庭的人,是拜占庭的人,是拜占庭的人,是拜占庭的人,是拜占庭的人会话数唉哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟;范登韦恩佐范登韦恩佐,净核心喂!喂微软公司aspnetcore。数据保护。azrestorage你好微软公司aspnetcore。数据保护。redis唔唔唔唔唔唔唔唔唔唔蓝色的阿力再说一遍何曰。贺盛德鲁滨逊鲁滨逊阿吉阿吉阿吉阿吉阿吉阿吉阿吉阿吉阿吉阿吉阿吉阿吉阿吉阿吉阿吉阿吉阿吉阿吉阿吉阿吉阿吉阿吉再说一遍。

哎哎哎微软公司aspnetcore。数据保护。redis哎哎哎哎persistkeystoredis(持久性存储库)贾克琳贾克琳贾克琳贾克琳再说一遍朱庇翁(伊朗伊斯兰共和国)。拜占庭的儿子配置服务-你好-你好AddDataProtection()

var redis=连接多路复用器连接(' 127。0 .0 .1:6379 ');服务部门添加数据保护().setapplicationname(' session _ application _ name ').persitkeystoredis(redis,“数据保护密钥”);韩大夫,韩大夫会话数

苏慕白曰

唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔,哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟app1你好app2

王振(电影)微软公司aspnetcore。数据保护。redis你好StackExchange(堆栈交换)。新建路线名字你好

吴登盛?吴登盛,ASP .NET核心(网络核心)朱庇特朱庇特朱庇特5000美元,僧儿app1贺盛瑞,拜占庭app2啁啾啾唻唻唻唻唻唻唻唻唻唻唻5001

是杨俊钦

app1项目

Startup.cs

使用系统。集合。通用;使用系统Linq .使用系统。线程化。任务;使用微软AspNetCore。建设者使用微软。托管;使用微软。扩展。配置;使用微软。扩展。依赖注射;使用微软。扩展。缓存redis使用微软。扩展。缓存。分布式;命名空间app1{公共类启动{公共启动(图标配置)配置){配置=配置}公共图标配置{ get } public void ConfigureServices(IServiceCollection services){ var redis=连接多路复用器.连接(' 127。0 .0 .1:6379 ');服务添加数据保护().SetApplicationName(' session _ application _ name ').PersistKeysToRedis(redis,)数据保护-密钥');服务adddistributedediscache(options={ options .配置=' 127 .0 .0 .1 ';选项instance name=' SampleInstance });服务addMVc();服务addSession();}公共void Configure(IApplicationBuilder应用程序,ihostingenvirmentenv){ if(env .IsDevelopment()) { app .usedeveloper异常页();} else { app .UseExceptionHandler('/Home/Error ');}应用程序.UseSession();应用程序.UseStaticFiles();应用程序.UseMvc(routes={ routes .MapRoute(名称: '默认',模板: ' {控制器=Home }/{操作=Index }/{ id?}');});} }}HomeControler.cs

公共类HomeController :控制器{公共IActionResult Index(){ HttpContext .会话。设置(' app1test ',编码. UTF8。GetBytes(' app1testvalue ');返回视图();} public IActionResult ShowRedis(){ byte[]temp;if(HttpContext .会话。TryGetValue('app1test,out temp)){查看数据[' Redis ']=编码. UTF8。getStrIng(temp);}返回视图();}}ShowRedis.cshtml

Redis会话值:视图数据[' Redis ']应用2项目

Startup.cs配置同app1配置一样。

家庭控制器。铯

公共类HomeController :控制器{ public IActionResult Index(){ byte[]temp;if(HttpContext .会话。TryGetValue('app1test,out temp)){查看数据[' Redis ']=编码. UTF8。getStrIng(temp);}返回视图();}}Index.cshtml

视图数据['Redis']运行效果

app1项目

首次打开进入ShowRedis页面,会话值为空

点击SetSessionValue以后,再回到ShowRedis页面:

app2项目,直接在浏览器访问:http://localhost:5001

以上是用Redis实现分布式会议示例。

1.4.总结

本节讲解了中间件的运行原理及配置过程,中间件之间对象依赖关系的配置和平时项目中常用到会议的配置问题。并在实际代码展示了怎样使用中间件实现分布式会议。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

更多资讯
游戏推荐
更多+