在第一部分中,我们探索了 ASP.NET核心请求和响应管道的总体结构。现在,我们将深入到基础层:服务器和主机基础设施。这是一切事物开始的地方,你的应用程序进入生命,原始网络请求转化为结构化 HttpContext 流经中器件管道的物体
了解此层至关重要, 因为它控制您的应用程序如何启动, 如何配置, 以及如何与隐藏的网络服务器互动 。 无论您是在制作、 优化性能或配置 HTTPS , 主机层是解决这些关切的地方 。
注意:这是我在AI的实验的一部分 / 一种花费1000美元 Clude 代码 Web 信用的方法。 我给这个文件,我的理解,我不得不提出这样的问题。这很有趣,填补了一个我还没有看到的地方填补的空白。
ASP.NET核心将应用程序托管和网络服务的关切分为两个不同的层面:
此分隔提供了灵活性: 您可以互换服务器( Kestrel、 HTTP.sys、 IIS 整合) 而不修改您的应用程序代码, 或者在不同的主机环境运行您的应用程序( 默认程序、 Windows Service、 系统守护程序) , 而不修改服务器配置 。
在ASP.NET核心6和后来的ASP.NET核心6中,主机模式简化为: WebApplication 和 WebApplicationBuilder替换旧的 IHostBuilder 和 IWebHostBuilder 具有更精简的 API 模式。
// Modern ASP.NET Core 8 application
var builder = WebApplication.CreateBuilder(args);
// Configure services during the build phase
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// Build the application
var app = builder.Build();
// Configure middleware after building
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
// Start the server and begin processing requests
app.Run();
当你打电话来时 WebApplication.CreateBuilder(args),在下列情况下发生大量初始化:
// Simplified view of what CreateBuilder does internally
public static WebApplicationBuilder CreateBuilder(string[] args)
{
var builder = new WebApplicationBuilder();
// 1. Configure the host defaults
// - Content root path (Directory.GetCurrentDirectory())
// - Load appsettings.json and appsettings.{Environment}.json
// - Load environment variables
// - Load command-line arguments
// - Setup default logging providers (Console, Debug, EventSource, EventLog on Windows)
// 2. Configure Kestrel as the default web server
builder.WebHost.UseKestrel();
// 3. Setup dependency injection container
// - Creates the IServiceCollection
// - Registers core services
// 4. Configure the environment
// - Sets ASPNETCORE_ENVIRONMENT (Development, Staging, Production)
// - Determines if running in development mode
// 5. Setup configuration system
// - Creates the IConfiguration hierarchy
// - Combines all configuration sources
return builder;
}
您对主机配置方式拥有广泛的控制 :
var builder = WebApplication.CreateBuilder(args);
// Configure Kestrel server options
builder.WebHost.ConfigureKestrel(serverOptions =>
{
serverOptions.Limits.MaxConcurrentConnections = 100;
serverOptions.Limits.MaxRequestBodySize = 10 * 1024 * 1024; // 10 MB
serverOptions.Limits.MinRequestBodyDataRate = new MinDataRate(
bytesPerSecond: 100,
gracePeriod: TimeSpan.FromSeconds(10)
);
});
// Add additional configuration sources
builder.Configuration.AddJsonFile("customsettings.json", optional: true);
builder.Configuration.AddEnvironmentVariables(prefix: "MYAPP_");
// Configure logging
builder.Logging.ClearProviders(); // Remove defaults
builder.Logging.AddConsole();
builder.Logging.AddDebug();
builder.Logging.SetMinimumLevel(LogLevel.Warning);
// Change the content root and web root
builder.Environment.ContentRootPath = "/custom/path";
builder.Environment.WebRootPath = "/custom/wwwroot";
var app = builder.Build();
辅助注射容器是在主机初始化期间建造的。在此注册的服务在您的申请中提供:
var builder = WebApplication.CreateBuilder(args);
// Singleton: One instance for the application lifetime
builder.Services.AddSingleton<IMyService, MyService>();
// Scoped: One instance per request
builder.Services.AddScoped<IRequestService, RequestService>();
// Transient: New instance every time it's requested
builder.Services.AddTransient<ITransientService, TransientService>();
// Configure options pattern
builder.Services.Configure<MyOptions>(
builder.Configuration.GetSection("MyOptions")
);
// Access configuration directly during service registration
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<MyDbContext>(options =>
options.UseSqlServer(connectionString)
);
var app = builder.Build();
ASP.NET核心提供了一个复杂的配置系统,将多种来源合并在一起:
var builder = WebApplication.CreateBuilder(args);
// Configuration is loaded in this order (later sources override earlier):
// 1. appsettings.json
// 2. appsettings.{Environment}.json
// 3. User secrets (in Development environment only)
// 4. Environment variables
// 5. Command-line arguments
// Access configuration
var mySetting = builder.Configuration["MySection:MySetting"];
var myValue = builder.Configuration.GetValue<int>("MySection:MyValue");
// Check environment
if (builder.Environment.IsDevelopment())
{
// Development-specific configuration
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
}
if (builder.Environment.IsProduction())
{
// Production-specific configuration
builder.Configuration.AddAzureKeyVault(/* ... */);
}
var app = builder.Build();
Kestrel 是 ASP.NET Core 的跨平台网络服务器。 它快速、轻量级且有能力处理生产工作量。 了解 Kestrel 的能力有助于您优化应用程序的性能和安全性 。
flowchart TD cc[Client Connection] ch["Connection Handler Layer<br/>• TLS/SSL Termination (if HTTPS)<br/>• Protocol Negotiation (HTTP/1.1, HTTP/2, HTTP/3)"] parser["HTTP Protocol Parser<br/>• Request Line Parsing (Method, Path, Protocol)<br/>• Header Parsing<br/>• Body Reading"] ctx["HttpContext Creation<br/>• Creates HttpContext object<br/>• Populates Request properties<br/>• Prepares Response object"] pipeline[Middleware Pipeline] cc --> ch --> parser --> ctx --> pipeline
要了解字节如何成为您中间软件可以使用的 HttpContext, 它有助于放大 Kestrel 的内部流动和责任。
flowchart LR
subgraph os[OS / Network Stack]
net[(TCP/UDP Sockets)]
end
subgraph kestrel[Kestrel Server]
accept["Connection Accept Loop<br/>(.NET Sockets)"]
subgraph connmw[Per-Connection Middleware]
tls["TLS Termination / ALPN<br/>(Selects HTTP/1.1 vs HTTP/2 vs HTTP/3)"]
limits["Connection & Request Limits<br/>(timeouts, sizes, rate limits)"]
logging[Connection Logging]
end
subgraph proto[Protocol Handlers]
h1["HTTP/1.1 Handler<br/>(keep-alive, chunked, pipelining)"]
h2["HTTP/2 Handler<br/>(multiplexing, HPACK)"]
h3["HTTP/3 Handler<br/>(QUIC, QPACK)"]
end
subgraph io[High-Perf IO]
pipes["System.IO.Pipelines<br/>(zero-copy buffers)"]
parser2[HTTP Parser]
end
features["Feature Mapping<br/>(IFeatureCollection)"]
ctxpool[HttpContext Pool]
appinvoke[IHttpApplication.ProcessRequestAsync]
end
app[Your Middleware Pipeline]
net --> accept --> connmw --> proto
proto --> io --> features --> ctxpool --> appinvoke --> app
sequenceDiagram
autonumber
participant C as Client
participant S as Socket
participant K as Kestrel
participant P as Protocol Handler
participant A as App (Middleware)
C->>S: Connect (TCP/QUIC)
S->>K: New connection accepted
K->>K: TLS handshake + ALPN
K->>P: Select protocol (HTTP/1.1, 2, or 3)
loop Read/Parse
P->>P: Read using System.IO.Pipelines
P->>P: Parse request line/headers/body
end
P->>K: Build features + rent HttpContext from pool
K->>A: ProcessRequestAsync(HttpContext)
A-->>K: Writes response via Pipes
K-->>C: Flush/Send response frames
Note over K,C: Backpressure applied when client is slow
要知道的关键内部 :
您可以配置 Kestrel 收听的端点以及如何收听 :
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(options =>
{
// Listen on all network interfaces on port 5000 (HTTP)
options.Listen(IPAddress.Any, 5000);
// Listen on localhost port 5001 (HTTPS)
options.Listen(IPAddress.Loopback, 5001, listenOptions =>
{
listenOptions.UseHttps("certificate.pfx", "password");
});
// Listen on specific IP with HTTP/2
options.Listen(IPAddress.Parse("192.168.1.100"), 5002, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http2;
});
// Unix domain socket (Linux/macOS)
options.ListenUnixSocket("/tmp/myapp.sock");
// Named pipe (Windows)
options.ListenNamedPipe("mypipename");
});
var app = builder.Build();
也可以通过 appings.json 配置端点 :
{
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "http://localhost:5000"
},
"Https": {
"Url": "https://localhost:5001",
"Certificate": {
"Path": "certificate.pfx",
"Password": "your-password"
}
}
}
}
}
var builder = WebApplication.CreateBuilder(args);
// Endpoints are automatically configured from appsettings.json
// when you don't explicitly call ConfigureKestrel
var app = builder.Build();
HTTPS对于生产应用至关重要。 Kestrel 提供了几种配置 TLS 的方法 :
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(options =>
{
options.Listen(IPAddress.Any, 5001, listenOptions =>
{
// Option 1: Certificate from file
listenOptions.UseHttps("certificate.pfx", "password");
// Option 2: Certificate from store (Windows)
listenOptions.UseHttps(storeCert =>
{
storeCert.Subject = "localhost";
storeCert.Store = "My";
storeCert.Location = StoreLocation.CurrentUser;
storeCert.AllowInvalid = false; // Don't allow invalid certs
});
// Option 3: Development certificate
listenOptions.UseHttps(); // Uses development certificate in Development environment
// Option 4: Configure TLS details
listenOptions.UseHttps(httpsOptions =>
{
httpsOptions.ServerCertificate = LoadCertificate();
httpsOptions.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
httpsOptions.CheckCertificateRevocation = true;
httpsOptions.SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13;
// Client certificate validation
httpsOptions.ClientCertificateValidation = (certificate, chain, errors) =>
{
// Custom validation logic
return errors == SslPolicyErrors.None;
};
});
});
});
var app = builder.Build();
Kestrel为控制资源使用和优化业绩提供了多种选择:
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(options =>
{
// Connection limits
options.Limits.MaxConcurrentConnections = 100;
options.Limits.MaxConcurrentUpgradedConnections = 100;
// Request limits
options.Limits.MaxRequestBodySize = 10 * 1024 * 1024; // 10 MB
options.Limits.MaxRequestHeaderCount = 100;
options.Limits.MaxRequestHeadersTotalSize = 32 * 1024; // 32 KB
options.Limits.MaxRequestLineSize = 8 * 1024; // 8 KB
// Keep-alive timeout
options.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(2);
// Request header read timeout
options.Limits.RequestHeadersTimeout = TimeSpan.FromSeconds(30);
// Minimum data rate for request body
options.Limits.MinRequestBodyDataRate = new MinDataRate(
bytesPerSecond: 240,
gracePeriod: TimeSpan.FromSeconds(5)
);
// Minimum data rate for response body
options.Limits.MinResponseDataRate = new MinDataRate(
bytesPerSecond: 240,
gracePeriod: TimeSpan.FromSeconds(5)
);
// HTTP/2 specific limits
options.Limits.Http2.MaxStreamsPerConnection = 100;
options.Limits.Http2.HeaderTableSize = 4096;
options.Limits.Http2.MaxFrameSize = 16 * 1024; // 16 KB
options.Limits.Http2.MaxRequestHeaderFieldSize = 8 * 1024; // 8 KB
options.Limits.Http2.InitialConnectionWindowSize = 128 * 1024; // 128 KB
options.Limits.Http2.InitialStreamWindowSize = 96 * 1024; // 96 KB
});
var app = builder.Build();
Kestel 支持现代 HTTP 协议 :
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(options =>
{
// HTTP/1.1 only
options.Listen(IPAddress.Any, 5000, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http1;
});
// HTTP/1.1 and HTTP/2
options.Listen(IPAddress.Any, 5001, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
listenOptions.UseHttps();
});
// HTTP/2 only
options.Listen(IPAddress.Any, 5002, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http2;
listenOptions.UseHttps();
});
// HTTP/3 (QUIC) - requires .NET 7+
options.Listen(IPAddress.Any, 5003, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http1AndHttp2AndHttp3;
listenOptions.UseHttps();
});
});
var app = builder.Build();
Kestrel 通过 IFeatureCollection 可用时间 HttpContext:
app.Use(async (context, next) =>
{
// Check if HTTP/2 is being used
var http2Feature = context.Features.Get<IHttpRequestFeature>();
if (http2Feature?.Protocol == "HTTP/2")
{
Console.WriteLine("Using HTTP/2");
}
// Access connection features
var connectionFeature = context.Features.Get<IHttpConnectionFeature>();
Console.WriteLine($"Remote IP: {connectionFeature?.RemoteIpAddress}");
Console.WriteLine($"Local IP: {connectionFeature?.LocalIpAddress}");
// TLS information
var tlsFeature = context.Features.Get<ITlsConnectionFeature>();
if (tlsFeature?.ClientCertificate != null)
{
Console.WriteLine($"Client cert: {tlsFeature.ClientCertificate.Subject}");
}
// Request body pipe for high-performance scenarios
var bodyPipeFeature = context.Features.Get<IRequestBodyPipeFeature>();
if (bodyPipeFeature != null)
{
var reader = bodyPipeFeature.Reader;
// Use System.IO.Pipelines for zero-copy reads
}
await next(context);
});
主办方为应用生命周期活动提供钩子:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
// Get the application lifetime
var lifetime = app.Services.GetRequiredService<IHostApplicationLifetime>();
// Application started event
lifetime.ApplicationStarted.Register(() =>
{
Console.WriteLine("Application has started");
// Perform startup tasks (warm up caches, etc.)
});
// Application stopping event
lifetime.ApplicationStopping.Register(() =>
{
Console.WriteLine("Application is stopping");
// Begin graceful shutdown (stop accepting new requests)
});
// Application stopped event
lifetime.ApplicationStopped.Register(() =>
{
Console.WriteLine("Application has stopped");
// Cleanup resources
});
app.Run();
您也可以执行 IHostedService 用于背景任务:
public class MyBackgroundService : IHostedService, IDisposable
{
private Timer? _timer;
private readonly ILogger<MyBackgroundService> _logger;
public MyBackgroundService(ILogger<MyBackgroundService> logger)
{
_logger = logger;
}
public Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Background service is starting");
_timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromMinutes(5));
return Task.CompletedTask;
}
private void DoWork(object? state)
{
_logger.LogInformation("Background service is working");
// Perform periodic work
}
public Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Background service is stopping");
_timer?.Change(Timeout.Infinite, 0);
return Task.CompletedTask;
}
public void Dispose()
{
_timer?.Dispose();
}
}
// Register the service
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHostedService<MyBackgroundService>();
var app = builder.Build();
ASP.NET核心自动处理优雅的关闭,但您可以定制行为:
var builder = WebApplication.CreateBuilder(args);
// Configure shutdown timeout
builder.WebHost.ConfigureKestrel(options =>
{
options.AddServerHeader = false; // Remove Server header for security
});
builder.Host.ConfigureHostOptions(options =>
{
// How long to wait for the application to shut down gracefully
options.ShutdownTimeout = TimeSpan.FromSeconds(30);
});
var app = builder.Build();
// During shutdown, Kestrel:
// 1. Stops accepting new connections
// 2. Waits for existing requests to complete (up to ShutdownTimeout)
// 3. Aborts remaining requests
// 4. Disposes services
// 5. Runs ApplicationStopped callbacks
app.Run();
在生产过程中,Kestrel通常支持反向代用(nginx、Apache、IIS):
var builder = WebApplication.CreateBuilder(args);
// Configure forwarded headers for reverse proxy scenarios
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
// If your proxy is on a known network
options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("10.0.0.0"), 8));
options.KnownProxies.Add(IPAddress.Parse("10.0.0.1"));
// Required when running in containers/Kubernetes
options.ForwardedHeaders = ForwardedHeaders.All;
options.KnownNetworks.Clear();
options.KnownProxies.Clear();
});
var app = builder.Build();
// Must be before other middleware
app.UseForwardedHeaders();
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
var builder = WebApplication.CreateBuilder(args);
// Enable Windows Service lifetime
builder.Host.UseWindowsService();
// Configure content root for Windows Service
builder.Host.UseContentRoot(AppContext.BaseDirectory);
var app = builder.Build();
app.Run();
var builder = WebApplication.CreateBuilder(args);
// Enable systemd lifetime
builder.Host.UseSystemd();
var app = builder.Build();
app.Run();
Kestreel 是标准选择, 您可以在需要时执行自定义服务器 :
public class CustomServer : IServer
{
private IFeatureCollection _features = new FeatureCollection();
public IFeatureCollection Features => _features;
public Task StartAsync<TContext>(IHttpApplication<TContext> application,
CancellationToken cancellationToken) where TContext : notnull
{
// Start listening for connections
// Create HttpContext for each request
// Invoke application.ProcessRequestAsync(httpContext)
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
// Stop accepting new connections
// Wait for existing requests to complete
return Task.CompletedTask;
}
public void Dispose()
{
// Cleanup resources
}
}
// Use custom server
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseServer(new CustomServer());
var app = builder.Build();
HttpContext 流经中器件管道的物体IFeatureCollection 提供使用低级别服务器的能力理解服务器和主机层使您能够控制您的应用程序如何启动,如何处理连接,如何在负载下运行。本基础支持在以上层发生的一切。
© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.