当前位置 博文首页 > sims:翻译 - ASP.NET Core 基本知识 - Web 主机 (Web Host)

    sims:翻译 - ASP.NET Core 基本知识 - Web 主机 (Web Host)

    作者:sims 时间:2021-01-30 19:11

    翻译自 https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/web-host?view=aspnetcore-5.0

    ASP.NET Core 应用程序配置和启动一个 Host。Host 负责应用程序的启动和生命周期的管理。至少的,Host 配置一个服务器和一个请求处理管道。Host 也会设置日志,依赖注入和配置。

    这篇文章覆盖了 Web Host,任然是只是向后兼容可用。 Generic Host 推荐用于所有类型的应用程序。

    配置一个 Host

    使用 IWebHostBuilder 的实例创建一个 Host。一般会在应用程序的入口点 Main 方法中创建。

    在工程模板中,Main 方法位于 Program.cs 中。典型的应用程序调用 CreateDefaultBuilder 启动配置一个 Host:

    public class Program
    {
        public static void Main(string[] args)
        {
            CreateWebHostBuilder(args).Build().Run();
        }
    
        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>();
    }

    代码中调用 CreateDefaultBuilder 的是在一个叫做 CreateWebHostBuilder 的方法中,这个方法从 Main 中分离出来,在 Main 方法中在 builder 对象上调用 Run 方法。这中分离是有必须的,如果你使用了 Entity Framework Core tools。这个工具期望找到一个 CreateWebHostBuilder 方法,以便能不必运行应用程序就能够在设计的时候配置 Host。一种途径是实现接口 IDesignTimeDbContextFactory。更多信息,查看 Design-time DbContext Creation。

    CreateDefaultBuilder 执行了以下任务:

    • 使用应用程序的托管配置的应用程序提供器配置 Kestrel 服务器作为 web 服务器。Kestrel 服务器默认选项,查看 Configure options for the ASP.NET Core Kestrel web server。
    • 设置 content root 为 Directory.GetCurrentDirectory 返回的路径值
    • 从以下地方加载主机配置(host configuration)
      前缀为 ASPNETCORE_  的环境变量(例如,ASPNETCORE_ENVIRONMENT)
      命令行参数
    • 按照下面的顺序加载应用程序配置
      appsetting.json
      appsetting.{Environment}.json
      User secrets 当应用程序使用入口程序集运行在 Development 环境时
      环境变量
      命令行参数
    • 为控制台和调试输出配置日志(logging)。日志包括在 appsetting.json 或者 appsetting.{Environment}.json 文件中配置区域配置的日志过滤(log filtering)规则。
    • 当 ASP.NET Core Module 运行在 IIS 之后,CreateDefaultBuilder 会使能 IIS 集成(IIS Integration),配置了应用程序基本地址和端口。IIS 集成也会配置应用程序捕获启动错误(capture startup errors)。关于 IIS 默认配置,查看 Host ASP.NET Core on Windows with IIS。
    • 如果应用程序环境为 Development,设置 ServiceProviderOptions.ValidateScopes 为 true。更多信息,查看 Scope validation。

    CreateDefaultBuilder 定义的配置可以被覆盖和使用 ConfigureAppConfiguration,ConfigureLogging 和其它方法及 IWebHostBuilder 的扩展方法扩展。下面是几个例子:

    • ConfigureAppConfiguration 用来为应用程序指定额外的 IConfiguration。下面的 ConfigureAppConfiguration 调用添加了一个代理去包含在 appsettings.xml 文件中的应用程序的配置。ConfigureAppConfiguration 可能会调用多次。注意这个配置并不应用到主机(例如,服务器 URLs 或者 环境)。查看 Host configuration values 部分。
      WebHost.CreateDefaultBuilder(args)
          .ConfigureAppConfiguration((hostingContext, config) =>
          {
              config.AddXmlFile("appsettings.xml", optional: true, reloadOnChange: true);
          })
          ...
    • 下面的 ConfigureLogging 调用添加一个代理去配置最小的logging level (SetMinimumLevel) 为 LogLevel.Warning。这个设置覆盖了appsettings.Development.json (LogLevel.Debug) 和 appsettings.Production.json (LogLevel.Error) 里面通过 CreateDefaultBuilder 配置的设置。ConfigureLogging 可能会调用多次。
      WebHost.CreateDefaultBuilder(args)
          .ConfigureLogging(logging => 
          {
              logging.SetMinimumLevel(LogLevel.Warning);
          })
          ...
    • 下面的 ConfigureKestrel 的调用覆盖了 Kestrel 通过 CreateDefaultBuilder 配置的默认的 Limits.MaxRequestBodySize 30,000,000 字节:
      WebHost.CreateDefaultBuilder(args)
          .ConfigureKestrel((context, options) =>
          {
              options.Limits.MaxRequestBodySize = 20000000;
          });

      content root 决定了 Host 在哪里搜索内容文件,例如 MVC 视图文件。当应用程序从工程根目录启动的时候,工程根目录被用作内容根目录。这在 Visual Studio 和 dotnet new templates 默认使用。

    更多关于应用程序配置的信息,查看 Configuration in ASP.NET Core。

    注意

    作为一种使用静态 CreateDefaultBuilder 方法的途径,从 WebHostBuilder 创建一个 Host 在 ASP.NET Core 2.x 中是受支持的。

    当设置一个主机的时候,可以提供 Configure 和 ConfigureServices 这两个方法。如果一个 Startup 方法被指定了,它必须定义 Configure 方法。更多信息,查看 App startup in ASP.NET Core 。多次调用 ConfigureServices 将会附加到另外一个上面。在 WebHostBuilder 上多次调用 Configure 或者 UseStartup 将会替换之前的设置。

    Host configuration values

    WebHostBuilder 依赖下面的方法设置主机配置值:

    • Host builder configuration,包含格式为 ASPNETCORE_{configurationKey} 的环境变量。例如,ASPNETCORE_ENVIRONMENT。
    • 扩展,例如 UseContentRoot 和 UseConfiguration (查看 Override configuration 部分)
    • UseSetting 和相关的键。当使用 UseSetting 设置值得时候,值被设置为字符串而忽略它的类型。

    主机使用最后设置值得选项。更多信息查看,Override configuration。

    Application Key (Name)

    当 UseStartup 或者 Configure 在主机构造方法中调用的时候,IWebHostEnvironment.ApplicationName 属性会自动设置。值被设置为包含应用程序入口点的程序集的名称。显式的设置,可以使用 WebHostDefaults.ApplicationKey:

    Key: applicationName

    Type: string

    Default: 包含应用程序入口点程序集的名称

    Set using: UseSetting

    Environment variable: ASPNETCORE_APPLICATIONNAME

    WebHost.CreateDefaultBuilder(args)
        .UseSetting(WebHostDefaults.ApplicationKey, "CustomApplicationName")

    Capture Startup Errors

    设置捕获启动错误的控制

    Key: captureStartupErrors

    Type: bool (true or 1)

    Default: 默认为 false,除非应用程序使用 Kestrel 运行在 IIS 之后,这时默认是 true

    Set using: CaptureStartupErrors

    Environment variable: ASPNETCORE_CAPTURESTARTUPERRORS

    当设置为 false 时,启动过程中的错误会导致主机退出。当设置为 true 时,主机会捕获启动过程中的异常,并且试图启动服务器。

    WebHost.CreateDefaultBuilder(args)
        .CaptureStartupErrors(true)

    Content root

    这个设置决定了 ASP.NET Core 开始搜索内容文件的位置。

    Key: contentRoot

    Type: string

    Default: 默认是应用程序程序集所在的目录

    Set using: UseContentRoot

    Environment variable: ASPNETCORE_CONTENTROOT

    content root 也被用作 web root 的基本路径。如果 content root 路径不存在,主机就会启动失败。

    WebHost.CreateDefaultBuilder(args)
        .UseContentRoot("c:\\<content-root>")

    更多信息,请查看:

    • Fundamentals: Content root
    • Web root

    Detailed Errors

    决定是否应该详细错误信息

    Key: detailedErrors

    Type: bool (treu 或者 1)

    Default: false

    Set using: UseSetting

    Environment variable: ASPNETCORE_DETAILEDERRORS

    当使能的时候(或者 Environment 被设置为 Development 的时候),应用程序会捕获异常详细信息。

    WebHost.CreateDefaultBuilder(args)
        .UseSetting(WebHostDefaults.DetailedErrorsKey, "true")

    Environment

     设置应用程序环境

    Key: environment

    Type: string

    Default: Production

    Set using: UseEnvironment

    Environment variable: ASPNETCORE_ENVIRONMENT

    environmenmt 可以被设置为任意的值。框架定义的值包括 Development,Staging 和 Production。值不区分大小写。默认的,Environment 从 ASPNETCORE_ENVIRONMENT  环境变量中读取。当使用 Visual Studio 时,环境变量可能在 lauchSetting.json 文件中设置。更过信息,请查看: Use multiple environments in ASP.NET Core。

    WebHost.CreateDefaultBuilder(args)
        .UseEnvironment(EnvironmentName.Development)

    Hosting Startup Assemblies

    设置应用程序托管启动程序集

    Key: hostingStartupAssemblies

    Type: string

    Default: Empty string

    Set using: UseSetting

    Environment variable: ASPNETCORE_HOSTINGSTARTUPASSEMBLIES

    以逗号分隔的字符串,启动时加载的托管的启动程序集

    尽管配置值被设置为空字符串,托管程序集总是包含应用程序程序集。当提供了托管启动程序集,它们在应用程序启动时创建公共服务时被添加到应用程序程序集。

    WebHost.CreateDefaultBuilder(args)
        .UseSetting(WebHostDefaults.HostingStartupAssembliesKey, "assembly1;assembly2")

    HTTPs Port

    设置 HTTPS 重定向端口。使用 enforcing HTTPS。

    Key: https_port

    Type: string

    Defalut: 默认无设置

    Set using: UseSetting

    Environment variable: ASPNETCORE_HTTPS_PORT

    WebHost.CreateDefaultBuilder(args)
        .UseSetting("https_port", "8080")

    Hosting Startup Exclude Assemblies

    冒号分隔的字符串,启动时排除托管启动程序集

    Key: hostingStartupExcludeAssemblies

    Type: string

    Default: Empty string

    Set using: UseSetting

    Environment variable: ASPNETCORE_HOSTINGSTARTUPEXCLUDEASSEMBLIES

    WebHost.CreateDefaultBuilder(args)
        .UseSetting(WebHostDefaults.HostingStartupExcludeAssembliesKey, "assembly1;assembly2")

    Prefer Hosting URLs

    表明主机是否应该在使用 WebHostBuilder 配置的 URLs 上监听,而不是 IServer 实现配置的 URLs

    Key: preferHostingUrls

    Type: bool (true 或者 1)

    Default: true

    Set using: PreferHostingUrls

    Environment variable: ASPNETCORE_PREFERHOSTINGURLS

    WebHost.CreateDefaultBuilder(args)
        .PreferHostingUrls(false)

    Prevent Hosting Startup

    阻止自动加载托管启动程序集,包括应用程序程序集配置的托管启动程序集。更多信息查看,Use hosting startup assemblies in ASP.NET Core。

    Key: preventHostingStartup

    Type: bool (true 或者 1)

    Default: false

    Set using: UseSetting

    Environment variable: ASPNETCORE_PREVENTHOSTINGSTARTUP

    WebHost.CreateDefaultBuilder(args)
        .UseSetting(WebHostDefaults.PreventHostingStartupKey, "true")

    Server URLs

    表明带有端口和协议的 IP 地址或者主机地址是否应该被服务器监听请求

    Key: urls

    Type: string

    Default: http://localhost:5000

    Set using: UseUrls

    Environment variable: ASPNETCORE_URLS

    设置一组服务器应该响应的冒号(;)分隔的 URL 前缀。例如,http://localhost:123。使用 "*" 表明服务器是否应该监听任意使用特定端口和协议(例如,http://*:5000)的 IP 地址或者主机地址。协议 (http:// 或者 https://) 必须包含在每一个 URL 中。支持的格式因服务器不同而不同。

    WebHost.CreateDefaultBuilder(args)
        .UseUrls("http://*:5000;http://localhost:5001;https://hostname:5002")

    Kestrel 有它自己的 endpoint 配置 API。更多信息查看,Configure endpoints for the ASP.NET Core Kestrel web server。

    Shutdown Timeout

    指定等待 Web Host 关闭的超时时间

    Key: shutdownTimeoutSeconds

    Type: int

    Default: 5

    Set using: UseShutdownTimeout

    Environment variable: ASPNETCORE_SHUTDOWNTIMEOUTSECONDS

    尽管使用 UseSetting 可以接受键为 int 的值(例如,.UseSetting(WebHostDefaults.ShutdownTimeoutKey,"10")),UseShutdownTimeout 带有 TimeSpan 参数。

    在超时时间内,主机会:

    • 触发 IApplicationLifetime.ApplicationStopping
    • 尝试停止托管的服务,日志记录任何服务停止失败的错误

    如果在所有服务停止之前超时了,任何活动的服务在应用程序关闭时都会停止。即使服务没有完成处理也会被停止。如果服务需要更多的时间去停止,增加超时时间。

    WebHost.CreateDefaultBuilder(args)
        .UseShutdownTimeout(TimeSpan.FromSeconds(10))

    Startup Assembly

    决定搜索 Startup 类的程序集

    Key: startupAssembly

    Type: string

    Default: 应用程序程序集

    Set using: UseStartup

    Environment variable: ASPNETCORE_STARTUPASSEMBLY

    可以指定程序的名称(string)或者类型 (TStartup)。如果多个 UseStartup 方法被调用,则最后一个优先级最高:

    WebHost.CreateDefaultBuilder(args)
        .UseStartup("StartupAssemblyName")
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<TStartup>()

    Web root

    设置应用程序静态资源的相对路径

    Key: webroot

    Type: string

    Default: 默认是 wwwroot。路基 {contentroot}/wwwroot 必须存在。如果路径不存在,一个 no-op 文件提供器将被使用。

    WebHost.CreateDefaultBuilder(args)
        .UseWebRoot("public")

    更多信息查看:

    • Fundamentals: Web root
    • Content root

    覆盖配置

    使用 Configuration 配置 Web Host。在下面的例子中,host 配置在 hostsetting.json 文件中是可选指定的。任何从 hostsetting.json 文件中加载的配置可能会被命令行参数覆盖。编译的配置(in config)使用 UseConfiguration 来配置主机。IWebHostBuilder 配置被添加到应用程序配置中,但是相反的就不是,ConfigureAppConfigureation 不会影响 IWebHostBuilder 配置。

    覆盖 UseUrls 提供的配置优先使用 hostsettings.json 配置,其次是命令行参数配置:

    public class Program
    {
        public static void Main(string[] args)
        {
            CreateWebHostBuilder(args).Build().Run();
        }
    
        public static IWebHostBuilder CreateWebHostBuilder(string[] args)
        {
            var config = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("hostsettings.json", optional: true)
                .AddCommandLine(args)
                .Build();
    
            return WebHost.CreateDefaultBuilder(args)
                .UseUrls("http://*:5000")
                .UseConfiguration(config)
                .Configure(app =>
                {
                    app.Run(context => 
                        context.Response.WriteAsync("Hello, World!"));
                });
        }
    }

    hostsettings.json:

    {
        urls: "http://*:5005"
    }

    注意

    UseConfiguration 只会复制 IConfiguration 提供的键值到 host builder 配置。因此,设置 reloadOnChange: true 为 JSON,INI,和 XML 设置文件没有影响。

    指定主机在一个特定的 URL 上运行,期望的值可以在运行 dotnet run 时命令行提示中传入。命令行参数覆盖了来自 hostsettings.json 中的 urls 值,服务器在 8080 端口监听:

    dotnet run --urls "http://*:8080"

    管理 Host

    Run

    Run 方法启动 web 应用程序并阻塞调用线程直到 Host 关闭:

    host.Run();

    Start

    通过调用它的 Start 方法以 non-blocking 方式运行 Host:

    using (host)
    {
        host.Start();
        Console.ReadLine();
    }

    如果一组 URLs 传递给 Start 方法,它就会监听这组指定的 URLs:

    var urls = new List<string>()
    {
        "http://*:5000",
        "http://localhost:5001"
    };
    
    var host = new WebHostBuilder()
        .UseKestrel()
        .UseStartup<Startup>()
        .Start(urls.ToArray());
    
    using (host)
    {
        Console.ReadLine();
    }

    应用程序可以使用预设值的默认 CreateDefaultBuilder 使用一个静态约定的方法初始化和启动一个新的 Host。这些方法启动服务器时没有控制台输出,使用 WaitForShutdown 等待终止(Ctrl-C/SIGINT  或者 SIGTERM):

    Start(RequestDelegate app)

    使用 RequestDelegate 启动:

    using (var host = WebHost.Start(app => app.Response.WriteAsync("Hello, World!")))
    {
        Console.WriteLine("Use Ctrl-C to shutdown the host...");
        host.WaitForShutdown();
    }

    在浏览器中发送一个请求 http://localhost:5000 接收到 "Hello World!" 响应,WaitForShutdown 阻塞了直到一个结束信号 (Ctrl-C/SIGINT  或者  SIGTERM) 出现。应用程序显示了 Console.WriteLine 信息,等待按键退出。

    Start(string url, RequestDelegate app)

    使用一个 URL 和 RequestDelegate 启动应用程序:

    using (var host = WebHost.Start("http://localhost:8080", app => app.Response.WriteAsync("Hello, World!")))
    {
        Console.WriteLine("Use Ctrl-C to shutdown the host...");
        host.WaitForShutdown();
    }

    和 Start(RequestDelegate app) 生成同样的结果,期望应用程序在 http://localhost:8080 上响应。

    Start(Action <IRouteBuilder> routerBuilder)

    使用 IRouteBuilder (Microsoft.AspNetCore.Routing) 的实例使用 routing 中间件:

    using (var host = WebHost.Start(router => router
        .MapGet("hello/{name}", (req, res, data) => 
            res.WriteAsync($"Hello, {data.Values["name"]}!"))
        .MapGet("buenosdias/{name}", (req, res, data) => 
            res.WriteAsync($"Buenos dias, {data.Values["name"]}!"))
        .MapGet("throw/{message?}", (req, res, data) => 
            throw new Exception((string)data.Values["message"] ?? "Uh oh!"))
        .MapGet("{greeting}/{name}", (req, res, data) => 
            res.WriteAsync($"{data.Values["greeting"]}, {data.Values["name"]}!"))
        .MapGet("", (req, res, data) => res.WriteAsync("Hello, World!"))))
    {
        Console.WriteLine("Use Ctrl-C to shutdown the host...");
        host.WaitForShutdown();
    }

    对上面的示例使用下面的浏览器请求:

    Request Response
    http://localhost:5000/hello/Martin Hello,Martin!
    http://localhost:5000/buenosdias/Catrina Buenos dias,Catrina!
    http://localhost:5000/throw/ooops! Throw an exception with string "ooops!"
    http://localhost:5000/throw  Throw an exception with string "Uh oh!"
    http://localhost:5000/Sante/Kevin Sante,Kevin! 
     http://localhost:5000 Hello World! 

     WaitForShutdown 阻塞直到结束信号(Ctrl-C/SIGINT 或者 SIGTERM)出现。应用程序显示 Console.WriteLine 信息,等待按键按下退出。

    Start(string url, Action<IRouteBuilder> routeBuilder)

    使用 URL 和 IRouterBuilder 实例:

    using (var host = WebHost.Start("http://localhost:8080", router => router
        .MapGet("hello/{name}", (req, res, data) => 
            res.WriteAsync($"Hello, {data.Values["name"]}!"))
        .MapGet("buenosdias/{name}", (req, res, data) => 
            res.WriteAsync($"Buenos dias, {data.Values["name"]}!"))
        .MapGet("throw/{message?}", (req, res, data) =>