理解ASP.Net核心请求和反应管道----第2部分:服务器和托管层 (中文 (Chinese Simplified))

理解ASP.Net核心请求和反应管道----第2部分:服务器和托管层

Sunday, 09 November 2025

//

12 minute read

一. 导言 导言 导言 导言 导言 导言 一,导言 导言 导言 导言 导言 导言

在第一部分中,我们探索了 ASP.NET核心请求和响应管道的总体结构。现在,我们将深入到基础层:服务器和主机基础设施。这是一切事物开始的地方,你的应用程序进入生命,原始网络请求转化为结构化 HttpContext 流经中器件管道的物体

了解此层至关重要, 因为它控制您的应用程序如何启动, 如何配置, 以及如何与隐藏的网络服务器互动 。 无论您是在制作、 优化性能或配置 HTTPS , 主机层是解决这些关切的地方 。

注意:这是我在AI的实验的一部分 / 一种花费1000美元 Clude 代码 Web 信用的方法。 我给这个文件,我的理解,我不得不提出这样的问题。这很有趣,填补了一个我还没有看到的地方填补的空白。

两层建筑:主机和服务器

ASP.NET核心将应用程序托管和网络服务的关切分为两个不同的层面:

  1. 主机主机 - 管理应用程序使用寿命、配置、依赖性注射和伐木
  2. 服务器服务器 - 处理HTTP通信,倾听请求,管理连接

此分隔提供了灵活性: 您可以互换服务器( Kestrel、 HTTP.sys、 IIS 整合) 而不修改您的应用程序代码, 或者在不同的主机环境运行您的应用程序( 默认程序、 Windows Service、 系统守护程序) , 而不修改服务器配置 。

主机层

Web 应用程序和 Web 应用程序

在ASP.NET核心6和后来的ASP.NET核心6中,主机模式简化为: WebApplicationWebApplicationBuilder替换旧的 IHostBuilderIWebHostBuilder 具有更精简的 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();

服务器图层: Kestreel

Kestrel 是 ASP.NET Core 的跨平台网络服务器。 它快速、轻量级且有能力处理生产工作量。 了解 Kestrel 的能力有助于您优化应用程序的性能和安全性 。

Kestreel 建筑结构

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

Kestreel 建筑结构 - 更深潜

要了解字节如何成为您中间软件可以使用的 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

要知道的关键内部 :

  • TLS 和 ALPN 选择决定哪个协议处理器运行此连接 。
  • IO.Pipelines系统支持所有用于最低分配额和高吞吐量的解析和写作。
  • 特性映射( 自然集合) 将低级别的服务器能力暴露在 HttpContext 上, 而不与 Kestrel 类型挂钩 。
  • HtpContext 对象被集合在一起,以减少GC的压力;它们根据请求被重置和重新使用。
  • 客户无法快速阅读时, 后压通过管道应用; 服务器不会过度缓冲写 。
  • 超时和限值( 保持超时、 信头、 请求体积、 HTTP/2 流限) 保护服务器不受慢速和资源耗竭的影响 。
  • 串列: 大多数工作运行在线索pool上; 协议处理器避免每次请求的线索创建和偏向于同步延续 。

配置 Kestrel 结束点

您可以配置 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();

HTTPPS 配置

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();

Kestreel 限制和性能调试

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();

HTTP/2和HTTP/3支助

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();

Windows 服务托管服务

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();

Linux 系统服务托管服务

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();

密钥外出

  • 主机管理应用程序使用寿命、配置、DI和记录
  • Kestreel 是一个高性能的跨平台网络服务器
  • 您可以配置端点、 HTTPS、 协议和性能限制
  • 服务器创建 HttpContext 流经中器件管道的物体
  • 优雅的关闭确保申请在申请终止前完成
  • 生产部署通常使用Kestrel的反向代理
  • 缩略 IFeatureCollection 提供使用低级别服务器的能力

理解服务器和主机层使您能够控制您的应用程序如何启动,如何处理连接,如何在负载下运行。本基础支持在以上层发生的一切。


Finding related posts...
logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.