Back to "Розуміння запиту ядра ASP. NET і лінії каналу відповіді - Частина 2: сервер і шар вузла"

This is a viewer only at the moment see the article on how this works.

To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk

This is a preview from the server running through my markdig pipeline

AI-Article ASP.NET ASP.NET Lifecycle

Розуміння запиту ядра ASP. NET і лінії каналу відповіді - Частина 2: сервер і шар вузла

Sunday, 09 November 2025

Вступ

У першій частині ми вивчали загальну архітектуру головного ядра ASP.NET, а також трубопровод, який відповідає за відповідь. HttpContext Об'єкти, які проходять через ваш середній канал.

Розуміння цього шару має вирішальне значення, оскільки воно керує запуском вашої програми, її налаштуванням і тим, як вона взаємодіє з основним веб- сервером. Визначає, чи буде ви залучені до створення, оптимізованої швидкодії або налаштувавши HTTPS, шар вузлів - це шар, у якому ви зможете знайти відповіді на ці питання.

ЗАУВАЖЕННЯ: це частина моїх експериментів з комп' ютером ШІ / спосіб витратити на веб- кредит 100$ Code. Я надав вам папірець, моє розуміння, питання, які я повинен був створити для цієї статті. Це весело і заповнить прогалину, яку я не бачив у жодному іншому місці.

The Two- Layer Archucture: вузол і сервер

Ядро ASP. NET розділює питання, пов' язані з отримуванням програми та вебом, на два різних шари:

  1. Вузол - Керує життям програми, налаштуваннями, ін'єкціями залежностей і веденням журналу
  2. Сервер - оброблює HTTP- зв' язок, слухає запити і керує з'єднаннями

Це розділення надає гнучкість: ви можете обмінюватися серверами (Kestrel, HTTP. sys, IIS Інтеграція) без зміни коду вашої програми, або запускати вашу програму у різних середовищах (програмі для роботи з комп' ютерами, службі Windows, системній фоновій службі) без зміни налаштувань сервера.

Шар вузла

Програма для створення веб-адміністрування і створення веб-диспетчерів

У ASP NET Core 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}?

Коли дзвоните 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();

Шар сервера: Kerstrel

Kerstrel - це міжплатформовий веб- сервер ядра ASP. NET. Цей сервер є швидким, легким і здатний виконувати роботу з виробництвом. Розуміння можливостей 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

Архітектура Кестру - Глибша пам'ятка

Для того, щоб зрозуміти, як байти стають HtpContext, яким може скористатися ваша середня робота, це допомагає збільшити швидкість до Kestrels moves thing і відповідальності.

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 визначає, який з протоколів запущено для цього з' єднання.
  • System.IO.Pipelines underpins all parsing and write for minimal dictions and high toput.
  • Програма для відображення можливостей (IFeatureCollection) визначає можливості сервера низького рівня у HtpContext без прив' язки до типів Kestrel.
  • Об' єкти HttpContext скупчуються, щоб зменшити тиск з боку GC; ці об' єкти перезаходяться і повторюються за запитом.
  • Перенапруження застосовується через труби, коли клієнт може швидко читати; сервер виграв через-буфер пише.
  • Тайм- аут і обмеження (зберігати, заголовки, розмір тіла запиту, обмеження потоку HTTP/ 2) захистити сервер від повільного виснаження ресурсів.
  • Розгалуження гілками: більшість завдань виконуються під час обробки протоколів AtailPool; вони уникають створення окремих запитів на гілки і надають перевагу асинхронним продовженням.

Налаштування кінцевих точок 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();

Крім того, ви можете налаштувати кінцеві точки за допомогою apponts. 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

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

Обмеження та налаштування швидкодії

У Kepstrel передбачено різноманітні параметри для керування використанням ресурсів і оптимізованої швидкодії:

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

Kepstrel підтримує сучасні протоколи 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);
});

Застосовувати події Lifetime

Вузлом є гачки для подій життєвого циклу програми:

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

Сценарії створення вузлів

Виконання за зворотним проксі

Зазвичай, Керструл працює за зворотним проксі (нгінкс, апачі, ІС):

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

Додатково: Нетиповий сервер

Хоча і Kestrel є стандартним вибором, за потреби ви можете реалізувати нетиповий сервер:

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

Захоплення ключів

  • Вузол керує життям програми, налаштуваннями, графічним інтерфейсом і веденням журналу
  • Kestrel - це високоякісний, міжплатформовий веб-сервер
  • Ви можете налаштувати кінцеві точки, HTTPS, протоколи і обмеження швидкодії
  • Створення сервера HttpContext об'єкти, які проходять через середній канал зв'язку
  • Грандієве завершення роботи забезпечує виконання запитів до завершення роботи програми
  • Виробництво зазвичай використовує Kestrel за проксі- сервером з зворотним доступом
  • The IFeatureCollection надає доступ до можливостей низькорівневих серверів

Розуміння сервера і шару вузлів надасть вам змогу керувати запуском вашої програми, тим, як вона керує з' єднаннями і тим, як вона працює під навантаженням. Ця база підтримує все, що відбувається на шарах, розташованих вище.


logo

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