一、请求处理管道
前面分别介绍了服务器、中间件管道、托管服务和主机,那么请求管道具体是怎样的,它们之间有什么关系?正常来说,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的托管服务。