编程博客
002、修改Nuget包位置
001、C#常用的单词
003、收藏的书签
回家准备
004、ASP.NET Core 3.0 gRPC
001、ASP.NET Core 3.0 使用gRPC
002、ASP.NET Core 3.0 gRPC 双向流
003、ASP.NET Core 3.0 gRPC 身份认证和授权
005、飞牛NAS
001、 FnOS飞牛系统实用配置1-应用远程访问(迅雷)
006、DeepSeek
001、DeepSeek 使用指南
007、并发编程
01、并发编程 - 死锁的产生、排查与解决方案
02、并发编程 - 初识线程
03、并发编程 - 线程浅试
04、并发编程 - 线程同步(一)
05、并发编程 - 线程同步(二)
06、并发编程 - 线程同步(三)之原子操作 Interlocked 简介
07、并发编程 - 线程同步(四)之原子操作 Interlocked 详解一
08、并发编程 - 线程同步(五)之原子操作 Interlocked 详解二
09、并发编程 - 线程同步(六)之锁 lock
008、启动项
03、应用--Program 中的 WebApplication
02、主机--Host
01、Program 文件的作用
04、控制反转 IOC 与依赖注入 DI
05、中间件
06、Logger 原理及配置 Log4Net
07、ElasticSearch
本文档使用 MrDoc 发布
-
+
首页
02、主机--Host
# [主机--Host](https://www.cnblogs.com/boise/p/18002730 "发布于 2024-02-02 10:40") # **概念****:主机是用于构建应用程序和服务、封装应用资源的对象,负责程序的启动和生命周期的管理,简单来说主机即应用程序。** **主机运行****:当主机运行的时候,他会将托管在服务容器集合里面注册的**`IHostService` 的每个实现调用 `IHostService.StartAsync()`。在 web 应用中,每一个 `IHostService` 实现就是启动。 [微软官网地址](https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/host/web-host?view=aspnetcore-7.0) **需要掌握:** * [ ] **主机的作用是什么?** * [ ] **主机的种类、对应的版本?** * [ ] **泛型主机的代码上和逻辑上的构造流程** * [ ] **泛型主机替换 Web 主机的原因以及通过什么拓展方法来支持 Http 负载?** ## 主机的种类和构建方式[#](https://www.cnblogs.com/boise/p/18002730#%E4%B8%BB%E6%9C%BA%E7%9A%84%E7%A7%8D%E7%B1%BB%E5%92%8C%E6%9E%84%E5%BB%BA%E6%96%B9%E5%BC%8F) ### 1. WebHost(范围:3.0 版本之前)[官网](https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/host/web-host?view=aspnetcore-7.0)[#](https://www.cnblogs.com/boise/p/18002730#1.-webhost%EF%BC%88%E8%8C%83%E5%9B%B4%EF%BC%9A3.0%E7%89%88%E6%9C%AC%E4%B9%8B%E5%89%8D%EF%BC%89%E5%AE%98%E7%BD%91) **在 3.0 版本之前,当我们构建 Web 应用的时候,Program.cs 默认构建的主机类型是 WebHost,在 CreateWebHostBuilder()方法中通过调用 WebHost 静态类的 CreateDefaultBuilder()方法返回一个**`IWebHostBuilder对象,` 然后调用 `Build()` 方法和 `Run()` 方法来构建主机和运行主机。 **流程:获取**`WebHost构建器` **-> 调用**`Build()` 方法生成主机实例 -> `Run()` 方法 *2.1 版本* ``` // WebAPI的Program.cs public class Program { public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } /// <summary> /// 生成Web应用主机 /// </summary> /// <param name="args"></param> /// <returns></returns> public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>()); } ``` ### 2. 泛型 Host(范围:3.0 版本之后)[官网](https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/host/generic-host?view=aspnetcore-7.0)[#](https://www.cnblogs.com/boise/p/18002730#2.-%E6%B3%9B%E5%9E%8Bhost%EF%BC%88%E8%8C%83%E5%9B%B4%EF%BC%9A3.0%E7%89%88%E6%9C%AC%E4%B9%8B%E5%90%8E%EF%BC%89%E5%AE%98%E7%BD%91) **3.0 以后微软将主机类型替换为了**`Host` 通用主机,通过在 `CreatHostBuilder()` 中调用 `Host.reateDefaultBuilder()` 方法返回一个 `IHostBuilder对象`,然后调用 `Build()方法和Run()方法` 来构建主机和运行主机。 **在 3.0 版本,微软对**`Host` 进行了升级,原本 `Host` 只能用于非 HTTP 负载,但是通过调用 `ConfigureWebHostDefaults()拓展方法` 来实现 HTTP 负载。 **在 6.0 版本,微软对于 netcore 进行了大升级,**`Program.cs` 文件发生了很大的改变,所以下方将会分为 2 个部分来分别介绍 3.0 版本到 5.0 版本的泛型 Host 是如何创建的?6.0 版本的泛型 Host 是如何创建的? #### 3.0 版本到 5.0 版本的的创建泛型 Host[#](https://www.cnblogs.com/boise/p/18002730#3.0%E7%89%88%E6%9C%AC%E5%88%B05.0%E7%89%88%E6%9C%AC%E7%9A%84%E7%9A%84%E5%88%9B%E5%BB%BA%E6%B3%9B%E5%9E%8Bhost) **流程:**获取 `IHostBuilder`-> 调用 `ConfigureWebHostDefaults()` 方法来拓展 `WebHost`(**web 应用需要调用此拓展方法,非 web 应用,如 WokerService 则不需要****) -> 调用**`Build()` 方法生成主机实例 -> `Run()` 方法 *5.0 版本* ``` // WebAPI的Program.cs文件 public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } /// <summary> /// 生成通用主机 /// </summary> /// <param name="args"></param> /// <returns></returns> public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) // 因为是WebAPI,所以要调用此拓展服务,配置WebAPI的配置,如中间件、服务等。 // 使用拓展方法UseStartup()指向Startup文件 // 官方描述:用于托管Web应用程序的默认值配置 .ConfigureWebHostDefaults(Builder => { Builder.UseStartup<Startup>(); }); } ``` ##### ConfigureWebHostDefaults()拓展方法: **原本 Host 是不支持 HTTP 工作负载的,所以要使用此拓展方法可以配置主机所需要的 Web 服务。** **调用这个方法会将 WebHost 注入到 Host 中。** **简单来说,如果你的版本是 3.0 到 5.0,且需要 web 服务,如 MVC 或者 WebAPI 则需要配置此服务。** *(创造项目的时候会自动生成的,所以了解一下这个拓展方法是干什么的就好了)* *ConfigureWebHostDefaults 拓展方法源码* ``` namespace Microsoft.Extensions.Hosting { // 用于托管 Web 应用程序的默认值配置 Microsoft.Extensions.Hosting.IHostBuilder // 这应该在应用程序特定的配置之前调用,以避免它覆盖提供的服务、配置源、环境、内容根等 public static class GenericHostBuilderExtensions { public static IHostBuilder ConfigureWebHostDefaults(this IHostBuilder builder, Action<IWebHostBuilder> configure); } } ``` #### 6.0 版本的的创建泛型 Host[#](https://www.cnblogs.com/boise/p/18002730#6.0%E7%89%88%E6%9C%AC%E7%9A%84%E7%9A%84%E5%88%9B%E5%BB%BA%E6%B3%9B%E5%9E%8Bhost) **6.0 版本,NetCore 使用最小托管模型来创建应用,只需要 4 行代码就能构建一个应用** [关于 WebApplication 与 Host 请查看应用]() **通过使用**`WebApplication.CreateBuilder(args)` 来创建主机 *最小托管模型* ``` // 得到应用构造器:WebApplicationBuilder var builder = WebApplication.CreateBuilder(args); // 配置日志 builder.Logging.AddLog4Net("ConfigFile/log4net.config"); // 得到应用:WebApplication var app = builder.Build(); // 配置中间件 app.UseStaticFiles(); // 运行主机 app.Run(); ``` ### 3. 为什么要用泛型 Host 替换 WebHost:[#](https://www.cnblogs.com/boise/p/18002730#3.-%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E7%94%A8%E6%B3%9B%E5%9E%8Bhost%E6%9B%BF%E6%8D%A2webhost%EF%BC%9A) [参考 stackoverflow 的回答](https://stackoverflow.com/questions/59745401/what-is-the-difference-between-host-and-webhost-class-in-asp-net-core) **泛型 Host 在 2.1 版本就已经存在了,当时只是用于非 Http 请求的工作负载,而 WebHost 构建器更多地与 HTTP 请求相关联并且适用于 Web 应用,随着微服务和 Docker 的发展和出现,程序需要一个更通用的 Web 主机,因此 .NET 核心团队在 3.0 对 Host 进行了改进,让 Host 也可也支持 HTTP 负载(通过拓展方法**`ConfigureWebHostDefaults`),**可以更好地将 ASP.NET Core 应用与非 Web 特定的其他服务器方案集成****。简而言之就是为了在所有的 netcore 应用中都是用一个主机。** ### 4. 从 WebHost 改为泛型 Host 后发生主要变化:[#](https://www.cnblogs.com/boise/p/18002730#4.-%E4%BB%8Ewebhost%E6%94%B9%E4%B8%BA%E6%B3%9B%E5%9E%8Bhost%E5%90%8E%E5%8F%91%E7%94%9F%E4%B8%BB%E8%A6%81%E5%8F%98%E5%8C%96%EF%BC%9A) **使用 Host 替换 WebHost,即 3.0 之后的变化,主要在于依赖注入 DI,在使用 HostBuilder 的时候,Startup.cs 的构造函数只能注入以下类型:** * **IConfiguration****:键值对的配置,如默认的 appsetting.json 文件中的配置,或者通过创建主机的时候使用**`Builder.AddJsonFile()` 方法引入的自定义 json 配置文件引入的 json 配置文件,通过这个接口可以获取配置文件的数据; * **IHostEnvironment****:提供****运行应用程序的宿主环境****,比如常用的 IsDevelopment()方法来判断是否是运行时环境;** * **IWebHostEnvironment****:提供有关运行应用程序的** **Web 托管环境的信息****,可以获取比如可服务应用程序的文件的绝对路径,默认是 wwwroot 的子文件夹;** ### 5.代码上的流程与实际逻辑详细流程对比(泛型主机)[#](https://www.cnblogs.com/boise/p/18002730#5.%E4%BB%A3%E7%A0%81%E4%B8%8A%E7%9A%84%E6%B5%81%E7%A8%8B%E4%B8%8E%E5%AE%9E%E9%99%85%E9%80%BB%E8%BE%91%E8%AF%A6%E7%BB%86%E6%B5%81%E7%A8%8B%E5%AF%B9%E6%AF%94%EF%BC%88%E6%B3%9B%E5%9E%8B%E4%B8%BB%E6%9C%BA%EF%BC%89) #### 代码上的流程:[#](https://www.cnblogs.com/boise/p/18002730#%E4%BB%A3%E7%A0%81%E4%B8%8A%E7%9A%84%E6%B5%81%E7%A8%8B%EF%BC%9A) 1. **Main 方法中调用**`CreateHostBuilder()`。 2. `CreateHostBuilder()` 方法调用静态方法 `Host.CreateDefaultBuilder()` 方法得到 `IHostBuilder` 构造器 。 3. **配置系统所需服务和**`ConfigureWebHostDefaults()`。 4. **返回**`IHostBuilder` 构造器。 5. **Main 方法继续调用构造器的**`Build()` 方法 -> `Run()` 方法。 #### 逻辑上的流程(源码):[#](https://www.cnblogs.com/boise/p/18002730#%E9%80%BB%E8%BE%91%E4%B8%8A%E7%9A%84%E6%B5%81%E7%A8%8B%EF%BC%88%E6%BA%90%E7%A0%81%EF%BC%89%EF%BC%9A) 1. **Host.CreateDefaultBuilder()方法,配置基础服务,并返回 IHostBuilder 构造器:** **创建一个**`IHostBuilder接口` 的 `HostBuilder实例`,根据 4 个方法来配置基础服务: **1.1** `ConfigureHostConfiguration()` 配置主机配置。 **1.2** `ConfigureLogging()` 配置日志服务。 **1.3** `ConfigureAppConfiguration()` 配置系统配置 appsetting.json 和自定义配置文件。 **1.4** `UseDefaultServiceProvider()` 配置 `ServiceProvider()` 依赖注入容器。 2. **ConfigureWebHostDefaults()注入 WebHost,配置我们自己的服务和 Http 负载支持:** **创建一个**`WebHostBuilder` 构造器,并调用 4 个方法来配置基础服务: **2.1** `UseKestrel()` 配置 Kestrel 的服务器的应用。 **2.2** `UseIIS()` 配置对 IIS 进程内运行的调用,首先判断是不是 windows,然后注册 `IISHttpServer` 服务,会覆盖 `UseKestrel()`,`UseIISIntegration()` 对 IIS 进程外运行的调用。 **2.3** `UseStart()` 配置对于 Startup.cs 文件的引用,找到后,会先找到用 Startup.cs 里面的 `ConfigureService()` 方法,然后使用 `Builder()` 方法调用。 **2.4** `services.AddHostedService<GenericWebHostService>()`,添加了一个 `IHostedService` 服务。 3. **Build()方法,生成 IHost 的实例,并配置相关服务然后返回 IHost:** **比较重要的:** **在这里会创建依赖注入容器,并依赖注入相关服务** 4. **Run()方法:** **本质上是调用的**`IHost.RunAsync()` **-> 调用的是**`IHost.StartAsync()`,它的流程是: **4.1** **从容器中调用所有的**`IHostService` 服务,然后依次调用 `StartAsync()` **包括**`ConfigureWebHostDefaults()` 中的 `WebHost` 的 `StartAsync()`,包括 `Startup.cs` 里面的 `Configuer()` 方法来创建中间件。 **4.2** **运行** ### 拓展**:**[#](https://www.cnblogs.com/boise/p/18002730#%E6%8B%93%E5%B1%95%EF%BC%9A) ### IHostService 作用(6.0 版本)[#](https://www.cnblogs.com/boise/p/18002730#ihostservice%E4%BD%9C%E7%94%A8%EF%BC%886.0%E7%89%88%E6%9C%AC%EF%BC%89) **继承实现**`IHostService接口` 中的 `StartAsync()` 方法和 `StopAsync()` 方法来管理应用启动和关闭事件,当然需要在 `Program.cs` 文件中使用 `builder.Services.AddHostService<T>()` 注入主机服务才会起作用; *ApplicationStart 类源码* ``` /// <summary> /// 应用启动和关闭事件,也可也继承IApplicationLifetime /// </summary> public class ApplicationStart : IHostedService { /// <summary> /// 应用启动 /// </summary> /// <param name="cancellationToken"></param> /// <returns></returns> public Task StartAsync(CancellationToken cancellationToken) { return Task.CompletedTask; } /// <summary> /// 应用关闭 /// </summary> /// <param name="cancellationToken"></param> /// <returns></returns> public Task StopAsync(CancellationToken cancellationToken) { return Task.CompletedTask; } } ``` ### 关于 BackgroundService 类(6.0 版本)(后台运行服务)[#](https://www.cnblogs.com/boise/p/18002730#%E5%85%B3%E4%BA%8Ebackgroundservice%E7%B1%BB%EF%BC%886.0%E7%89%88%E6%9C%AC%EF%BC%89%EF%BC%88%E5%90%8E%E5%8F%B0%E8%BF%90%E8%A1%8C%E6%9C%8D%E5%8A%A1%EF%BC%89) `BackgroundService类` 也是继承于 `IHostService`,并增加了一个 Task 的任务属性,`CancellationTokenSource` 取消令牌属性和 `ExecuteTask()` 方法来运行任务。通常用于 WokerService 服务的 `Woker` 类,同样也是需要通过 `builder.Services.AddHostService<T>()` 此方法来注入的主机服务中,以达到后台运行的目的; ---
个人天使
2025年2月10日 13:52
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档(打印)
分享
链接
类型
密码
更新密码