大多数人认为ASP.NET仅仅只是页面——使用模板来创建HTML页面然后返回给浏览器。但是这仅仅只是ASP.NET使用HTTP管道模型处理WEB程序很小的一方面。管道模型是类似于Web Services的一种在服务器端处理ASP.NET页面的框架技术。作为一名高级的ASP.NET的开发者,你必须清楚管道模型是如何工作的。这篇文章就是解释和阐述HTTP管道模型是如何处理HTTP请求的。

一、管道对象模型

在System.Web的命名空间中处理HTTP的请求主要使用管道模型。一般的管道模型的结构如图-1。在管道模型开始运行前,HTTP的请求首先被传到HttpRuntime类的一个实例中,然后这个HttpRuntime的对象开始检查请求并找出这个请求被发送到的那个应用程序(在管道程序看来,一个虚拟目录就是一个应用程序)。然后管道模型就使用一个HttpApplicationFactory对象来找出或者创建一个HttpApplication对象来处理这个请求,一个HttpApplication可以包含一系列HTTP module对象(派生自IHttpModule接口)。HTTP modules作为一个过滤器可以在HTTP请求和响应信息穿过管道模型时检查和修改这些信息的内容。然后HttpApplication对象就使用HTTP handler factory来找出或产生一个HTTP handler对象。HTTP handlers是HTTP通信的最后一步,它主要用于处理请求信息(request)和响应信息(response)。注:HTTP handlers和 handler factory分别派生自IHttpHandler接口和IHttpHandlerFactory接口。

图-1

一个HttpApplication包括它的modules、handler在同一时刻只能处理一个Request请求。如果多重request请求同时到达一个相同的application时,多重HttpApplication对象将会被使用。

管道模型使用一个HttpContext对象去描述声明每一个成对的request/response信息。这个对象在HttpApplicaiton和handler之间来回传递。每一个module也能访问当前的HttpContext。HttpContext对象通过属性来描述声明HTTP的request和response信息(分别创建HttpRequest类和HttpResponse类的对象);同样,HttpContext对象也能通过属性来描述声明安全信息和每一个call、session和application。-2展示了部分HttpContext类常用的属性。

ASP.NET的HTTP管道模型是可扩展的,你可以实现自己的HTTP module、handler以及handler factory。你也可以直接继承HttpApplication类。

属性名

描述

Application

每一个application的request信息

Application Instance

正在处理request请求的Application对象

Cache

每一个application的缓存信息

Handler

正在处理request请求的Handler对象

Items

每一个request请求信息

Request

HTTP request 信息

Response

HTTP response 信息

Server

Utility functions

Session

Per-user cross-request state

User

User information

图-2:HttpContext类的常用属性

二、管道处理模型

ASP.NET的HTTP管道程序运行在IIS上来接收传递到进程中的request请求(被完整地传送到其他的web服务器上)。当IIS接收到一个HTTP的request请求时,它首先会通过目标URL检查文件的扩展名,如果文件的名被可执行代码关联,IIS就会调用这些代码来处理request请求。文件的扩展名被映射成可执行代码存储在IIS的metabase标记中。当ASP.NET被安装后,它会通过一个动态链接库aspnet_isapi.dll将各种不同的文件扩展名添加到matabase标记中,包括.apx和.asmx。

当IIS收到一个某一个页面文件发送的HTTP request请求时,它会调用aspnet_isapi.dll中的代码:使用一个命名管道将IIS服务器上的inetinfo.exe发送来的request请求转发到ASP.NET工作进程的一个实例:aspnet_wp.exe中。(在Windows Server 2003中, IIS 6.0kernel-mode模式的HTTP listener, 允许 request请求不通过inetinfo.exe而直接从操作系统转发到工作进程。)工作进程使用一个HttpRuntime类的实例来处理request请求。图-3 展示了完整的机制。

图-3

HTTP管道程序在工作进程的实例中处理request请求。默认地,在某一时刻仅仅只能有一个工作进程工作(如果你的web服务器有多个CPU,你可以配置管道程序使用多个工作进程),这是一个在本地IIS上很重要的一个改变,它使用不同的工作进程主要为了隔离不同的application程序。同时管道程序的各个工作进程也完全地被AppDomain所隔离,你可以将AppDomain看作是进程中的一个子进程。管道程序向一个AppDomain中的所有虚拟目录发送HTTP request请求。换句话说,每一个虚拟目录被作为一个单独的应用程序对待。这还有另外一个本地IIS值得注意的改变就是允许多个虚拟目录成为同一个application的一部分。
 ASP.NET支持基于很多标准的循环工作进程,这些标准包括空闲时间、requests serviced的数量、requests队列的数量以及物理内存的耗费量。全局.NET配置文件和machine配置文件初始化这些数值(好象processModel的元素)。当一个aspnet_wp.exe的实例 crosses one of these thresholds, aspnet_isapi.dll会运行一个新的工作进程并开始发送request请求。旧的实例在它处理完request请求后会自动终止。循环工作进程会提升可靠性通过在这些进程耗尽资源之前杀死它们。

三、HTTP Handlers

HTTP handlers 是一个继承自IHttpHandler接口的简单类,以下是该类的详细代码:

interface IHttpHandler

{

// called to process request and generate response

void ProcessRequest(HttpContext ctx);

// called to see if handler can be pooled

bool IsReuseable { get; }

}

Handlers也可以继承自IHttpAsyncHandler接口,如果想要它们支持异步调用。

HttpApplicaiton对象会调用ProcessRequest方法,通过handler来处理当前的HTTP请求和产生response响应。在此期间IsReuseable属性会被访问为类测定hanlder是否可以被再使用。

图-4的代码实现了一个简单的可以重用的HTTP句柄,它可以响应所有的request请求并返回当前的时间在一个XML标记中。你也可以使用使用HttpContext对象的response属性来设置response信息的MIME属性从而输出自己的内容。using System;
using System.Web;
 
namespace Pipeline
{
 
 public class TimeHandler : IHttpHandler
 {
    void ProcessRequest(HttpContext ctx)
    {
      ctx.Response.ContentType = "text/xml";
      ctx.Response.Write("<now>");
      ctx.Response.Write(
                   DateTime.Now.ToString());
      ctx.Response.Write("</now>");
    }
    bool IsReuseable { get { return true; } }
 }
}

图-4:TimeHandler

当HTTP handler类被实现时,它一定是被配置好的。配置会分为三个阶段:第一、你应该将编译好的代码放到ASP.NET工作进程能够找到的地方。一般地,已编译好的.NET文件(一般是dll文件)应该位于web服务器的虚拟目录下的bin文件夹中或位于全局编译缓存中(GAC)。

第二步:在HTTP request请求到来时,你应该让HTTP的管道程序执行你的代码。你可以通过在你虚拟目录下的web.config文件中去添加<httpHandlers>标签。如下:

<configuration>

<system.web>

<httpHandlers>

<add verb="GET" path="*.time"

type="Pipeline.TimeHandler,

Pipeline"

/>

</httpHandlers>

</system.web>

</configuration>

以上的代码可以作为附加的信息添加到.config的配置文件中。例如,这个web.config文件会告诉asp.net的HTTP管道程序处理所有.time文件的GET请求通过调用编译文件中的Pipeline.TimeHandler类。

最后,这些.time文件的request请求会被IIS转发到aspnet_isapi.dll,以便这些请求可以被管道程序第一时间处理。而且这些request请求也会在IIS的metabase中添加一个新的文件mapping映射。不过还有更简单的方式,就是直接使用IIS管理台将虚拟目录的文件扩展名映射到Application的配置对话框中。如图-5:

图-5

除了实现已有的客户端handler外,你也可以写自己的handler factoriey。一个handler factoriey就是一个实现了IHttpHandlerFactory的类。Handler factiory的配置方法和普通handlers一样,唯一不同的是原先web.config文件中的handler类都将被factory类所代替。

四、标准Handlers

    一些高级的ASP.NET技术,例如pages和Web Services都是通过顶层HTTP handler直接创建的。以下是通过.config文件来配置<httpHandlers>部分:

<httpHandlers> entries:

<httpHandlers>

<add verb="*" path="*.ashx"

type="System.Web.UI.SimpleHandlerFactory"

/>

<add verb="*" path="*.aspx"

type="System.Web.UI.PageHandlerFactory"

/>

<add verb="*" path="*.asmx"

type="System.Web.Services.Protocols.

WebServiceHandlerFactory ... "

/>

</httpHandlers>

第一个实体映射扩展名为.ashx的文件到SimpleHandlerFactory类,使得一个HTTP handler factory知道如何从.ashx源文件中安装、编译和执行一个IHttpHandler。然后结果对象就可以被HTTP管道程序直接使用。

图-6展示了使用.ashx文件重写的一个TimeHandler例子。@WebHandler部分告诉SimpleHandlerFactory Http handler类的名字在源代码编译后。这么做最大的好处就在它的配置非常简单:你只需要将所有的.ashx文件拷贝到虚拟目录下,而不需要再创建或修改web.config文件或在.NET安装完后再更新IIS。

<%@ WebHandler language="C#"
    class="Pipeline.TimeHandler" %>
 
using System;
using System.Web;
 
namespace Pipeline
{
 
 public class TimeHandler : IHttpHandler
 {
    void ProcessRequest(HttpContext ctx)
    {
      // set response message MIME type
      ctx.Response.ContentType = "text/xml";
      // write response message body
      ctx.Response.Write("<now>");
      ctx.Response.Write(
                   DateTime.Now.ToString());
      ctx.Response.Write("</now>");
    }
    bool IsReuseable { get { return true; } }
 }
}

图-6

第二个<httpHandlers>部分的实体将.aspx文件扩展名映射到PageHandlerFactory类,主要为了让HTTP handler factory知道如何将.aspx的源代码编译成一个System.Web.UI.Page-derived类。这个Page类实现了IHttpHandler借口,因此最终对象可以被HTTP管道程序直接使用。

第三个实体将.asmx的扩展名映射到WebServiceHandlerFactory类,这么做主要为了让一个HTTP handler factory知道如何将一个.asmx文件中的源代码编译并实例化。然后它会绑定一个标准的HTTP handler(默认的为SyncSessionlessHandler)实例并使用反射机制将SOAP信息转化成方法的调用参数。最后,最终对象就可以被HTTP管道程序直接使用了。
   这里需要值得注意的是PageHandlerFactory、WebServiceHandlerFactory和SimpleHandlerFactory类并不能在每一个request请求上都编译.aspx、.asmx和.ashx文件。作为替代,这些编译好的代码会被缓存在ASP.NET安装目录下的临时文件中。并且当源代码改变时,这些代码仅仅只会被编译一次。

五、HTTP Modules

    HTTP handlers是HTTP通信的最终部分。Handler类的实例专门用来接收HTTP请求并产生response响应。HTTP modules作为过滤器在request和response信息穿过管道程序时处理它们(可以是检查并修改这些信息的内容)。管道程序可以用这些HTTP modules特别安全地实现自己的底层处理程序。

HTTP modules 是实现IHttpModule接口的简单类:

interface IHttpModule

{

// called to attach module to app events

void Init(HttpApplication app);

// called to clean up

void Dispose()

}

当module被第一次创建时,Init方法会被HttpApplication对象调用,它可以通过HttpApplication对象将一个或多个事件handlers绑定到事件上。

图-7的代码展示了一个HTTP module如何处理HttpApplication对象的BeginRequest和EndRequest事件。在这个例子中,Init方法使用了常见的.NET技术将module的OnBeginRequst和OnEndRequest作为事件句柄绑定到HttpApplication对象上。OnBeginRequest主要作用是获取存储当前时间并将时间存放到变量start中。而OnEndRequest主要作用是计算OnBeginRequest和OnEndRequest之间的运行时间差并将这段时间添加到客户端HTTP header中。

OnEndRequest方法的最大优势在于第一个参数实际上传递的module绑定的HttpApplication对象。并且当前的信息会做为一个HttpApplication对象的属性(Http-Context)被OnEndRequest方法使用。

using System;
using System.Web;
 
namespace Pipeline
{
 
 public class ElapsedTimeModule : IHttpModule
 {
    DateTime start;
    public void Init(HttpApplication app)
    {
      // register for pipeline events
      app.BeginRequest +=
          new EventHandler(this.OnBeginRequest);
      app.EndRequest +=
          new EventHandler(this.OnEndRequest);
    }
    public void Dispose() {}
 
    public void OnBeginRequest(object o,
                               EventArgs args)
    {
      // record time when request started
      start = DateTime.Now;
    }
 
    public void OnEndRequest(object o,
                             EventArgs args)
    {
      // measure elapsed time
      TimeSpan elapsed =
              DateTime.Now - start;
 
      // get access to app and context
      HttpApplication app =
              (HttpApplication) o;
      HttpContext ctx = app.Context;
 
      // add custom header to HTTP response
      ctx.Response.AppendHeader(
                   "ElapsedTime",
                   elapsed.ToString());
    }
 }
}

图-7

在一个HTTP module类被实现和使用之间,必须对它做一定的配置。配置的步骤包括两步。首先你应该将编译好的module代码放到web服务器上的站点目录下的bin文件夹中以至于ASP.NET的工作进程能够找到它。
    然后你应该在你的web.config文件中添加<httpModules>部分,如下:

<configuration>

<system.web>

<httpModules>

<add

name="Elapsed"

type="Pipeline.ElapsedTimeModule, Pipeline"

/>

</httpModules>

</system.web>

</configuration>

这个例子中,web.config文件会告诉ASP.NET的HTTP管道程序将Pipeline.ElapsedTimeModule绑定到每一个HttpApplication对象用来处理这个虚拟目录下的service请求。

ASP.NET使用管道模型(PipleLines)处理HTTP请求相关推荐

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

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

  2. ASP.NET Core轻松入门之Middleware管道模型

    Middleware指的是微软的的asp.net core的管道模型.其原理可以用微软官方的下图展示: 原理如上图,随着Request的发起,HttpContext会经历多个管道处理(图中的箭头游走方 ...

  3. ASP.NET Core 管道再探

    几乎任何服务器端处理环境都有自己的直通组件管道,用于检查.重路由或修改传入请求和传出响应.经典 ASP.NET 围绕 HTTP 模块理念进行排列,而 ASP.NET Core 采用基于中间件组件的更现 ...

  4. 机器学习管道模型_使用连续机器学习来运行您的ml管道

    机器学习管道模型 Vaithy NarayananVaithy Narayanan Follow跟随 Jul 15 7月15 使用连续机器学习来运行ML管道 (Using Continuous Mac ...

  5. 调用管道模型:高敏感、高性能

    调用管道模型 高敏感.高性能 把一个完整的调用链(例如一个request-response)一个管道,url入口处以及和数据库打交道处看作是管道的两端.在这个管道里,会存在许许多多的条件判断. 经常会 ...

  6. 通过重建Hosting系统理解HTTP请求在ASP.NET Core管道中的处理流程[上]:采用管道处理请求...

    之所以称ASP.NET Core是一个Web开发平台,而不是一个单纯的开发框架,源于它具有一个极具扩展性的请求处理管道,我们可以通过对这个管道的定制来满足各种场景下的HTTP处理需求.ASP. NET ...

  7. Asp.Net Mvc之模型注解

    Asp.Net Mvc之模型注解 正文: 命名空间: using System.ComponentModel;      using System.ComponentModel.DataAnnotat ...

  8. ASP.NET Core管道深度剖析[共4篇]

    在<管道是如何处理HTTP请求的?>中,我们对ASP.NET Core的请求处理管道的构成以及它对请求的处理流程进行了详细介绍,接下来我们需要了解的是这样一个管道是如何被构建起来的.这样一 ...

  9. ASP.NET Core管道深度剖析(4):管道是如何建立起来的?

    在<管道是如何处理HTTP请求的?>中,我们对ASP.NET Core的请求处理管道的构成以及它对请求的处理流程进行了详细介绍,接下来我们需要了解的是这样一个管道是如何被构建起来的.这样一 ...

最新文章

  1. 零基础掌握极大似然估计
  2. Ubuntu12.04下解决sudo apt-get update警告Duplicate sources.list entry
  3. deepl真的有取代一般翻译的能力,这吞吐量和稳定性...亲测有效
  4. 美国会不会禁用python_美国要是禁用Windows系统,该怎么办?国人会不会选择换系统呢?...
  5. HTML5 Web Storage API
  6. k8s核心技术-集群安全机制(概述)---K8S_Google工作笔记0038
  7. 微信小程序调查报告(二)-账号注册篇
  8. zepto 清除html,Zepto的使用
  9. Beaver‘s triple(乘法三元组)-秘密共享的乘法计算
  10. Managing Supply and Demand Balance Through Machine Learning-笔记
  11. 公主同盟第3关(GBA)(难) 奥兰多西部
  12. [AHK]定时运行脚本
  13. r语言进行自然语言处理_开始进行自然语言处理
  14. java实现pdf转为word
  15. 手机通讯录 客户端/服务器数据同步方案设计
  16. 简单聊一聊Python工程师任职要求及未来发展方向
  17. 使用计算机录制声音10,Win10电脑麦克风无法录音怎么解决 win10麦克风声音无法输入的解决方法...
  18. opentsdb 简易生动讲解
  19. 标签超出图像控件c语言,VC++标签控件之图像标签控件
  20. 对动量守恒定律的质疑

热门文章

  1. kafka operation
  2. 实现进程守护 脚本命令
  3. 剑客决斗(NYOJ 110)
  4. 进阶学习js中的执行上下文
  5. oracle中DECODE与CASE的用法区别
  6. UIImageView 圆角
  7. 炎炎夏日需要一个清凉的地 - 自制水冷系统(十一 指尖的思绪之程序篇)
  8. WinAPI: SetTextColor - 设置设备环境的文本颜色
  9. 【Breadth-first Search 】785. Is Graph Bipartite?
  10. [剑指offer][JAVA][面试题第13题][机器人的运动][DFS][BFS]