zoukankan      html  css  js  c++  java
  • 你必须知道ASP.NET知识------从IIS到httpmodule(第一篇)

    一、写在前面

      最近有时间,顺便将这系列洗完,接着上文:IIS各个版本知识总结

      这篇文章原本计划写到HttpHandler为止,但限于篇幅就写到httpmodule

      本文有不足之处,求指正,希望我能将它分析透彻.

    二、回顾--我们还是从IIS说起

      从上文(IIS各个版本知识总结)可以很清楚地意思到经典模式和集成模式的区别:集成模式是一个伟大的改进,让IIS集成了.NET功能(不在依靠之前IIS版本的aspnet_ISPAI.DLL).

      所以,对于我们所开发的ASP.NET程序而言,这些完全不必知道;但运行环境自己必须知道发生了什么情况.

      所以两者的主要区别在于:从w3wp.exe初始化httpapplication这一阶段.

    三、看看经典模式(包括IIS6)的过程

    IIS的处理进程到w3wp这一阶段后,iis会通过com的方式创建AppManagerAppDomainFactory对象,AppManagerAppDomainFactory会

    在Create方法中创建ISAPIRuntime对象.代码如下.

    using System;
    using System.Globalization;
    using System.IO;
    using System.Runtime.InteropServices;
    using System.Runtime.Remoting;
    using System.Security.Permissions;
    using System.Web.Util;
    namespace System.Web.Hosting
    {
        [SecurityPermission(SecurityAction.LinkDemand, Unrestricted = true)]
        public sealed class AppManagerAppDomainFactory : IAppManagerAppDomainFactory
        {
            private ApplicationManager _appManager;
            public AppManagerAppDomainFactory()
            {
                this._appManager = ApplicationManager.GetApplicationManager();
                this._appManager.Open();
            }
            [return: MarshalAs(UnmanagedType.Interface)]
            public object Create(string appId, string appPath)
            {
                object result;
                try
                {
                    if (appPath[0] == '.')
                    {
                        FileInfo fileInfo = new FileInfo(appPath);
                        appPath = fileInfo.FullName;
                    }
                    if (!StringUtil.StringEndsWith(appPath, '\'))
                    {
                        appPath += "\";
                    }
                    ISAPIApplicationHost appHost = new ISAPIApplicationHost(appId, appPath, false);
                    ISAPIRuntime iSAPIRuntime = (ISAPIRuntime)this._appManager.CreateObjectInternal(appId, typeof(ISAPIRuntime), appHost, false, null);
                    iSAPIRuntime.StartProcessing();
                    result = new ObjectHandle(iSAPIRuntime);
                }
                catch (Exception)
                {
                    throw;
                }
                return result;
            }
            public void Stop()
            {
                this._appManager.Close();
            }
            internal static string ConstructSimpleAppName(string virtPath)
            {
                if (virtPath.Length <= 1)
                {
                    return "root";
                }
                return virtPath.Substring(1).ToLower(CultureInfo.InvariantCulture).Replace('/', '_');
            }
        }
    }
    View Code

    最终将流程交由ProcessRequest处理,代码如下.接着如红色处,由HttpRuntime.ProcessRequestNoDemand(iSAPIWorkerRequest)处理

    public int ProcessRequest(IntPtr ecb, int iWRType)
            {
                IntPtr intPtr = IntPtr.Zero;
                if (iWRType == 2)
                {
                    intPtr = ecb;
                    ecb = UnsafeNativeMethods.GetEcb(intPtr);
                }
                ISAPIWorkerRequest iSAPIWorkerRequest = null;
                int result;
                try
                {
                    bool useOOP = iWRType == 1;
             //注:internal abstract class ISAPIWorkerRequest : HttpWorkerRequest iSAPIWorkerRequest
    = ISAPIWorkerRequest.CreateWorkerRequest(ecb, useOOP); iSAPIWorkerRequest.Initialize(); string appPathTranslated = iSAPIWorkerRequest.GetAppPathTranslated(); string appDomainAppPathInternal = HttpRuntime.AppDomainAppPathInternal; if (appDomainAppPathInternal == null || StringUtil.EqualsIgnoreCase(appPathTranslated, appDomainAppPathInternal)) { HttpRuntime.ProcessRequestNoDemand(iSAPIWorkerRequest); result = 0; } else { HttpRuntime.ShutdownAppDomain(ApplicationShutdownReason.PhysicalApplicationPathChanged, SR.GetString("Hosting_Phys_Path_Changed", new object[] { appDomainAppPathInternal, appPathTranslated })); result = 1; } } catch (Exception ex) { //.................................. } return result; }

    ISAPIWorkerRequest是对请求信息的一层C++封装.

    四、HttpRuntime中发生的事情

    接着上面 HttpRuntime.ProcessRequestNoDemand(iSAPIWorkerRequest);

    internal static void ProcessRequestNoDemand(HttpWorkerRequest wr)
            {
                RequestQueue requestQueue = HttpRuntime._theRuntime._requestQueue;
                wr.UpdateInitialCounters();
                if (requestQueue != null)
                {
                    wr = requestQueue.GetRequestToExecute(wr);
                }
                if (wr != null)
                {
                    HttpRuntime.CalculateWaitTimeAndUpdatePerfCounter(wr);
                    wr.ResetStartTime();
                    HttpRuntime.ProcessRequestNow(wr);
                }
            }
            internal static void ProcessRequestNow(HttpWorkerRequest wr)
            {
                HttpRuntime._theRuntime.ProcessRequestInternal(wr);
            }
    View Code

    我们看到方法进入

    private void ProcessRequestInternal(HttpWorkerRequest wr)

    其结构如下

    private void ProcessRequestInternal(HttpWorkerRequest wr)
            {
                Interlocked.Increment(ref this._activeRequestCount);
                if (this._disposingHttpRuntime)
                {
                    try
                    {
                        wr.SendStatus(503, "Server Too Busy");
                        wr.SendKnownResponseHeader(12, "text/html; charset=utf-8");
                        byte[] bytes = Encoding.ASCII.GetBytes("<html><body>Server Too Busy</body></html>");
                        wr.SendResponseFromMemory(bytes, bytes.Length);
                        wr.FlushResponse(true);
                        wr.EndOfRequest();
                    }
                    finally
                    {
                        Interlocked.Decrement(ref this._activeRequestCount);
                    }
                    return;
                }
                HttpContext httpContext;
                try
                {
                    httpContext = new HttpContext(wr, false);
                }
                catch
                {
                    try
                    {
                        wr.SendStatus(400, "Bad Request");
                        wr.SendKnownResponseHeader(12, "text/html; charset=utf-8");
                        byte[] bytes2 = Encoding.ASCII.GetBytes("<html><body>Bad Request</body></html>");
                        wr.SendResponseFromMemory(bytes2, bytes2.Length);
                        wr.FlushResponse(true);
                        wr.EndOfRequest();
                        return;
                    }
                    finally
                    {
                        Interlocked.Decrement(ref this._activeRequestCount);
                    }
                }
                wr.SetEndOfSendNotification(this._asyncEndOfSendCallback, httpContext);
                HostingEnvironment.IncrementBusyCount();
                try
                {
                    try
                    {
                        this.EnsureFirstRequestInit(httpContext);
                    }
                    catch
                    {
                        if (!httpContext.Request.IsDebuggingRequest)
                        {
                            throw;
                        }
                    }
                    httpContext.Response.InitResponseWriter();
                    IHttpHandler applicationInstance = HttpApplicationFactory.GetApplicationInstance(httpContext);
                    if (applicationInstance == null)
                    {
                        throw new HttpException(SR.GetString("Unable_create_app_object"));
                    }
                    if (EtwTrace.IsTraceEnabled(5, 1))
                    {
                        EtwTrace.Trace(EtwTraceType.ETW_TYPE_START_HANDLER, httpContext.WorkerRequest, applicationInstance.GetType().FullName, "Start");
                    }
                    if (applicationInstance is IHttpAsyncHandler)
                    {
                        IHttpAsyncHandler httpAsyncHandler = (IHttpAsyncHandler)applicationInstance;
                        httpContext.AsyncAppHandler = httpAsyncHandler;
                        httpAsyncHandler.BeginProcessRequest(httpContext, this._handlerCompletionCallback, httpContext);
                    }
                    else
                    {
                        applicationInstance.ProcessRequest(httpContext);
                        this.FinishRequest(httpContext.WorkerRequest, httpContext, null);
                    }
                }
                catch (Exception e)
                {
                    httpContext.Response.InitResponseWriter();
                    this.FinishRequest(wr, httpContext, e);
                }
            }
    View Code

    传说中的HttpApplication就是在这里初始化的.

    IHttpHandler applicationInstance = HttpApplicationFactory.GetApplicationInstance(httpContext);//因为HttpApplication实现了IHttpHandler接口

    最终通过BuildManager.GetGlobalAsaxType()获取对应的Global.asax所告知的类型进行HttpApplication的实例化.

     

    internal static IHttpHandler GetApplicationInstance(HttpContext context)
            {
                if (HttpApplicationFactory._customApplication != null)
                {
                    return HttpApplicationFactory._customApplication;
                }
                if (context.Request.IsDebuggingRequest)
                {
                    return new HttpDebugHandler();
                }
                HttpApplicationFactory._theApplicationFactory.EnsureInited();
                HttpApplicationFactory._theApplicationFactory.EnsureAppStartCalled(context);
                return HttpApplicationFactory._theApplicationFactory.GetNormalApplicationInstance(context);
            }
    private HttpApplication GetNormalApplicationInstance(HttpContext context)
            {
                HttpApplication httpApplication = null;
                lock (this._freeList)
                {
                    if (this._numFreeAppInstances > 0)
                    {
                        httpApplication = (HttpApplication)this._freeList.Pop();
                        this._numFreeAppInstances--;
                        if (this._numFreeAppInstances < this._minFreeAppInstances)
                        {
                            this._minFreeAppInstances = this._numFreeAppInstances;
                        }
                    }
                }
                if (httpApplication == null)
                {
                    httpApplication = (HttpApplication)HttpRuntime.CreateNonPublicInstance(this._theApplicationType);
                    using (new ApplicationImpersonationContext())
                    {
                        httpApplication.InitInternal(context, this._state, this._eventHandlerMethods);//注意:这里是主战场
                    }
                }
                if (AppSettings.UseTaskFriendlySynchronizationContext)
                {
                    httpApplication.ApplicationInstanceConsumersCounter = new CountdownTask(1);
                    httpApplication.ApplicationInstanceConsumersCounter.Task.ContinueWith(delegate(Task _, object o)
                    {
                        HttpApplicationFactory.RecycleApplicationInstance((HttpApplication)o);
                    }, httpApplication, TaskContinuationOptions.ExecuteSynchronously);
                }
                return httpApplication;
            }

    五、主战场中的发生的事情

    internal void InitInternal(HttpContext context, HttpApplicationState state, MethodInfo[] handlers)
            {
                this._state = state;
                PerfCounters.IncrementCounter(AppPerfCounter.PIPELINES);
                try
                {
                    try
                    {
                        this._initContext = context;
                        this._initContext.ApplicationInstance = this;
                        context.ConfigurationPath = context.Request.ApplicationPathObject;
                        using (new DisposableHttpContextWrapper(context))
                        {
                            if (HttpRuntime.UseIntegratedPipeline)
                            {
                                try
                                {
                                    context.HideRequestResponse = true;
                                    this._hideRequestResponse = true;
                                    this.InitIntegratedModules();
                                    goto IL_6B;
                                }
                                finally
                                {
                                    context.HideRequestResponse = false;
                                    this._hideRequestResponse = false;
                                }
                            }
                            this.InitModules();
                            IL_6B:
                            if (handlers != null)
                            {
                                this.HookupEventHandlersForApplicationAndModules(handlers);
                            }
                            this._context = context;
                            if (HttpRuntime.UseIntegratedPipeline && this._context != null)
                            {
                                this._context.HideRequestResponse = true;
                            }
                            this._hideRequestResponse = true;
                            try
                            {
                                this.Init();
                            }
                            catch (Exception error)
                            {
                                this.RecordError(error);
                            }
                        }
                        if (HttpRuntime.UseIntegratedPipeline && this._context != null)
                        {
                            this._context.HideRequestResponse = false;
                        }
                        this._hideRequestResponse = false;
                        this._context = null;
                        this._resumeStepsWaitCallback = new WaitCallback(this.ResumeStepsWaitCallback);
                        if (HttpRuntime.UseIntegratedPipeline)
                        {
                            this._stepManager = new HttpApplication.PipelineStepManager(this);
                        }
                        else
                        {
                            this._stepManager = new HttpApplication.ApplicationStepManager(this);
                        }
                        this._stepManager.BuildSteps(this._resumeStepsWaitCallback);
                    }
                    finally
                    {
                        this._initInternalCompleted = true;
                        context.ConfigurationPath = null;
                        this._initContext.ApplicationInstance = null;
                        this._initContext = null;
                    }
                }
                catch
                {
                    throw;
                }
            }

     待续................................

    六、求关注、求推荐

            兄台给点鼓励吧 O(∩_∩)O~,你的鼓励是我继续写好这一系列的理由

  • 相关阅读:
    Spring攻略学习笔记(3.00)AOP核心概念和术语
    zoj 3494
    第43周星期五
    findBugs学习小结
    第42周星期日
    Cookie知识小结
    第42周星期三
    第42周星期六
    第43周星期四小结
    第43周星期二
  • 原文地址:https://www.cnblogs.com/humble/p/3919240.html
Copyright © 2011-2022 走看看