.Net Core中,管道往往伴随着请求一起出现。客户端发起Http请求,服务端去响应这个请求,之间的过程都在管道内进行。

举一个生活中比较常见的例子:旅游景区

我们都知道,有些景区大门离景区很远,我们需要经过层层关卡才能到达景区。

我的请求最终就是去到景区,去到景区的整个过程就是管道,景区就是服务器,层层关卡就是一个个中间件了,比如:门票停车费摆渡费等等。

如果其中任何一个中间件卡壳了,比如我没买门票,那别人肯定是不让我进去,这就是管道短路了。


.NET Core 请求管道包含一系列Http请求委托(RequestDelegate),依次调用。

微软给的图示:

.Net Core服务

在解释管道的使用方法之前,我们先来准备一个.Net Core服务。

创建一个.Net Core控制台应用程序,并实现如下代码,一个简单的使用 Kestrel 托管的服务就完成了:

internal class Program
{
static void Main(string[] args)
{
new WebHostBuilder()
.UseKestrel()
.UseStartup<Startup2>()
.Build()
.Start(); Console.ReadLine();
}
}
public class Startup
{
public void Configure(IApplicationBuilder app)
{
}
}

这也是.Net Core的优点之一,只选择我们需要的,摒弃那些多余的功能。优点是优点,一般开发中也犯不上这样去做。

Kestrel 托管默认监听端口:5000

管道中间件

微软这边内置了三个扩展函数供我们构建自己的中间件:

  1. Use
  2. Map
  3. Run

其中UseMap函数还提供了对应的分支扩展:UseWhenMapWhenUseMiddleware。下面我们一个个来解释。

app.Use

Use 是最常用的一种模式,承接上一个请求并执行下一个请求的任务

public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
Console.WriteLine("middleware1");
await next.Invoke();
});
app.Use(async (context, next) =>
{
Console.WriteLine("middleware2");
});
}

app.UseWhen

UseWhenUse的基础上提供了条件分支的功能

app.UseWhen(context =>
// 判断请求路径的开头是否是/h
context.Request.Path.StartsWithSegments(new PathString("/h")),
c => c.Use(async (context, next) =>
{
Console.WriteLine("middleware1");
await next.Invoke();
})
);
app.Use(async (context, next) =>
{
Console.WriteLine("middleware2");
});

app.Map

Map我们可以理解成专为请求路径扩展的分支中间件,可以根据请求路径去处理对应分支逻辑,与上面的UseWhen例子效果类似,但更加方便。

app.Map("/h", _app =>
{
_app.Use(async (context, next) =>
{
Console.WriteLine("hello world");
});
});

app.MapWhen

MapWhenUseWhen类似,都是在请求上下文的基础上去扩展分支,比Map更加灵活。

app.MapWhen(context => { return context.Request.Query["name"] == "tony"; }, _app => {
_app.Use(async (context, next) => {
context.Response.ContentType = "text/plain; charset=utf-8";
await context.Response.WriteAsync("i 服了 you");
});
});

app.Run

Run一般用于断路或请求管道的末尾,不会将请求传递下去

app.Run(async context =>
{
await context.Response.WriteAsync("hello world");
});

UseMiddleware

将一个完整的类添加到管道中间件,也就是将上面的请求委托,用类以及函数的形式替代了,便于我们的代码管理。

app.UseMiddleware<DotnetboyMiddleware>();

public class DotnetboyMiddleware
{
private readonly RequestDelegate _next;
private readonly string _name;
public DotnetboyMiddleware(RequestDelegate next, string name)
{
_next = next;
_name = name;
}
public Task Invoke(HttpContext context)
{
context.Response.WriteAsync($"my name is {_name}").Wait();
return this._next(context);
}
}

微软内置的一些管道中间件扩展函数就介绍完了,下面我们实现一下微软实例图示中的效果:

public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
Console.WriteLine("middleware1 : in");
await next.Invoke();
Console.WriteLine("middleware1 : out");
});
app.Use(async (context, next) =>
{
Console.WriteLine("middleware2 : in");
await next.Invoke();
Console.WriteLine("middleware2 : out");
});
app.Run(async context =>
{
Console.WriteLine("Hello World");
await context.Response.WriteAsync("Hello World");
});
}

从上面的例子中我们可以看到,中间件都是由上而下依次执行,由每个中间件决定是否继续执行下一个中间件,最终到响应结果。

如果哪个中间件决定不往下执行,那通道也就短路了,比如我们去掉 middleware2await next.Invoke();

执行到 Console.WriteLine("middleware2 : out"); 就短路了,此路不通,原路返回。

因为管道中间件执行逻辑的关系,我们在实际开发中要注意两点:

  • 1、谨慎使用管道短路

  • 2、注意中间件的使用顺序,比如:路由中间件肯定是要在认证中间件前面执行,有中间件需要访问文件,在此之前就必须先执行开放静态文件的中间件

.NET Core基础篇之:白话管道中间件的更多相关文章

  1. Asp.Net Core基础篇之:白话管道中间件

    在Asp.Net Core中,管道往往伴随着请求一起出现.客户端发起Http请求,服务端去响应这个请求,之间的过程都在管道内进行. 举一个生活中比较常见的例子:旅游景区. 我们都知道,有些景区大门离景 ...

  2. Core 1.0中的管道-中间件模式

    ASP.NET Core 1.0中的管道-中间件模式 SP.NET Core 1.0借鉴了Katana项目的管道设计(Pipeline).日志记录.用户认证.MVC等模块都以中间件(Middlewar ...

  3. ASP.NET Core 1.0中的管道-中间件模式

    ASP.NET Core 1.0借鉴了Katana项目的管道设计(Pipeline).日志记录.用户认证.MVC等模块都以中间件(Middleware)的方式注册在管道中.显而易见这样的设计非常松耦合 ...

  4. .NET Core基础篇之:配置文件读取

    配置文件是每个项目最基础的部分,也是不可或缺的部分,比如:数据库连接.中间件属性等常见的配置. 今天这篇文章主要内容就是,在.Net Core项目中怎样去读取配置文件并使用. 提前准备 appsett ...

  5. .NET Core基础篇之:依赖注入DependencyInjection

    依赖注入已经不是什么新鲜话题了,在.NET Framework时期就已经出现了各种依赖注入框架,比如:autofac.unity等.只是在.net core微软将它搬上了台面,不用再依赖第三方组件(那 ...

  6. .NET Core基础篇之:集成Swagger文档与自定义Swagger UI

    Swagger大家都不陌生,Swagger (OpenAPI) 是一个与编程语言无关的接口规范,用于描述项目中的 REST API.它的出现主要是节约了开发人员编写接口文档的时间,可以根据项目中的注释 ...

  7. ASP.NET Core 基础知识(四) Startup.cs类

    ASP.NET Core应用程序需要一个启动类,按照约定命名为Startup.在 Program 类的主机生成器上调用 Build 时,将生成应用的主机, 通常通过在主机生成器上调用 WebHostB ...

  8. 你所不知道的库存超限做法 服务器一般达到多少qps比较好[转] JAVA格物致知基础篇:你所不知道的返回码 深入了解EntityFramework Core 2.1延迟加载(Lazy Loading) EntityFramework 6.x和EntityFramework Core关系映射中导航属性必须是public? 藏在正则表达式里的陷阱 两道面试题,带你解析Java类加载机制

    你所不知道的库存超限做法 在互联网企业中,限购的做法,多种多样,有的别出心裁,有的因循守旧,但是种种做法皆想达到的目的,无外乎几种,商品卖的完,系统抗的住,库存不超限.虽然短短数语,却有着说不完,道不 ...

  9. ASP.NET Core 中间件 - ASP.NET Core 基础教程 - 简单教程,简单编程

    原文:ASP.NET Core 中间件 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 中间件 上一章节中,我们我们有讲到 Startup 类中的 Confi ...

随机推荐

  1. pycharm的selenium设置

    如果运行文件,提示 no model named selenium 那就需要添加selenium的安装地址 如上图 在python>lib>site-packages 在pycharm的f ...

  2. NOI2020 同步赛划水记

    因为太菜了没去现场参加 NOI 就算去了估计也只能混个Fe(雾) "两天都会各有一道签到题,争取拿到70分.剩下的题每道题打30分暴力.每天130分,就能稳拿Ag了."--ls D ...

  3. Linux中gz文件操作遇到的一些技巧和坑

    目录 不解压情况下获取gz超大文件的前/后几行? Perl读入gz文件操作? 不能直接通过wc -l 来统计gz文件的行数 前提是gz文件超大,如上百G,肯定不能直接解压来做. 不解压情况下获取gz超 ...

  4. os.path.join()函数

    连接两个或更多的路径名组件 import os p1 = '/date' p2 = 'mage' p3 = 'img' all = os.path.join(p1,p2,p3) print(all) ...

  5. linux sort 命令详解(转载)

    转载:http://www.cnblogs.com/51linux/archive/2012/05/23/2515299.html#3374576 sort是在Linux里非常常用的一个命令,管排序的 ...

  6. Selenium的安装和使用

    一.Selenium的安装,Selenium是一个自动化测试工具,利用它我们可以驱动浏览器执行特定的动作,如点击.下拉等操作.对于一些JavaScript渲染的页面来说,这种抓取方式非常有效.1.pi ...

  7. c#表中信息点击跳转

    OnRowCommand="gridInfoData_RowCommand" <Columns> <asp:ButtonField HeaderText=&quo ...

  8. 中小型企业SaaS行业将崛起于新十年

    2020开始的新十年,国内中小型企业SaaS市场将迎来蓬勃生机,四大助推器已经就绪 第一,云服务打好底座: 随着阿里云.腾讯云乃至华为云的蓬勃发展,基础设施的不断完善,为中小型Saas企业的发展,提供 ...

  9. python 多态、组合、反射

    目录 多态.多态性 多态 多态性 鸭子类型 父类限制子类的行为 组合 面向对象的内置函数 反射 多态.多态性 多态 多态通俗理解起来,就像迪迦奥特曼有三种形态一样,怎么变还是迪迦奥特曼 定义:多态指的 ...

  10. Ubuntu Linux安装QT5之旅

    1. QT 版本选择 如何选择QT版本,参考如下介绍 https://www.cnblogs.com/chinasoft/p/15226293.html 2.  在此以5.15.0解说 下载QT 版本 ...