.NET Core中间件的注册和管道的构建(1)---- 注册和构建原理

0x00 问题的产生

管道是.NET Core中非常关键的一个概念,很多重要的组件都以中间件的形式存在,包括权限管理、会话管理、路由等。所以搞明白中间件是如何注册并最终构建成管道的很重要。园子里很多先驱早已经开始了这方面的研究学习,也写了很多文章,不过我看了后有些地方还不是特别明白。毕竟每个人都是不同的,有些内容作者觉得是常识不需要多写的地方对我来说可能就是个盲区。幸好.NET Core整个项目都是开源的,找到源码看了下解决了我心中的困惑。同时写篇博客记录一下,也算一个补充,如果大家看了能有所收获那就更好了。本来是想一片文章写完的,后来发现太长了,所以分了两篇。这是第一篇,主要说一下中间件的注册和管道的构建原理,后面一篇写一下注册中间件类的原理和写中间件类需要注意的约定和特性。

0x01 中间件的注册

管道的构建主要包含中间件注册和把注册的中间件构建成管道。先来说中间件的注册。

什么是中间件。说简单一点中间件就是一个方法,传入一个HttpContext类型参数,返回Task。参数HttpContext中包含了HTTP请求和响应等相关信息,中间件可以读取/修改其中的部分内容,并决定是否让下一个中间件继续处理这个HttpContext。这个方法包装为一个委托RequestDelegate。

为了让中间件有权决定是否让下一个中间件继续处理HttpContext,当前中间件需要下一个中间件的引用。所以在注册中间件的时候需要注册为Func<RequestDelegate,RequestDelegate>的形式,其中传入的参数指的是下一个中间件,返回的是我们注册的中间件,传入的参数在ApplicationBuilder在执行Build()方法构建管道时传入(后面会看到)。所以为了方便理解,不那么严谨的来看,中间件以Func<NextMiddleware,ThisMiddleware>的形式注册并存储在一个列表中。

可以通过ApplicationBuilder的Use方法注册中间件

0x02 管道的构建

管道的构建就是把Func<RequestDelegate,RequestDelegate>列表串在一起。用第一个Func的返回值作为第二个Func的参数,第二个Func的返回值作为第三个Func的参数,依次类推。最终返回最后一个Func返回的RequestDelegate(中间件)。管道工作时最后一个RequestDelegate可以决定是否调用倒数第二个RequestDelegate,倒数第二个RequestDelegate可以决定是否调用倒数第三个RequestDelegate,依次类推直到调用第一个RequestDelegate。这中间有两个问题:

第一个是这样构建管道,中间件的顺序和注册的时候是相反的,所以在构件时首先把列表_components.Reverse()以保证正确的中间件顺序。

第二个问题是构建第一个中间件时没有RequestDelegate可以传入,所以需要构建一个把状态码设置为404的中间件作为最开始的RequestDelegate传入。当然在构建完成后这个中间件是存在于管道最末端的。这样管道构建就算完成了。Build()代码如下:

0x03 测试

构建完成后的管道和中间件如下图:

这是微软官方的图,很多文章中也引用过。从这张图中可以看出来中间件通过调用next()启动下一个中间件。如果中间件不调用next()那么它之后的所有中间件就都不会调用了。除此之外还有一个细节需要注意,就是next()的调用并不是必须要放到最后的。也就是说可以先调用后面的中间件,等后面的中间件调用完成后在执行一些操作(图中的more logic)。

下面来分别进行测试,正常建立一个.NET Core MVC Web项目。

测试1:注释掉Configure()中的所有内容,然后依次注册中间件:

运行后结果为:

这个测试印证了之前代码中看到的中间件的注册顺序就是调用顺序。


测试2:注释掉Middleware1的next调用,其它保持不变。这样Middleware1就不会调用Middleware2,Middleware2以及之后的所有中间件都无法调用。

运行结果变为:

这个测试说明Middleware1不调用next()的话后面的Middleware2和Middleware3都没有被调用。


测试3:把Configure()方法修改如下:

我们在最开始注册一个中间件记录当前时间,然后调用后面所有中间件,最后返回时计算后面所有中间件执行所消耗的时间。为了看上去更明显后面又注册了一个中间件强制睡眠100毫秒。需要注意的是强制睡眠的中间件要注册在MVC之前,因为MVC结束后就直接返回了,不会调用后面的中间件了。

运行结果为:

这个测试说明对下一个中间件的调用不一定非要放到最后,可以先调用后面中间件,等后面所有中间件调用完成后再继续处理。

0x04 写在最后

这篇文章主要讨论了中间件的注册和管道构建的一些原理,实际上对于复杂一点的中间件来说,一般都有更复杂的逻辑并对其它组件依赖。下一篇将讨论把中间件写成一个类并注入依赖的方法和原理。

此外这篇文章主要是我个人的一些理解和直觉。。。好吧真的有些是直觉,能力有限,博客园大牛众多,有错误的地方大家嘴下留情啊。

0x05 相关文章

.NET Core中间件的注册和管道的构建(1)---- 注册和构建原理

.NET Core中间件的注册和管道的构建(2)---- 用UseMiddleware扩展方法注册中间件类

.NET Core中间件的注册和管道的构建(3) ---- 使用Map/MapWhen扩展方法

.NET Core中间件的注册和管道的构建(1)---- 注册和构建原理的更多相关文章

  1. .NET Core中间件的注册和管道的构建(3) ---- 使用Map/MapWhen扩展方法

    .NET Core中间件的注册和管道的构建(3) ---- 使用Map/MapWhen扩展方法 0x00 为什么需要Map(MapWhen)扩展 如果业务逻辑比较简单的话,一条主管道就够了,确实用不到 ...

  2. .NET Core中间件的注册和管道的构建(2)---- 用UseMiddleware扩展方法注册中间件类

    .NET Core中间件的注册和管道的构建(2)---- 用UseMiddleware扩展方法注册中间件类 0x00 为什么要引入扩展方法 有的中间件功能比较简单,有的则比较复杂,并且依赖其它组件.除 ...

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

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

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

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

  5. ASP.NET Core MVC 2.x 全面教程_ASP.NET Core MVC 03. 服务注册和管道

    ASP.NET Core MVC 2.x 全面教程_ASP.NET Core MVC 03. 服务注册和管道 语雀: https://www.yuque.com/yuejiangliu/dotnet/ ...

  6. .net core 中间件管道底层剖析

    .net core 管道(Pipeline)是什么? 由上图可以看出,.net core 管道是请求抵达服务器到响应结果返回的中间的一系列的处理过程,如果我们简化一下成下图来看的话,.net core ...

  7. net core 中间件管道

    net core 中间件管道 .net core 管道(Pipeline)是什么? 由上图可以看出,.net core 管道是请求抵达服务器到响应结果返回的中间的一系列的处理过程,如果我们简化一下成下 ...

  8. ASP.NET Core 中间件详解及项目实战

    前言 在上篇文章主要介绍了DotNetCore项目状况,本篇文章是我们在开发自己的项目中实际使用的,比较贴合实际应用,算是对中间件的一个深入使用了,不是简单的Hello World,如果你觉得本篇文章 ...

  9. [转]ASP.NET Core 中间件详解及项目实战

    本文转自:http://www.cnblogs.com/savorboard/p/5586229.html 前言 在上篇文章主要介绍了DotNetCore项目状况,本篇文章是我们在开发自己的项目中实际 ...

随机推荐

  1. CSS3 background-image背景图片相关介绍

    这里将会介绍如何通过background-image设置背景图片,以及背景图片的平铺.拉伸.偏移.设置大小等操作. 1. 背景图片样式分类 CSS中设置元素背景图片及其背景图片样式的属性主要以下几个: ...

  2. 使用Visual Studio 2015 开发ASP.NET MVC 5 项目部署到Mono/Jexus

    最新的Mono 4.4已经支持运行asp.net mvc5项目,有的同学听了这句话就兴高采烈的拿起Visual Studio 2015创建了一个mvc 5的项目,然后部署到Mono上,浏览下发现一堆错 ...

  3. Ubuntu 14.04中Elasticsearch集群配置

    Ubuntu 14.04中Elasticsearch集群配置 前言:本文可用于elasticsearch集群搭建参考.细分为elasticsearch.yml配置和系统配置 达到的目的:各台机器配置成 ...

  4. nginx+php的使用

    原文来自:windows下配置nginx+php环境 按照他的步骤走,亲测可用! 但是这里他后面说的根目录可能有些人有点懵. 其实在设置的时候就设置了: 网站根目录就是www这个目录,如果没创建请自行 ...

  5. [APUE]文件和目录(下)

    一.mkdir和rmdir函数 #include <sys/types.h> #include <sys/stat.h> int mkdir(const char *pathn ...

  6. windows环境下sublime的nodejs插件详细安装图解

    前面的话   搜索了好多文档后,才成功地安装了sublime text3的nodejs插件.为了存档,也为了方便有同样需求的朋友,将其安装过程详细记录如下 安装nodejs 虽然nodejs官网提供了 ...

  7. 关于python的bottle框架跨域请求报错问题的处理

    在用python的bottle框架开发时,前端使用ajax跨域访问时,js代码老是进入不了success,而是进入了error,而返回的状态却是200.url直接在浏览器访问也是正常的,浏览器按F12 ...

  8. Asp.net Core准备工作

    1.安装环境 安装.Net Core SDK 安装VS2015 Update3 安装DotNetCore.1.0.1-VS2015Tools.Preview2.0.2.exe 2.新建Core工程 项 ...

  9. 深入理解CSS六种颜色模式

    前面的话 赏心悦目的颜色搭配让人感到舒服,修改元素颜色的功能让人趋之若鹜.但颜色规划不当,会让网站用户无所适从.颜色从<font color="">发展至今,保留了很多 ...

  10. js callee,caller学习

    原文地址:js callee,caller学习 /* * caller 返回一个对函数的引用,该函数调用了当前函数. * 如果函数是由顶层调用的,那么 caller包含的就是 null . * 如果在 ...