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 写在最后

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

原文地址:http://www.cnblogs.com/durow/p/5736385.html

.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

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

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

    0x00 为什么需要Map(MapWhen)扩展 如果业务逻辑比较简单的话,一条主管道就够了,确实用不到Map.不过当业务逻辑比较复杂的时候,有时候我们可能希望根据情况的不同使用特殊的一组中间件来处理 ...

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

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

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

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

  4. aspx 使用什么中间件_.NET Core中间件与依赖注入的一些思考

    点击上方蓝字"小黑在哪里"关注我吧 1.起源? 为什么会有这篇文章呢? 源于我看了老A的aspnet core 3 框架揭秘[1]请求管道 篇产生的疑惑? 三点疑惑: Single ...

  5. ASP.NET Core中间件初始化探究

    前言 在日常使用ASP.NET Core开发的过程中我们多多少少会设计到使用中间件的场景,ASP.NET Core默认也为我们内置了许多的中间件,甚至有时候我们需要自定义中间件来帮我们处理一些请求管道 ...

  6. .NET Core中间件与依赖注入的一些思考

    点击上方蓝字"小黑在哪里"关注我吧 1.起源? 为什么会有这篇文章呢? 源于我看了老A的aspnet core 3 框架揭秘[1] 请求管道 篇产生的疑惑? 三点疑惑: Singl ...

  7. .net core HttpClient 使用之消息管道解析(二)

    一.前言 前面分享了 .net core HttpClient 使用之掉坑解析(一),今天来分享自定义消息处理HttpMessageHandler和PrimaryHttpMessageHandler ...

  8. ASP.NET Core 中间件分类

    ASP.NET Core 中间件的配置方法可以分为以上三种,对应的Helper方法分别是:Run(), Use(), Map(). Run(),使用Run调用中间件的时候,会直接返回一个响应,所以后续 ...

  9. Asp.Net Core 中间件应用实战中你不知道的那些事

    一.概述 这篇文章主要分享Endpoint 终结点路由的中间件的应用场景及实践案例,不讲述其工作原理,如果需要了解工作原理的同学, 可以点击查看以下两篇解读文章: •Asp.Net Core EndP ...

最新文章

  1. 关系数据理论中的范式
  2. 为什么MySQL不推荐使用uuid或者雪花id作为主键?
  3. command not found: shopt 的 ~/.bashrc
  4. 【Java静态代理】以模拟“婚庆公司帮助你嫦娥奔月”为例
  5. 使用spring boot +WebSocket实现(后台主动)消息推送
  6. 小学四年级计算机制作月历教案,四年级上册信息技术教案-1制作月历|冀教版(5页)-原创力文档...
  7. c语言方向变量,C语言,变量与内存
  8. 获取当前日期是本年的第几周java与mysql获取值不一致
  9. EDA第一次课<1117电路图的绘制>
  10. mui android 模拟器,MUI框架-07-HBuilder+夜神安卓模拟器
  11. 小米刷机一直在android界面,小米手机变砖怎么办?(小白刷机记)卡在开机怎么办?界面进不去,重启不管用​...
  12. 使用docx4j追尾合并多个docx文件为一个docx文件
  13. 免费思维导图软件,收藏
  14. 卸载windows电脑软件,这样卸载才干净
  15. 新家入住气味难忍 除去甲醛有妙招
  16. IE和Outlook Express的翻译插件设计
  17. pythonSSL证书错误
  18. mini2440 LED 测试
  19. php 字母数字下划线,CTF踩坑PHP编写一个不包含数字字母和下划线的后门
  20. java模拟回合制游戏大小姐_[源码和文档分享]基于java的RPG回合制游戏

热门文章

  1. Java工程转换为Maven工程-b
  2. yum安装最新的 LNMP
  3. Sphinx全文检索引擎测试
  4. SQLServer事务的隔离级别
  5. .NET 编码的基础知识
  6. EF Core 小技巧:迁移已经应用到数据库,如何进行迁移回退操作?
  7. 有趣分享:国内产业图谱
  8. Source Generator 单元测试
  9. ABP Vnext 4.4:统一Ef Core的DbContext/移除EF Core Migrations项目
  10. 基于ABP落地领域驱动设计-02.聚合和聚合根的最佳实践和原则