• ASP.Net Core解读请求处理管道


    一、请求处理管道

    前面分别介绍了服务器、中间件管道、托管服务和主机,那么请求管道具体是怎样的,它们之间有什么关系?正常来说,ASP.NET Core的请求处理管道由一个服务器和中间件管道构成。但对于面向传输层的服务器来说,它其实没有中间件的概念。不管服务器类型,当服务器接收到请求之后,会将该请求分发给一个处理器进行处理,对服务器而言,这个处理器就是一个HTTP应用,此应用通过IHttpApplication<TContext>接口来表示,如下是IHttpApplication<TContext> 的定义: 
    /// <summary>
    /// Represents an application.
    /// </summary>
    /// <typeparam name="TContext">The context associated with the application.</typeparam>
    public interface IHttpApplication<TContext> where TContext : notnull
    {
        /// <summary>
        /// Create a TContext given a collection of HTTP features.
        /// </summary>
        /// <param name="contextFeatures">A collection of HTTP features to be used for creating the TContext.</param>
        /// <returns>The created TContext.</returns>
        TContext CreateContext(IFeatureCollection contextFeatures);
    
        /// <summary>
        /// Asynchronously processes an TContext.
        /// </summary>
        /// <param name="context">The TContext that the operation will process.</param>
        Task ProcessRequestAsync(TContext context);
    
        /// <summary>
        /// Dispose a given TContext.
        /// </summary>
        /// <param name="context">The TContext to be disposed.</param>
        /// <param name="exception">The Exception thrown when processing did not complete successfully, otherwise null.</param>
        void DisposeContext(TContext context, Exception? exception);
    }

    由于服务器是通过IServer接口表示的,所以可以将ASP.NET Core框架的核心视为由IServer和IHttpApplication<TContext>对象组成的管道,即请求处理管道。

    我们可以根据需要注册不同类型的服务器,在默认情况下,IHttpApplication由HostingApplication实现,如下面源码所示:
     internal class HostingApplication : IHttpApplication<HostingApplication.Context>

    HostingApplication对象由指定的RequestDelegate对象来完成所有的请求处理工作,如下面源码所示:

    internal class HostingApplication : IHttpApplication<HostingApplication.Context>
        {
            private readonly RequestDelegate _application;
            private readonly IHttpContextFactory? _httpContextFactory;
            private readonly DefaultHttpContextFactory? _defaultHttpContextFactory;
            private readonly HostingApplicationDiagnostics _diagnostics;
    
            public HostingApplication(
                RequestDelegate application,
                ILogger logger,
                DiagnosticListener diagnosticSource,
                ActivitySource activitySource,
                DistributedContextPropagator propagator,
                IHttpContextFactory httpContextFactory)
            {
                _application = application;
                _diagnostics = new HostingApplicationDiagnostics(logger, diagnosticSource, activitySource, propagator);
                if (httpContextFactory is DefaultHttpContextFactory factory)
                {
                    _defaultHttpContextFactory = factory;
                }
                else
                {
                    _httpContextFactory = httpContextFactory;
                }
            }
    ..........
    // Execute the request public Task ProcessRequestAsync(Context context) { return _application(context.HttpContext!); }
         ............
    }

    而RequestDelegate就是中间件委托链,所有的这一切都被GenericWebHostService整合在一起。如下是GenericWebHostService类的StartAsync方法:

    public async Task StartAsync(CancellationToken cancellationToken)
    {
        HostingEventSource.Log.HostStart();
    
        var serverAddressesFeature = Server.Features.Get<IServerAddressesFeature>();
        var addresses = serverAddressesFeature?.Addresses;
        if (addresses != null && !addresses.IsReadOnly && addresses.Count == 0)
        {
            var urls = Configuration[WebHostDefaults.ServerUrlsKey];
            if (!string.IsNullOrEmpty(urls))
            {
                serverAddressesFeature!.PreferHostingUrls = WebHostUtilities.ParseBool(Configuration, WebHostDefaults.PreferHostingUrlsKey);
    
                foreach (var value in urls.Split(';', StringSplitOptions.RemoveEmptyEntries))
                {
                    addresses.Add(value);
                }
            }
        }
        //中间件委托链
        RequestDelegate? application = null;
    
        try
        {
            var configure = Options.ConfigureApplication;
    
            if (configure == null)
            {
                throw new InvalidOperationException($"No application configured. Please specify an application via IWebHostBuilder.UseStartup, IWebHostBuilder.Configure, or specifying the startup assembly via {nameof(WebHostDefaults.StartupAssemblyKey)} in the web host configuration.");
            }
    
            var builder = ApplicationBuilderFactory.CreateBuilder(Server.Features);
    
            foreach (var filter in StartupFilters.Reverse())
            {
                configure = filter.Configure(configure);
            }
    
            configure(builder);
    
            // Build the request pipeline
            application = builder.Build();
        }
        catch (Exception ex)
        {
            Logger.ApplicationError(ex);
    
            if (!Options.WebHostOptions.CaptureStartupErrors)
            {
                throw;
            }
         
            var showDetailedErrors = HostingEnvironment.IsDevelopment() || Options.WebHostOptions.DetailedErrors;
    
            application = ErrorPageBuilder.BuildErrorPageApplication(HostingEnvironment.ContentRootFileProvider, Logger, showDetailedErrors, ex);
        }
        //创建HostingApplication对象,关联中间件委托链
        var httpApplication = new HostingApplication(application, Logger, DiagnosticListener, ActivitySource, Propagator, HttpContextFactory);
    
        await Server.StartAsync(httpApplication, cancellationToken);
    
        if (addresses != null)
        {
            foreach (var address in addresses)
            {
                Log.ListeningOnAddress(LifetimeLogger, address);
            }
        }
    
        if (Logger.IsEnabled(LogLevel.Debug))
        {
            foreach (var assembly in Options.WebHostOptions.GetFinalHostingStartupAssemblies())
            {
                Log.StartupAssemblyLoaded(Logger, assembly);
            }
        }
    
        if (Options.HostingStartupExceptions != null)
        {
            foreach (var exception in Options.HostingStartupExceptions.InnerExceptions)
            {
                Logger.HostingStartupAssemblyError(exception);
            }
        }
    }

    而GenericWebHostService是Asp.net Core的托管服务。 

  • 相关阅读:
    How Do I Enable Remote Access To MySQL Database Server?
    超越MySQL:三个流行MySQL分支的对比
    自动杀死UNIX僵死的进程 红联Linux门户 中国领先的Linux技术网站 网站导航 Linux企业应用 UniX技术文章
    公司简介_关于我们_知阅网——免费借阅,送还上门
    超越MySQL:三个流行MySQL分支的对比
    reviewboard升级
    Implementing Regular Expressions
    乐维UP IT领域的社交问答
    Price Comparison Script
    Kill the undesired UNIX processes in one go
  • 原文地址:https://www.cnblogs.com/qtiger/p/15386971.html
Copyright © 2020-2023  润新知