我相信在第一次听到这个名词时,有的小伙伴会一脸懵,而且还有很多疑问,其实我在第一次接触这个概念时跟很多小伙伴一样一脸懵.

接下来我将以我自己的理解来讲述什么是管道模型。

什么是管道模型

首先有没有小伙伴思考过在.NET 中WebForm、MVC、Webapi 之类的框架做应用程序的开发部署之后,用户在浏览器或是利用HttpClient 输入URL地址请求之后是怎么到达我们的应用程序呢?中间又经过了哪些步骤呢?

其实在用户输入URL之后,Http请求会经过一系列的流转,每次流转都有一些特有的处理,而管道模型就是为Http请求提供支撑和流转而抽象出的一个模型。


在实际中他是如何执行的

老规矩先上图,然后再一步一步分析,这样比较直观,其实在isapi之前还有一些只是在流程图中没有标记出来,因为没必要去深究,至少在目前阶段.

下面以文字的方式来解释一下,管道模型一部分的流程图走向情况:

  1. 用户发起请求到达DNS,DNS会解析域名找到对应的IP及端口。

  2. IIS中HttpSys监听服务接受请求。

  3. HttpSys监听服务根据请求类型的后缀,将请求转发到对应的应用程序处理(isapi.dll),IIS中处理程序映射可以实现配置,不同的后缀将到达不同的处理程序.net的请求映射到aspnet.isapi,java或者其他的也可以配置对应的dll。

  4. 在http请求到达Isapi后会将请求转换为一个HttpWorkerRequest对象,然后把对象传入到

    HttpRuntime.ProcessRequest

  5. 在ProcessRequest方法中利用HttpApplicationFactory传入HttpContext进行构建

    HttpApplication,当然在这前几个步骤如果发生错误,那就直接返回了。

我上面描述的这一部分已经执行完了,当然由于是系统固定流程这时作为开发者并不能进行升级或者是扩展,待请求到达了我们被创建的HttpApplication之后的才是真正的开始.


  • HttpApplication

HttpApplication类在管道模型中充当一个很重要的角色,它定义对 ASP.NET 应用程序内所有应用程序对象公用的方法、属性和事件,此类是用户在 Global.asax 文件中定义的应用程序的基类,订阅httpApplication事件的任何 HTTP 模块 (HttpModule) 都必须实现 IHttpModule接口.

在我们学习管道的过程中,所注重的应该是它所发布的一系列事件,它们用来处理各式各样的请求,并且每次请求都会将它们逐一执行一遍,但由于处理不尽相同,又可能都需要,所以使用了事件的模式来扩展,具体事件内容和作用,在下方引入的代码中.

开闭原则

观察者模式

(用事件的意义:封装共性部分,将不确定部分利用事件的方式,说白了就是委托回调,将需要扩展的部分以委托的形式暴露出去,委托对于C#,跟指针对于C一样的伟大,一样的令人膜拜)

 public class HttpApplication : IComponent,IDisposable,
IHttpAsyncHandler, IHttpHandler,
IRequestCompletedNotifier, ISyncContext
{
//表示处理的开始
public event EventHandler BeginRequest;
//验证请求,一般用来取得请求用户的信息
public event EventHandler AuthenticateRequest;
//已经获取请求用户的信息
public event PostAuthenticateRequest;
// 授权,一般用来检查用户的请求是否获得权限
public event AuthorizeRequest;
//用户请求已经得到授权
public event PostAuthorizeRequest;
//获取以前处理缓存的处理结果,如果以前缓存过,那么不必再进行请求的处理,直接返回缓存结果
public event ResolveRequestCache;
//已经完成缓存的获取操作
public event PostResolveRequestCache;
//已经根据用户的请求,创建了处理请求的处理器对象
public event PostMapRequestHandler;
//取得请求的状态,一般用于Session
public event AcquireRequestState;
//已经取得了Session
public event PostAcquireRequestState;
//准备执行处理程序
public event PreRequestHandlerExecute; //已经执行了处理程序
public event PostRequestHandlerExecute;
//释放请求的状态
public event ReleaseRequestState;
//已经释放了请求的状态
public event PostReleaseRequestState;
//更新缓存
public event UpdateRequestCache;
// 已经更新了缓存
public event PostUpdateRequestCache;
//请求的日志操作
public event LogRequest;
//已经完成了请求的日志操作
public event PostLogRequest;
本次请求处理完成
public event EndRequest;
}

  • HttpModule

疑问又来了,既然HttpApplication发布了一系列事件,我想对其发布某个事件进行扩展或者自定义又该如何操作呢?接下来就该HttpModule登场了,没错他才是主角,在ASP.NET中占有举足轻重的地位,可以说是大哥级别的,因为无论是WebForm,又或者是MVC乃至WebAPI都只是HttpModule延伸出来的冰山一角而已,这么说在某种意义上一点也不过分,只是突然感觉自己很渺小.

突然这样说可能让人无法理解,当你自己去理解了,你肯定会赞同我这种说法.

由于每一次Http请求,都会将HttpApplication中所有的事件执行一遍,同理那实现订阅的HttpModule也会针对每一个请求而执行一次,所以比较适合做一些全局的操作,例如缓存,或者实现请求压缩,做一些性能监控,或者恶意ip请求校验,下面用一个实例来实现HttpModule请求压缩,以及实现的步骤

  • 1.首先创建一个类GzipModule 实现IHttpModule接口
internal class GzipModule : IHttpModule
{
public void Dispose(){} public void Init(HttpApplication app)
{
app.BeginRequest += App_BeginRequest;
} private void App_BeginRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
string IsAcceptType = app.Context.Request.Headers["Accept-Encoding"]; //请求头不包含格式编码直接拦截返回
if (string.IsNullOrEmpty(IsAcceptType)) return;
IsAcceptType = IsAcceptType.ToUpperInvariant(); //如果客户端请求头包含压缩请求标识那么响应也返回压缩格式
//如果是默认请求就返回默认的响应格式
if (IsAcceptType.Contains("GZIP"))
{
app.Context.Response.AppendHeader("Content-encoding", "gzip");
app.Context.Response.Filter = new GZipStream(app.Context.Response.Filter
, CompressionMode.Compress);
}
else if (IsAcceptType.Contains("DEFLATE"))
{
app.Context.Response.AppendHeader("Content-encoding", "deflate");
app.Context.Response.Filter = new DeflateStream(app.Context.Response.Filter
, CompressionMode.Compress);
}
}
}
  • 2.在配置文件下注册HttpModule
	<system.webServer>
<httpErrors existingResponse="PassThrough" />
<modules>
<add name="GzipModule" type="namespace.GzipModule, namespace" preCondition="integratedMode" />
</modules>
</system.webServer>

到这里您可能会问有没有动态注册的方式不写在配置文件,我的回答是有的,以webapi框架为例

1.在AssemblyInfo文件中加入编译特性,在代码编译时动态注册

 [assembly: PreApplicationStartMethod(typeof(DynamicRegisterHttpMoudle), "RegisterMoudle")]
public class DynamicRegisterHttpMoudle
{
public static void RegisterMoudle()
{
HttpApplication.RegisterModule(typeof(GzipModule));
}
}

2.利用静态构造函数注入,因为静态构造函数是在类加载时首先被CLR调用的

    public class WebApiApplication : System.Web.HttpApplication
{
static WebApiApplication(){
RegisterModule(typeof(GzipModule));
}
protected void Application_Start() { }
}

到这里你可能仍然无法理解HttpModule,只是简单知道它是什么和它的表象,最重要的一点就是任何Http请求都会经过它,但是我觉得知道这一点就够了,相信随着后面的积累,你对它将会对它有颠覆性的认识,并且崇拜它.


HttpHandler

接下来我们还要认识一个重要的内容HttpHandler,至于它是什么?相对正式的回答是这样的:

HttpHandler是一个HTTP请求的真正处理中心,也正是在这个HttpHandler容器中,ASP.NET Framework才真正地对客户端请求的服务器页面做出编译和执行并将处理过后的信息附加在HTTP请求信息流中再次返回到HttpModule中。

不过从字面意思还是能看得懂的,至于大白话的意思就是Http最终的请求是由这个叫HttpHandler来完成的,到底是不是这样呢?在后面我会进一步去验证,先来做一个HttpHandler简单的实现,我们自定义一个后缀为.cc请求的被我们自定义的HttpHandler处理。

1.首先自定义类然后继承自IHttpHandler

 public class CustomHttpHander : IHttpHandler
{
public bool IsReusable => false; public void ProcessRequest(HttpContext context)
{
string time =DateTime.Now.ToString();
string respone = string.Format("自定义HttpHander,{0}请求到达", time );
context.Response.Write(respone);
}
}

2.配置文件注册HttpHandler

<system.webServer>
<httpErrors existingResponse="PassThrough" />
<modules>
<add name="CustomHttpHandler" path="*.cc" verb="*" type="namespace.CustomHttpHander,namespace" preCondition="integratedMode,runtimeVersionv4.0" />
</modules>
</system.webServer>

这样我们就自定义了一个.cc后缀的请求被CustomHttpHandler处理,至于为什么能实现特殊请求后缀的自定义,这是HttpHandler的机制,但是它的核心内容还是一个Http请求处理中心,当然我们后续会进一步了解的MvcHandler 、HttpControllerHandler这些meb框架中的核心处理程序,从源码的角度来更进一步的了解它。

至此管道模型大致的概念以及执行流程已经在本文中做了简单分析,后续学习Mvc和Webapi的源码因为和管道这一块衔接很紧密,有了这一部分的铺垫及知识点画像,相对会更加容易理解。

ASP.NET管道模型简析的更多相关文章

  1. Asp.net管道模型(管线模型)

    Asp.net管道模型(管线模型)   前言 为什么我会起这样的一个标题,其实我原本只想了解asp.net的管道模型而已,但在查看资料的时候遇到不明白的地方又横向地查阅了其他相关的资料,而收获比当初预 ...

  2. Asp.net管道模型(管线模型)之一发不可收拾

    前言 为什么我会起这样的一个标题,其实我原本只想了解asp.net的管道模型而已,但在查看资料的时候遇到不明白的地方又横向地查阅了其他相关的资料,而收获比当初预想的大了很多. 有本篇作基础,下面两篇就 ...

  3. asp.net管道模型

    查了很多资料,终于大概弄懂管道模型(注意并非指定是asp.net范畴)是个什么概念了,其实就是从Unix移植过来的一种概念,也可以说是一种模式吧(只允许一头读,一头写,并且读完了就会自动消失). as ...

  4. ASP.NET-HTTP管道模型

    HTTP管道模型处理WEB程序很小的一方面.管道模型是类似于Web Services的一种在服务器端处理ASP.NET页面的框架技术 一.管道对象模型 在System.Web的命名空间中处理HTTP的 ...

  5. Asp.net管道模型之(HttpModules 和 HttpHandler)

    上一节我们从大概范围介绍了管道模型的整体流程,我们从其中知道管道最重要的两大组件为:HttpModules 跟 HttpHandler.今天我们着重来介绍一下这两大组件 一:asp.net处理管道 从 ...

  6. ASP.Net 管道模型 VS Asp.Net Core 管道 总结

    1 管道模型  1 Asp.Net Web Form管道 请求进入Asp.Net工作进程后,由进程创建HttpWorkRequest对象,封装此次请求有关的所有信息,然后进入HttpRuntime类进 ...

  7. Owin管道与asp.net管道模型

    ------2016.3.6 更新 文中提到没有Microsoft.Owin.Host.SystemWeb 这个dll 便不会加载Startup.Configuration,因为这个dll 其中有个O ...

  8. asp.net 管道模型+生命处理周期

    http://www.cnblogs.com/qianlifeng/archive/2010/12/16/1908568.html https://msdn.microsoft.com/zh-cn/l ...

  9. Linux驱动之平台设备驱动模型简析(驱动分离分层概念的建立)

    Linux设备模型的目的:为内核建立一个统一的设备模型,从而有一个对系统结构的一般性抽象描述.换句话说,Linux设备模型提取了设备操作的共同属性,进行抽象,并将这部分共同的属性在内核中实现,而为需要 ...

随机推荐

  1. Windows漏洞:MS08-067远程代码执行漏洞复现及深度防御

    摘要:详细讲解MS08-067远程代码执行漏洞(CVE-2008-4250)及防御过程 本文分享自华为云社区<Windows漏洞利用之MS08-067远程代码执行漏洞复现及深度防御>,作者 ...

  2. Go语言核心36讲(Go语言实战与应用七)--学习笔记

    29 | 原子操作(上) 我们在前两篇文章中讨论了互斥锁.读写锁以及基于它们的条件变量,先来总结一下. 互斥锁是一个很有用的同步工具,它可以保证每一时刻进入临界区的 goroutine 只有一个.读写 ...

  3. liunx下安装mysql(8.0.27)

    一.软件下载: 1.通过官网下载: https://dev.mysql.com/downloads/repo/yum/ 本文使用的系统为centos7,基于RedHat7的版本 2.下载完成后文件 m ...

  4. [loj3523]分糖果

    做法1 将问题离线,并在左端点和右端点打上差分,之后即可以看作求$f(C,[a_{1},a_{2},...,a_{n}])$,其表示以$C$为上限(0为下限),从0开始不断加上$a_{i}$(可以为负 ...

  5. [cf1217F]Forced Online Queries Problem

    可以用并查集维护连通性,删除可以用按置合并并查集,但删掉一条边后无法再维护两点的联通性了(因为产生环的边是不加入的)暴力思路是, 考虑前i个操作后边的集合,暴力加入即可,但复杂度是$o(n^2)$的用 ...

  6. Dubbo的反序列化安全问题——kryo和fst

    目录 0 前言 1 Dubbo的协议设计 2 Dubbo中的kryo序列化协议触发点 3 Dubbo中的fst序列化协议触发点 3.1 fst复现 3. 2 思路梳理 4 总结 0 前言 本篇是Dub ...

  7. 【JVM源码解析】模板解释器解释执行Java字节码指令(上)

    本文由HeapDump性能社区首席讲师鸠摩(马智)授权整理发布 第17章-x86-64寄存器 不同的CPU都能够解释的机器语言的体系称为指令集架构(ISA,Instruction Set Archit ...

  8. SA 复习笔记

    大家好,由于蒟蒻 tzc 最近被动态点分治这个学也学不会的毒瘤玩意儿虐得不轻,所以就准备换换脑筋来 Van 同样学也学不会的后缀数组了. 考虑一个非常经典的问题:[模板]后缀排序. 一些定义(very ...

  9. Codeforces 739C - Alyona and towers(线段树)

    Codeforces 题目传送门 & 洛谷题目传送门 可能有人会问我为什么为这道 *2500 的 D1C 写题解,我觉得大概是想要在写题解数量上 dd ycx 吧,因为 ycx 到目前为止写了 ...

  10. fping (比ping更强大的ping工具)

    Fping程序类似于ping(ping是通过ICMP(网络控制信息协议InternetControl Message Protocol)协议回复请求以检测主机是否存在).Fping与ping不同的地方 ...