ASP.NET Core 管道和中间件(pipeline) - zLulus/My_Note GitHub Wiki
管道和中间件
.net core 管道是请求抵达服务器到响应结果返回的中间的一系列的处理过程
。
在ASP.NET Core中,针对HTTP请求采用pipeline也就是通常说的管道方式来处理,而管道容器内可以挂载很多中间件
(处理逻辑)“串联”
来处理HTTP请求,每一个中间件都有权决定是否需要执行下一个中间件,或者直接做出响应。
这样的机制使得HTTP请求能够很好的被层层处理和控制
,并且层次清晰处理起来甚是方便。
为了再次说明管道和中间件的概念,举一个官方给出的权限验证的例子,中间件A,B分别按顺序挂载在管道容器中,A为权限验证中间件,只有通过A的权限验证才能执行B,如果没有通过A的验证,A有权中断管道处理直接返回相应的错误提示例如401等。这样必须由上一节点来调用的串行递归执行方式就是pipeline,而每一个节点就是中间件或者叫中间组件。
内置中间件
.net core 给我们内置了很多中间件:
自定义中间件
用Use
将多个请求委托链接在一起。 next 参数表示管道中的下一个委托。 可通过不调用 next 参数使管道短路
。 通常可在下一个委托前后执行操作。
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
// Do work that doesn't write to the Response.
await next.Invoke();
// Do logging or other work that doesn't write to the Response.
});
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from 2nd delegate.");
});
}
}
当委托不将请求传递给下一个委托时,它被称为“让请求管道短路” 。 通常需要短路,因为这样可以避免不必要的工作。 例如,静态文件中间件可以处理对静态文件的请求,并让管道的其余部分短路,从而起到终端中间件 的作用。 如果中间件添加到管道中,且位于终止进一步处理的中间件前,它们仍处理 next.Invoke 语句后面的代码。
Run 委托
不会收到 next 参数。 第一个 Run 委托始终为终端,用于终止管道。
Run 是一种约定。
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
// Do work that doesn't write to the Response.
await next.Invoke();
// Do logging or other work that doesn't write to the Response.
});
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from 2nd delegate.");
});
}
}
在前面的示例中,Run 委托将 "Hello from 2nd delegate." 写入响应,然后终止管道。 如果在 Run 委托之后添加了另一个 Use 或 Run 委托,则不会调用该委托。
中间件执行顺序
按照Startup.cs
的Configure方法添加中间件组件的顺序定义了针对请求调用这些组件的顺序,以及响应的相反顺序
。 此顺序对于安全性、性能和功能至关重要。
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// Middleware A
app.Use(async (context, next) =>
{
Console.WriteLine("A (before)");
await next();
Console.WriteLine("A (after)");
});
// Middleware B
app.Use(async (context, next) =>
{
Console.WriteLine("B (before)");
await next();
Console.WriteLine("B (after)");
});
// Middleware C (terminal)
app.Run(async context =>
{
Console.WriteLine("C");
await context.Response.WriteAsync("Hello world");
});
}
执行情况如下:
实现:记录方法的执行时间等信息
.net core有实现好的方法.NET Core 和 ASP.NET Core 中的日志记录
原理:
1.自定义计时中间件,在进入管道时(next()方法之前)开始计时,在离开管道时(next()之后)停止计时
2.自定义豁免Attribute,以AOP的方式,豁免不需要计时中间件的方法
豁免Attribute的实现,是在管道计时中间件里面,查询当前方法的Attribute列表中是否存在豁免Attribute,如果是,则不进行计时操作
示例代码
参考资料
官方资料
ASP.NET Core - 中间件与管道(1)
.net core 中间件管道底层剖析
ASP.NET Core中的中间件