使用 IIS 和 ASP.NET Core 进行进程内托管

注意

此版本不是本文的最新版本。 对于当前版本,请参阅此文的 .NET 8 版本

警告

此版本的 ASP.NET Core 不再受支持。 有关详细信息,请参阅 .NET 和 .NET Core 支持策略。 对于当前版本,请参阅此文的 .NET 8 版本

重要

此信息与预发布产品相关,相应产品在商业发布之前可能会进行重大修改。 Microsoft 对此处提供的信息不提供任何明示或暗示的保证。

对于当前版本,请参阅此文的 .NET 8 版本

进程内托管在与其 IIS 工作进程相同的进程中运行 ASP.NET Core 应用。 进程内承载相较进程外承载提供更优的性能,因为请求并不通过环回适配器进行代理,环回适配器是一个网络接口,用于将传出的网络流量返回给同一计算机。

下图说明了 IIS、ASP.NET Core 模块和进程内托管的应用之间的关系:

进程内托管方案中的 ASP.NET Core 模块

启用进程内托管

自 ASP.NET Core 3.0 起,默认情况下已为部署到 IIS 的所有应用启用进程内托管。

若要显式配置进程内托管的应用,请在项目文件 (.csproj) 中将 <AspNetCoreHostingModel> 属性的值设置为 InProcess

<PropertyGroup>
  <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
</PropertyGroup>

一般体系结构

请求的常规流程如下:

  1. 请求从 Web 到达内核模式 HTTP.sys 驱动程序。
  2. 驱动程序将本机请求路由到网站的配置端口上的 IIS,通常为 80 (HTTP) 或 443 (HTTPS)。
  3. ASP.NET Core 模块接收本机请求,并将其传递给 IIS HTTP 服务器 (IISHttpServer)。 IIS HTTP 服务器是将请求从本机转换为托管的 IIS 进程内服务器实现。

在 IIS HTTP 服务器处理请求后:

  1. 请求被发送到 ASP.NET Core 中间件管道。
  2. 中间件管道处理该请求并将其作为 HttpContext 实例传递给应用的逻辑。
  3. 应用的响应通过 IIS HTTP 服务器传递回 IIS。
  4. IIS 将响应发送到发起请求的客户端。

CreateDefaultBuilder 添加 IServer 实例的方式是:调用 UseIIS 方法来启动 CoreCLR 和将应用托管在 IIS 工作进程(w3wp.exeiisexpress.exe)内。 性能测试表明,与在进程外托管应用并将请求代理传入 Kestrel 相比,在进程中托管 .NET Core 应用可提供明显更高的请求吞吐量。

作为单个文件可执行文件发布的应用无法由进程内托管模型加载。

应用程序配置

要配置 IIS 选项,请在 Program.cs 中包括 IISServerOptions 的服务配置。 下面的示例将禁用 AutomaticAuthentication

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Server.IIS;
using Microsoft.EntityFrameworkCore;
using RPauth.Data;

var builder = WebApplication.CreateBuilder(args);

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();

builder.Services.Configure<IISServerOptions>(options =>
{
    options.AutomaticAuthentication = false;
});

builder.Services.AddTransient<IClaimsTransformation, MyClaimsTransformation>();
builder.Services.AddAuthentication(IISServerDefaults.AuthenticationScheme);

builder.Services.AddRazorPages();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

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

app.MapRazorPages();

app.Run();
选项 默认 设置
AutomaticAuthentication true 若为 true,IIS 服务器将设置经过 Windows 身份验证进行身份验证的 HttpContext.User。 若为 false,则服务器仅提供 HttpContext.User 的 identity 并在 AuthenticationScheme 显式请求时响应质询。 必须在 IIS 中启用 Windows 身份验证使 AutomaticAuthentication 得以运行。 有关详细信息,请参阅 Windows 身份验证
AuthenticationDisplayName null 设置在登录页上向用户显示的显示名。
AllowSynchronousIO false HttpContext.RequestHttpContext.Response 是否允许同步 I/O。
MaxRequestBodySize 30000000 获取或设置 HttpRequest 的最大请求正文大小。 请注意,IIS 本身有限制 maxAllowedContentLength,这一限制将在 IISServerOptions 中设置 MaxRequestBodySize 之前进行处理。 更改 MaxRequestBodySize 不会影响 maxAllowedContentLength。 若要增加 maxAllowedContentLength,请在 web.config 中添加一个将 maxAllowedContentLength 设置为更高值的项。 有关更多详细信息,请参阅配置

进程内和进程外托管之间的差异

在进程内托管时,将应用以下特征:

  • 使用 IIS HTTP 服务器 (IISHttpServer),而不是 Kestrel 服务器。 对于进程内托管,CreateDefaultBuilder 会调用 UseIIS 来进行以下操作:

    • 注册 IISHttpServer
    • 在 ASP.NET Core 模块后运行时,配置服务器应侦听的端口和基本路径。
    • 配置主机以捕获启动错误。
  • requestTimeout 属性不适用于进程内托管。

  • 不支持在应用之间共享应用池。 每个应用使用一个应用池。

  • 应用和已安装的运行时(x64 或 x86)的体系结构(位数)必须与应用池的体系结构匹配。 例如,为 32 位 (x86) 发布的应用必须已为其 IIS 应用程序池启用 32 位。 有关详细信息,请参阅创建 IIS 站点部分。

  • 检测到客户端连接断开。 客户端断开连接时,将取消 HttpContext.RequestAborted 取消标记。

  • 在进程内托管时,不会在内部调用 AuthenticateAsync 来初始化用户。 因此,默认情况下不激活每次身份验证后用于转换声明的 IClaimsTransformation 实现。 使用 IClaimsTransformation 实现转换声明时,请调用 AddAuthentication 以添加身份验证服务:

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Server.IIS;
using Microsoft.EntityFrameworkCore;
using RPauth.Data;

var builder = WebApplication.CreateBuilder(args);

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();

builder.Services.Configure<IISServerOptions>(options =>
{
    options.AutomaticAuthentication = false;
});

builder.Services.AddTransient<IClaimsTransformation, MyClaimsTransformation>();
builder.Services.AddAuthentication(IISServerDefaults.AuthenticationScheme);

builder.Services.AddRazorPages();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

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

app.MapRazorPages();

app.Run();

进程内托管在与其 IIS 工作进程相同的进程中运行 ASP.NET Core 应用。 进程内承载相较进程外承载提供更优的性能,因为请求并不通过环回适配器进行代理,环回适配器是一个网络接口,用于将传出的网络流量返回给同一计算机。

下图说明了 IIS、ASP.NET Core 模块和进程内托管的应用之间的关系:

进程内托管方案中的 ASP.NET Core 模块

启用进程内托管

自 ASP.NET Core 3.0 起,默认情况下已为部署到 IIS 的所有应用启用进程内托管。

若要显式配置进程内托管的应用,请在项目文件 (.csproj) 中将 <AspNetCoreHostingModel> 属性的值设置为 InProcess

<PropertyGroup>
  <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
</PropertyGroup>

一般体系结构

请求的常规流程如下:

  1. 请求从 Web 到达内核模式 HTTP.sys 驱动程序。
  2. 驱动程序将本机请求路由到网站的配置端口上的 IIS,通常为 80 (HTTP) 或 443 (HTTPS)。
  3. ASP.NET Core 模块接收本机请求,并将其传递给 IIS HTTP 服务器 (IISHttpServer)。 IIS HTTP 服务器是将请求从本机转换为托管的 IIS 进程内服务器实现。

在 IIS HTTP 服务器处理请求后:

  1. 请求被发送到 ASP.NET Core 中间件管道。
  2. 中间件管道处理该请求并将其作为 HttpContext 实例传递给应用的逻辑。
  3. 应用的响应通过 IIS HTTP 服务器传递回 IIS。
  4. IIS 将响应发送到发起请求的客户端。

CreateDefaultBuilder 添加 IServer 实例的方式是:调用 UseIIS 方法来启动 CoreCLR 和将应用托管在 IIS 工作进程(w3wp.exeiisexpress.exe)内。 性能测试表明,与在进程外托管应用并将请求代理传入 Kestrel 相比,在进程中托管 .NET Core 应用可提供明显更高的请求吞吐量。

作为单个文件可执行文件发布的应用无法由进程内托管模型加载。

应用程序配置

要配置 IIS 选项,请在 ConfigureServices 中包括 IISServerOptions 的服务配置。 下面的示例禁用 AutomaticAuthentication:

services.Configure<IISServerOptions>(options => 
{
    options.AutomaticAuthentication = false;
});
选项 默认 设置
AutomaticAuthentication true 若为 true,IIS 服务器将设置经过 Windows 身份验证进行身份验证的 HttpContext.User。 若为 false,则服务器仅提供 HttpContext.User 的 identity 并在 AuthenticationScheme 显式请求时响应质询。 必须在 IIS 中启用 Windows 身份验证使 AutomaticAuthentication 得以运行。 有关详细信息,请参阅 Windows 身份验证
AuthenticationDisplayName null 设置在登录页上向用户显示的显示名。
AllowSynchronousIO false HttpContext.RequestHttpContext.Response 是否允许同步 I/O。
MaxRequestBodySize 30000000 获取或设置 HttpRequest 的最大请求正文大小。 请注意,IIS 本身有限制 maxAllowedContentLength,这一限制将在 IISServerOptions 中设置 MaxRequestBodySize 之前进行处理。 更改 MaxRequestBodySize 不会影响 maxAllowedContentLength。 若要增加 maxAllowedContentLength,请在 web.config 中添加一个将 maxAllowedContentLength 设置为更高值的项。 有关更多详细信息,请参阅配置

进程内和进程外托管之间的差异

在进程内托管时,将应用以下特征:

  • 使用 IIS HTTP 服务器 (IISHttpServer),而不是 Kestrel 服务器。 对于进程内托管,CreateDefaultBuilder 会调用 UseIIS 来进行以下操作:

    • 注册 IISHttpServer
    • 在 ASP.NET Core 模块后运行时,配置服务器应侦听的端口和基本路径。
    • 配置主机以捕获启动错误。
  • requestTimeout 属性不适用于进程内托管。

  • 不支持在应用之间共享应用池。 每个应用使用一个应用池。

  • 应用和已安装的运行时(x64 或 x86)的体系结构(位数)必须与应用池的体系结构匹配。 例如,为 32 位 (x86) 发布的应用必须已为其 IIS 应用程序池启用 32 位。 有关详细信息,请参阅创建 IIS 站点部分。

  • 检测到客户端连接断开。 客户端断开连接时,将取消 HttpContext.RequestAborted 取消标记。

  • 在进程内托管时,不会在内部调用 AuthenticateAsync 来初始化用户。 因此,默认情况下不激活每次身份验证后用于转换声明的 IClaimsTransformation 实现。 使用 IClaimsTransformation 实现转换声明时,请调用 AddAuthentication 以添加身份验证服务:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddTransient<IClaimsTransformation, ClaimsTransformer>();
        services.AddAuthentication(IISServerDefaults.AuthenticationScheme);
    }
    
    public void Configure(IApplicationBuilder app)
    {
        app.UseAuthentication();
    }
    
  • 不支持 Web 包(单文件)部署