ASP.NET Core HTTP 管道中的那些事儿

 

前言

马上2016年就要过去了,时间可是真快啊。

上次写完 Identity 系列之后,反响还不错,所以本来打算写一个 ASP.NET Core 中间件系列的,但是中间遇到了很多事情。首先是 NPOI 的移植工作,移植过后还有一些Bug需要修复,然后一个事情是一个有关于分布式架构中消息一致性的一个中间件设计开发工作,还有就是博客还要坚持写,最后就是还有好几本书需要读,以及消化学习,所以深深感觉到时间不够用。废话不多说了,进入主题。

大部分中间件都是要依赖于 HTTP 管道和 HttpAbstractions 提供的上下文的,所以有必要先介绍一下 ASP.NET Core 在管道中封装了什么,了解清楚之后有助于更高的进阶学习。你看不懂也没有关系,对这些概念有一个认识就可以了,不需要你精通每一步都具体做了哪些东西,达到会用就是我的目的。因为我觉得随着你以后开发的深入,对这些东西使用多了之后,自然会想了解更多,到那个时候,你就会去看源码了。

IApplicationBuilder

IApplicationBuilder 是应用大家最熟悉它的地方应该就是位于 Startup.cs 文件中的 Configure 方法了吧

public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
app.UseDeveloperExceptionPage();
app.UseStaticFiles();
app.UseMvc();
}

IApplicationBuilder 就像其名字一样,其实很简单,就是对内做了一个接口封装,对外提供了一个扩展,具体来说就是

对内封装了

  • IServiceProvider ApplicationServices { get; set; }:应用程序使用的服务,就是ConfigureServices注入的那些。
  • IFeatureCollection ServerFeatures { get; }: 工具箱对象,下面会提到的。
  • IDictionary<string, object> Properties { get; } :横跨各个中间件,在他们之间共享数据。

对外扩展了

  • IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware):注册中间件

还有一个 Build 用来返回管道最终的 HttpContext 状态

  • RequestDelegate Build(); : 最终的 RequestDelegate 形态

没什么复杂的东西,就这几个东西需要了解,下面是一个 IApplicationBuilder 的贴图,看起来应该会更直观。

那 RequestDelegate 又是什么东西呢?

RequestDelegate

RequestDelegate 是一个委托,是以委托形式对 HttpContext 的封装,在 ASP.NET Core 中也是非常重要的一个对象,先看一下定义吧。

namespace Microsoft.AspNetCore.Http
{
public delegate Task RequestDelegate(HttpContext context);
}

为什么说这个对象很重要呢,因为在管道中所有的中间件都是直接或者间接的使用到它来做一些功能,因为它包装这 HttpContext 的嘛,而在Web开发中 HttpContext 的地位又是如此的高,接下来就说说 HttpContext

HttpContext

HttpContext 应该是做Web开发最熟悉的一个对象了,在这个对象中,封装着Http整个管道中的关键对象信息,这个对象同时伴随着整个管道中传输,也就是会经历整个请求的生命周期,所以这个对象非常重要,也是学习Web开发的一个基础知识。

与传统 .NET Framework 中的 System.Web.HttpContext 不同的是,在 ASP.NET Core 中 HttpContext 是一个抽象类,位于 Microsoft.AspNetCore.Http 命名空间下。它有一个默认的实现叫 DefaultHttpContext 位于 Microsoft.AspNetCore.Http 程序集。

我们知道以前的 System.Web.HttpContext 是怎么创建的吧?

在传统ASP.NET程序中,IIS接收到请求之后,会交给 aspnet_isapi.dll 这个程序集,程序集启动 ASP.NET 运行环境,然后调用 ISAPIRuntime 进行封装,封装之后就是一个 HttpWorkRequest 对象了,然后由 HttpRuntime将其转化为一个HttpContext。

所以在System.Web.HttpContext中,其构造函数为 HttpWorkerRequest

namespace System.Web
{
public sealed class HttpContext : IServiceProvider, IPrincipalContainer
{
public HttpContext(HttpWorkerRequest wr);
}
}

也就是说其实构建HttpContext所有的信息都是来自于 IIS 传递下来的 HttpWorkerRequest

现在,忘了它吧,是的全部忘掉,这个时候你又要骂微软了,尼玛当年为了面试这个东西不知道背了多少遍。 =_=

没办法,时代要发展要进步,我们也需要不断的学习,那在 ASP.NET Core 中,没有了 IIS ,它的 HttpContext 又是如何生成的呢? 构建 HttpContext 所需的信息又怎么来的呢? 客官不要着急,听我慢慢分解

IFeatureCollection

这里就需要先说一下另外一个比较重要接口了,它就是 IFeatureCollection 接口,这个接口是干嘛的呢? 我们先看一下它的定义:

public interface IFeatureCollection : IEnumerable<KeyValuePair<Type, object>>
{ bool IsReadOnly { get; } int Revision { get; } object this[Type key] { get; set; } TFeature Get<TFeature>(); void Set<TFeature>(TFeature instance);
}

看到这个接口的定义应该能够明白其功能了,接口继承于IEnumerable<KeyValuePair<Type, object>> 说明接口是一个键值对的集合,我们给接口取个名字吧,叫“工具箱”。

有些同学应该猜出来了,是的,ASP.NET Core中构建 HttpContext 就是所有需要的组件都是来自于 工具箱,那么 工具箱 里面都有什么呢?可以看到工具箱里面有 IHttpRequestFeature, IHttpResponseFeature, ISessionFeature 等等还有很多就不一一列举了,正是由于这一个一个的工具箱里面的工具,最终构建成为了整个 HttpContext 对象。我们来看一下 HttpContext 对象的构造函数:

namespace Microsoft.AspNetCore.Http
{
public class DefaultHttpContext : HttpContext
{
public DefaultHttpContext(IFeatureCollection features)
{
Initialize(features);
}
}
}

没错吧,有同学可能要问了,工具箱里面的这些工具什么时候初始化的呢? 先别急,我们先看看我们熟悉的 Request 和 Response。

HttpRequest

同样在 ASP.NET Core ,HttpRequest 也成为了一个抽象类,它的默认实现叫 DefaultHttpRequest,主要是封装浏览器对服务器的请求的各种数据,包括浏览器请求的网址,查询字符串数据或表单数据等等...

不一一详细介绍了,都是很简单的内容。

HttpResponse

HttpResponse 也成为了一个抽象类,它的默认实现叫 DefaultHttpResponse,主要是是服务器接收到浏览器的请求后,处理返回结果常用的一个对象。

ASP.NET Core 管道

是时候该解释一下上面的 工具箱 初始化的问题了,我想我用一个图来直接说明管道中的请求再合适不过了,下面就是一个 ASP.NET Core 整个服务端构建管道一个流程图:

从图中可以看到,RequestDelegate 携带着 HttpContext 一路经过各种 Server、Hosting 等,最终到达了由 IApplicationBuilder 构建出来的 Application pipeline 这一管道区域,然后再经过各种中间件处理,最终构建出来了我们的 Response,而我们的工具箱 也正是在这个过程中变得 “ 饱满 ” 起来。

有一个需要知道的知识点就是,中间件是怎么样添加或者叫注册到管道中的呢? 又是如何被应用起来的呢?

上面的图可以看到,橙色区域的 Application pipeline 是由 IApplicationBuilder 构建起来的。也就是说我们可以在 IApplicationBuilder 做点什么东西来添加我们的中间件。 是的 IApplicationBuilder 暴露出来了一个 IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware); 方法来让我们注册中间件,也就是说位于 Startup.cs 文件中的 Configure 方法。

那么又是怎么样应用起来的呢? IApplicationBuilder 在 Hosting 中有一个 IApplicationBuilderFactory 的对象,Hosting 通过这个Factory 创建之后就会传递到了 HostingApplication 对象中,最后由 IWebHost 对象调用 IServer 对象的Start 同时把 HostingApplication传递进去来最终启动服务端。可以对照上面的图理解一下。

总结

在本篇中,我们知道了 ASP.NET Core Http 管道中的几个对象,他们分别是 IApplicationBuilder , RequestDelegate , HttpContext , HttpRequest , HttpResponseIFeatureCollection 等,然后也知道了他们之间的关系,接着我们通过一个管道流程图知道了他们的调用关系,也知道了如何向管道中注册中间件。

NET Core HTTP 管道的更多相关文章

  1. ASP.NET Core HTTP 管道中的那些事儿

    前言 马上2016年就要过去了,时间可是真快啊. 上次写完 Identity 系列之后,反响还不错,所以本来打算写一个 ASP.NET Core 中间件系列的,但是中间遇到了很多事情.首先是 NPOI ...

  2. 用.Net Core控制台模拟一个ASP.Net Core的管道模型

    在我的上几篇文章中降到了asp.net core的管道模型,为了更清楚地理解asp.net core的管道,再网上学习了.Net Core控制台应用程序对其的模拟,以加深映像,同时,供大家学习参考. ...

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

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

  4. asp.net core mvc 管道之中间件

    asp.net core mvc 管道之中间件 http请求处理管道通过注册中间件来实现各种功能,松耦合并且很灵活 此文简单介绍asp.net core mvc中间件的注册以及运行过程 通过理解中间件 ...

  5. net core 中间件管道

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

  6. 如果你想深刻理解ASP.NET Core请求处理管道,可以试着写一个自定义的Server

    我们在上面对ASP.NET Core默认提供的具有跨平台能力的KestrelServer进行了详细介绍(<聊聊ASP.NET Core默认提供的这个跨平台的服务器——KestrelServer& ...

  7. ASP.NET Core真实管道详解[2]:Server是如何完成针对请求的监听、接收与响应的【上】

    Server是ASP .NET Core管道的第一个节点,负责完整请求的监听和接收,最终对请求的响应同样也由它完成.Server是我们对所有实现了IServer接口的所有类型以及对应对象的统称,如下面 ...

  8. ASP.NET Core真实管道详解[1]:中间件是个什么东西?

    ASP.NET Core管道虽然在结构组成上显得非常简单,但是在具体实现上却涉及到太多的对象,所以我们在 <ASP.NET Core管道深度剖析[共4篇]> 中围绕着一个经过极度简化的模拟 ...

  9. ASP.NET Core真实管道详解[1]

    ASP.NET Core管道虽然在结构组成上显得非常简单,但是在具体实现上却涉及到太多的对象,所以我们在 <ASP.NET Core管道深度剖析[共4篇]> 中围绕着一个经过极度简化的模拟 ...

随机推荐

  1. wifi强度数据采集器(android)

    来源:毕业设计 关键词:wifi数据的采集 SQLite数据库的使用 需求 采集实验室内各坐标处各wifi信号的强度 UI 因为是辅助工具,所以UI写的很简单,如下图 Wifi相关操作 //获取Wif ...

  2. 16、总经理要阅读的书籍 - IT软件人员书籍系列文章

    总经理是公司的一个领导角色.他主要负责公司级别的比如规划,战略等等内容.有些公司的总经理,比如软件公司的总经理,往往是一个大的业务员,将更多的大型的软件项目投取过来,让公司能够有钱赚,让公司员工能够跟 ...

  3. 你知道哪些linux命令,能把文件上传到远程linux服务器

    多数情况下 企业的服务基本都是部署在linux服务器 那对于测试同学,必须掌握基本的linux命令   至少要知道怎么部署整体环境   部署过程中,经常需要的操作,是向服务器上传部署包   你一般都是 ...

  4. mac 远程连接服务器

    很多刚用mac的同学 可能会纠结,连接远程服务器咋整? 有没有类型windows上的securecrt 其实,完全可以不用: mac自带的终端就可以搞定:终端terminal 如何连接远程服务器? s ...

  5. 让UNION与ORDER BY并存于SQL语句当中

    在SQL语句中,UNION关键字多用来将并列的多组查询结果(表)合并成一个结果(表),简单实例如下: SELECT [Id],[Name],[Comment] FROM [Product1] UNIO ...

  6. HDFS 和YARN HA 简介

    HDFS: 基础架构 1.NameNode(Master) 1)命名空间管理:命名空间支持对HDFS中的目录.文件和块做类似文件系统的创建.修改.删除.列表文件和目录等基本操作. 2)块存储管理. 使 ...

  7. SQLServer基本函数

    1.字符串函数  长度与分析用 datalength(Char_expr) 返回字符串包含字符数,但不包含后面的空格 substring(expression,start,length) 取子串 ri ...

  8. Solr页面查询各个字段参数解释

    q:查询的关键字,此参数最为重要,例如,q=id:1,默认为q=*:*,类似于sql中的where 1=1. fq(filter query):过滤查询,提供一个可选的筛选器查询.返回在q查询符合结果 ...

  9. 烂泥:NFS做存储与KVM集成

    本文由秀依林枫提供友情赞助,首发于烂泥行天下. 以前有关NFS的文章,我们介绍的都是NFS的使用挂载等等.这篇文章我们介绍有关NFS作为存储使用. 既然本篇文章的主题是有关NFS的,我们还是先把NFS ...

  10. 使用bakefile编译C工程代码

    前言 最近有个想法,想把ineedle整体架构从头自己编写代码来实现一下,来加深对iNeedle系统的理解,同时加强Linux + C相关知识.由于iNeedle系统的庞大,只能是先把框架搭起来,根据 ...