冠军

导航

各种各样的 Host Builder

各种各样的 Host Buider

If you're building for the web or writing a distributed application, you might need to use a different host builder. Consider the following list of additional host builders:

  • DistributedApplicationBuilder: A builder for creating distributed apps. For more information, see .NET Aspire.
  • WebApplicationBuilder: A builder for web applications and services. For more information, see ASP.NET Core.
  • WebHostBuilder: A builder for IWebHost. For more information, see ASP.NET Core web host.

见:https://learn.microsoft.com/en-us/dotnet/core/extensions/generic-host?tabs=appbuilder#additional-scenario-based-host-builders

HostApplicationBuilder

用来构建托管的应用和服务。从 .NET 6 开始提供。

见:https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.hostapplicationbuilder?view=net-8.0

WebApplicationBuilder

用于构建 Web 应用和 Web 服务的托管器,从 .NET 6 开始提供。现在推荐的方式。

见:https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.builder.webapplicationbuilder?view=aspnetcore-8.0

DistributedApplicationBuilder

主要用于实现 .NET Aspire 中,用来管理分布式应用。它比较新,从 .NET 8 开始提供。

见: https://learn.microsoft.com/en-us/dotnet/api/aspire.hosting.distributedapplicationbuilder?view=dotnet-aspire-8.0

WebHostBuilder

最早在 .NET Core 就提供的用于开发 Web 应用的托管器,它从 .NET 1.0 就开始提供。

WebHostBuilder 提供了便利的方式来完成对 IServer he RequestDelegate 对象的封装。它提供了 UseHttpListenerServer() 方法用来注册 HttpListener。以及 Configure() 方法用来配置 Web 服务器注册处理中间件。

见:https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.hosting.webhostbuilder?view=aspnetcore-8.0

.NET 中的 HostBuilder 类型详解

概述

.NET 提供了多种 HostBuilder 来适应不同类型的应用程序。每种 HostBuilder 都针对特定的应用场景进行了优化配置。


.NET 默认提供的 HostBuilder 类型

1. Host.CreateDefaultBuilder (Generic Host)

命名空间: Microsoft.Extensions.Hosting
适用场景: 控制台应用、后台服务、Worker Service

特点

  • 最基础的通用主机
  • 适合长期运行的后台服务
  • 不包含 Web 相关配置

默认配置内容

using Microsoft.Extensions.Hosting;

var host = Host.CreateDefaultBuilder(args)
    .ConfigureServices((context, services) =>
    {
        // 注册服务
    })
    .Build();

await host.RunAsync();

自动配置的内容

  • 配置系统: appsettings.json, appsettings.{Environment}.json, 环境变量, 命令行参数
  • 日志系统: Console, Debug, EventSource, EventLog (Windows)
  • 依赖注入: IServiceCollection
  • 生命周期管理: IHostApplicationLifetime
  • 环境: Development, Staging, Production

完整示例

using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

public class Program
{
    public static async Task Main(string[] args)
    {
        var host = Host.CreateDefaultBuilder(args)
            .ConfigureServices((context, services) =>
            {
                // 注册后台服务
                services.AddHostedService<MyBackgroundService>();
                
                // 注册其他服务
                services.AddSingleton<IMyService, MyService>();
            })
            .ConfigureLogging(logging =>
            {
                logging.AddConsole();
                logging.AddDebug();
            })
            .Build();

        await host.RunAsync();
    }
}

public class MyBackgroundService : BackgroundService
{
    private readonly ILogger<MyBackgroundService> _logger;
    
    public MyBackgroundService(ILogger<MyBackgroundService> logger)
    {
        _logger = logger;
    }
    
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
            await Task.Delay(1000, stoppingToken);
        }
    }
}

2. WebApplication.CreateBuilder (ASP.NET Core Minimal API)

命名空间: Microsoft.AspNetCore.Builder
适用场景: Web API、Minimal API、现代 Web 应用
最低版本: .NET 6.0+

特点

  • 简化的 Web 应用配置
  • 内置 Kestrel Web 服务器
  • 支持 Minimal API 风格
  • 更简洁的代码结构

默认配置内容

using Microsoft.AspNetCore.Builder;

var builder = WebApplication.CreateBuilder(args);

// 配置服务
builder.Services.AddControllers();

var app = builder.Build();

// 配置中间件
app.MapGet("/", () => "Hello World!");

app.Run();

自动配置的内容

  • 所有 Generic Host 的配置
  • Kestrel Web 服务器
  • HTTP 管道
  • 路由系统
  • 端点配置
  • 静态文件支持
  • HTTPS 重定向
  • CORS

完整示例

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;

var builder = WebApplication.CreateBuilder(args);

// 添加服务
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

// 自定义日志
builder.Logging.AddConsole();
builder.Logging.SetMinimumLevel(LogLevel.Information);

// 自定义 Kestrel
builder.WebHost.ConfigureKestrel(options =>
{
    options.ListenLocalhost(5000);
    options.ListenLocalhost(5001, listenOptions =>
    {
        listenOptions.UseHttps();
    });
});

var app = builder.Build();

// 配置 HTTP 请求管道
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

// Minimal API 端点
app.MapGet("/api/health", () => Results.Ok(new { status = "healthy" }));

app.MapPost("/api/users", (User user) => Results.Created($"/api/users/{user.Id}", user));

app.Run();

public record User(int Id, string Name);

3. WebHost.CreateDefaultBuilder (传统 ASP.NET Core)

命名空间: Microsoft.AspNetCore.WebHost
适用场景: 传统 ASP.NET Core MVC/Razor Pages 应用
状态: 已过时,建议使用 WebApplication.CreateBuilder

特点

  • .NET Core 2.x - .NET 5 时代的标准方式
  • 需要 Startup 类
  • 较为繁琐的配置方式

默认配置内容

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseRouting();
        app.UseAuthorization();
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
}

自动配置的内容

  • Kestrel 作为 Web 服务器
  • IIS 集成
  • 配置和日志系统
  • 内容根目录
  • Startup 类支持

4. WebApplication.CreateEmptyBuilder (最小化 Web Host)

命名空间: Microsoft.AspNetCore.Builder
适用场景: 需要完全控制 Web 应用配置,极致性能优化
最低版本: .NET 7.0+

特点

  • 最小化的 Web 应用配置
  • 不包含任何默认配置
  • 适合微服务、高性能场景
  • 完全手动控制所有配置

默认配置内容

using Microsoft.AspNetCore.Builder;

var builder = WebApplication.CreateEmptyBuilder(new WebApplicationOptions());

// 必须手动添加所有需要的服务
builder.Services.AddRouting();

// 必须手动配置 Kestrel
builder.WebHost.UseKestrel();

var app = builder.Build();

// 手动配置中间件
app.MapGet("/", () => "Hello World!");

app.Run();

与 CreateBuilder 的区别

  • 不包含 配置系统(appsettings.json)
  • 不包含 日志系统
  • 不包含 依赖注入默认服务
  • 不包含 环境检测
  • 更快的启动速度
  • 更小的内存占用

完整示例

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

var builder = WebApplication.CreateEmptyBuilder(new WebApplicationOptions
{
    Args = args,
    ContentRootPath = Directory.GetCurrentDirectory()
});

// 手动添加必需的服务
builder.WebHost.UseKestrel(options =>
{
    options.ListenLocalhost(5000);
});

// 手动添加配置(如果需要)
builder.Configuration.AddJsonFile("appsettings.json", optional: true);
builder.Configuration.AddEnvironmentVariables();

// 手动添加日志(如果需要)
builder.Logging.AddConsole();
builder.Logging.SetMinimumLevel(LogLevel.Information);

// 添加路由
builder.Services.AddRouting();

var app = builder.Build();

// 配置端点
app.MapGet("/", () => "Hello from Empty Builder!");
app.MapGet("/api/ping", () => Results.Ok(new { status = "pong" }));

app.Run();

使用场景

// 极简 API - 只需要路由
var builder = WebApplication.CreateEmptyBuilder(new WebApplicationOptions());
builder.WebHost.UseKestrel();
builder.Services.AddRouting();

var app = builder.Build();
app.MapGet("/health", () => "OK");
app.Run();

5. HostBuilder (手动构建)

命名空间: Microsoft.Extensions.Hosting
适用场景: 需要完全控制非 Web 应用配置过程

特点

  • 完全手动配置
  • 最大灵活性
  • 需要自己配置所有内容

示例

using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

var builder = new HostBuilder()
    .ConfigureAppConfiguration((context, config) =>
    {
        // 手动配置
        config.SetBasePath(Directory.GetCurrentDirectory());
        config.AddJsonFile("appsettings.json", optional: false);
        config.AddJsonFile($"appsettings.{context.HostingEnvironment.EnvironmentName}.json", optional: true);
        config.AddEnvironmentVariables();
        config.AddCommandLine(args);
    })
    .ConfigureServices((context, services) =>
    {
        // 注册服务
        services.AddHostedService<MyService>();
    })
    .ConfigureLogging((context, logging) =>
    {
        // 配置日志
        logging.AddConfiguration(context.Configuration.GetSection("Logging"));
        logging.AddConsole();
        logging.AddDebug();
    });

var host = builder.Build();
await host.RunAsync();

各 HostBuilder 对比表

特性 Host.CreateDefaultBuilder WebApplication.CreateBuilder WebApplication.CreateEmptyBuilder WebHost.CreateDefaultBuilder HostBuilder
.NET 版本 .NET Core 2.1+ .NET 6.0+ .NET 7.0+ .NET Core 2.0+ .NET Core 2.1+
状态 ✅ 当前推荐 ✅ 当前推荐 (Web) ✅ 高性能场景 ⚠️ 已过时 ✅ 高级场景
Web 服务器 ✅ Kestrel ⚡ 手动配置 ✅ Kestrel
自动配置 ✅ 完整 ✅ 完整 Web ❌ 无 ✅ 完整 Web ❌ 手动
配置系统
日志系统
Minimal API
启动速度 ⚡ 最快
内存占用 ⚡ 最小
复杂度
适用场景 后台服务 Web API 微服务/高性能 传统 MVC 完全自定义

选择指南

🎯 使用 Host.CreateDefaultBuilder 当:

  • ✅ 创建控制台应用
  • ✅ 开发 Worker Service (后台服务)
  • ✅ 创建定时任务
  • ✅ 不需要 HTTP 服务器

示例场景:

// Windows Service
public class Program
{
    public static async Task Main(string[] args)
    {
        await Host.CreateDefaultBuilder(args)
            .UseWindowsService()  // Windows 服务支持
            .ConfigureServices(services =>
            {
                services.AddHostedService<DataProcessingService>();
            })
            .Build()
            .RunAsync();
    }
}

🌐 使用 WebApplication.CreateBuilder 当:

  • ✅ 创建 REST API
  • ✅ 使用 Minimal API
  • ✅ 开发现代 Web 应用 (.NET 6+)
  • ✅ 需要简洁的代码结构

示例场景:

// REST API with Minimal API
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<AppDbContext>();

var app = builder.Build();

app.MapGet("/api/products", async (AppDbContext db) => 
    await db.Products.ToListAsync());

app.MapPost("/api/products", async (Product product, AppDbContext db) =>
{
    db.Products.Add(product);
    await db.SaveChangesAsync();
    return Results.Created($"/api/products/{product.Id}", product);
});

app.Run();

🚀 使用 WebApplication.CreateEmptyBuilder 当:

  • ✅ 需要极致性能和最快启动速度
  • ✅ 微服务架构
  • ✅ 云原生应用
  • ✅ 容器化部署(减少镜像大小)
  • ✅ 只需要最基本的路由功能

示例场景:

// 极简微服务
var builder = WebApplication.CreateEmptyBuilder(new WebApplicationOptions());
builder.WebHost.UseKestrel(options => options.ListenLocalhost(8080));
builder.Services.AddRouting();

var app = builder.Build();

app.MapGet("/health", () => "OK");
app.MapGet("/ready", () => Results.Ok(new { ready = true }));

app.Run();

🏗️ 使用 WebHost.CreateDefaultBuilder 当:

  • ⚠️ 维护旧项目 (.NET Core 2.x - .NET 5)
  • ⚠️ 需要 Startup 类结构
  • ⚠️ 建议迁移到 WebApplication.CreateBuilder

⚙️ 使用 HostBuilder 当:

  • ✅ 需要完全自定义配置
  • ✅ 高级场景
  • ✅ 特殊的初始化逻辑

实际应用示例

示例 1: Worker Service (使用 Host.CreateDefaultBuilder)

using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.DependencyInjection;

public class Program
{
    public static async Task Main(string[] args)
    {
        await Host.CreateDefaultBuilder(args)
            .UseWindowsService()      // Windows 服务
            .UseSystemd()             // Linux systemd
            .ConfigureServices((context, services) =>
            {
                services.AddHostedService<EmailWorker>();
                services.AddHostedService<DataSyncWorker>();
                
                // 注册依赖
                services.AddSingleton<IEmailService, EmailService>();
                services.AddSingleton<IDataSyncService, DataSyncService>();
            })
            .Build()
            .RunAsync();
    }
}

public class EmailWorker : BackgroundService
{
    private readonly IEmailService _emailService;
    private readonly ILogger<EmailWorker> _logger;

    public EmailWorker(IEmailService emailService, ILogger<EmailWorker> logger)
    {
        _emailService = emailService;
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Email Worker started");
        
        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                await _emailService.ProcessQueueAsync();
                await Task.Delay(TimeSpan.FromSeconds(30), stoppingToken);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error processing email queue");
            }
        }
    }
}

示例 2: Web API (使用 WebApplication.CreateBuilder)

using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Authentication.JwtBearer;

var builder = WebApplication.CreateBuilder(args);

// 配置服务
builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("Default")));

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidIssuer = builder.Configuration["Jwt:Issuer"],
            ValidAudience = builder.Configuration["Jwt:Audience"]
        };
    });

builder.Services.AddAuthorization();
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

// 注册业务服务
builder.Services.AddScoped<IProductService, ProductService>();
builder.Services.AddScoped<IOrderService, OrderService>();

var app = builder.Build();

// 配置中间件管道
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();

// Minimal API 端点
var apiGroup = app.MapGroup("/api").RequireAuthorization();

apiGroup.MapGet("/products", async (IProductService service) => 
    await service.GetAllAsync());

apiGroup.MapGet("/products/{id}", async (int id, IProductService service) =>
{
    var product = await service.GetByIdAsync(id);
    return product is not null ? Results.Ok(product) : Results.NotFound();
});

apiGroup.MapPost("/products", async (Product product, IProductService service) =>
{
    var created = await service.CreateAsync(product);
    return Results.Created($"/api/products/{created.Id}", created);
});

app.MapControllers();

app.Run();

示例 3: 混合应用 (Web + Background Service)

var builder = WebApplication.CreateBuilder(args);

// Web 服务
builder.Services.AddControllers();
builder.Services.AddSwaggerGen();

// 后台服务 - 在 Web 应用中运行
builder.Services.AddHostedService<DataCleanupWorker>();
builder.Services.AddHostedService<CacheRefreshWorker>();

// 共享服务
builder.Services.AddDbContext<AppDbContext>();
builder.Services.AddSingleton<ICacheService, RedisCacheService>();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.Run();

// 数据清理后台服务
public class DataCleanupWorker : BackgroundService
{
    private readonly IServiceProvider _serviceProvider;
    private readonly ILogger<DataCleanupWorker> _logger;

    public DataCleanupWorker(
        IServiceProvider serviceProvider,
        ILogger<DataCleanupWorker> logger)
    {
        _serviceProvider = serviceProvider;
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                using var scope = _serviceProvider.CreateScope();
                var dbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
                
                // 清理过期数据
                var expiredRecords = await dbContext.Records
                    .Where(r => r.ExpiryDate < DateTime.UtcNow)
                    .ToListAsync(stoppingToken);
                
                dbContext.Records.RemoveRange(expiredRecords);
                await dbContext.SaveChangesAsync(stoppingToken);
                
                _logger.LogInformation("Cleaned {Count} expired records", expiredRecords.Count);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error during data cleanup");
            }

            // 每小时运行一次
            await Task.Delay(TimeSpan.FromHours(1), stoppingToken);
        }
    }
}

配置对比详解

1. Host.CreateDefaultBuilder 默认配置

Host.CreateDefaultBuilder(args)
    // 等同于:
    .ConfigureAppConfiguration((context, config) =>
    {
        config.SetBasePath(Directory.GetCurrentDirectory());
        config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
        config.AddJsonFile($"appsettings.{context.HostingEnvironment.EnvironmentName}.json", 
            optional: true, reloadOnChange: true);
        
        if (context.HostingEnvironment.IsDevelopment())
        {
            config.AddUserSecrets<Program>();
        }
        
        config.AddEnvironmentVariables();
        config.AddCommandLine(args);
    })
    .ConfigureLogging((context, logging) =>
    {
        logging.AddConfiguration(context.Configuration.GetSection("Logging"));
        logging.AddConsole();
        logging.AddDebug();
        logging.AddEventSourceLogger();
    })
    .UseDefaultServiceProvider((context, options) =>
    {
        options.ValidateScopes = context.HostingEnvironment.IsDevelopment();
        options.ValidateOnBuild = true;
    });

2. WebApplication.CreateBuilder 默认配置

WebApplication.CreateBuilder(args)
    // 包含所有 Host.CreateDefaultBuilder 的配置,额外添加:
    .ConfigureWebHostDefaults(webBuilder =>
    {
        webBuilder.UseKestrel(options =>
        {
            // 默认配置
            options.Configure(context.Configuration.GetSection("Kestrel"));
        });
        
        webBuilder.ConfigureKestrel(options =>
        {
            // 默认端口配置
            options.ListenAnyIP(5000);
            options.ListenAnyIP(5001, listenOptions =>
            {
                listenOptions.UseHttps();
            });
        });
        
        webBuilder.UseIISIntegration();
    });

总结

快速决策树

需要创建什么应用?
│
├─ 需要 HTTP 服务器?
│  ├─ 是 → 使用 WebApplication.CreateBuilder (.NET 6+)
│  │       或 WebHost.CreateDefaultBuilder (旧版本)
│  └─ 否 → 往下看
│
├─ 后台服务/Worker Service?
│  └─ 是 → 使用 Host.CreateDefaultBuilder
│
└─ 需要完全自定义?
   └─ 是 → 使用 HostBuilder

推荐使用优先级 (.NET 6+ 项目)

  1. WebApplication.CreateBuilder - Web 应用首选(功能完整)
  2. Host.CreateDefaultBuilder - 后台服务首选
  3. WebApplication.CreateEmptyBuilder - 高性能微服务首选(.NET 7+)
  4. HostBuilder - 特殊需求
  5. WebHost.CreateDefaultBuilder - 已过时,不推荐

关键要点

  • 📌 .NET 6+ 优先使用 WebApplication.CreateBuilder (Web) 和 Host.CreateDefaultBuilder (非 Web)
  • 📌 .NET 7+ 高性能场景使用 WebApplication.CreateEmptyBuilder
  • 📌 所有 HostBuilder 都支持依赖注入、配置、日志(CreateEmptyBuilder 需手动配置)
  • 📌 可以在 Web 应用中运行后台服务 (使用 IHostedService)
  • 📌 CreateDefaultBuilder 已经包含了大部分常用配置,无需手动配置
  • 📌 CreateEmptyBuilder 提供最小化配置,适合容器化和微服务

posted on 2024-10-28 09:31  冠军  阅读(129)  评论(0)    收藏  举报