世界杯战报
ASP.NET Core 对本机 AOT 的支持
在 ASP.NET Core 中发布和部署本机代码提前编译(AOT)应用程序具有以下优势:
最小化的磁盘占用量。 使用本机 AOT 发布应用时,该过程将生成单个可执行文件。 可执行文件仅包含支持应用所需的外部依赖项的代码。 可执行文件大小减小可能会导致:
较小的容器映像,例如在容器化部署方案中。
缩短了较小映像的部署时间。
缩短启动时间。 本机 AOT 应用程序可能需要的启动时间更少,因此:
应用能够更快地处理请求。
改进了部署,其中容器业务流程协调程序管理从一个应用版本到另一个应用的转换。
减少了内存需求。 本机 AOT 应用程序可能需要较少的内存,这取决于应用程序所执行的具体工作。 减少内存消耗可以提高部署密度和可伸缩性。
下图显示了针对各种模板应用的基准测试的结果。 基准比较 AOT 发布的应用(橙色条)、裁剪的运行时应用(绿色条)和未裁剪的运行时应用(黄色条)的性能。 测试显示,Native AOT 应用演示了较低的应用大小、内存使用率和启动时间。
本文介绍对 ASP.NET Core 中的本机 AOT 应用的支持,包括发布和部署概述。
对于 ASP.NET Core Blazor WebAssembly 本机 AOT 指南(该指南是对本文指南的补充或替代),请参阅 ASP.NET Core Blazor WebAssembly 生成工具和提前编译 (AOT)。
查看 ASP.NET Core 和原生 AOT 兼容性
目前,并非所有 ASP.NET Core 功能都与本机 AOT 兼容。
下表汇总了 ASP.NET Core 功能与本机 AOT 的兼容性:
功能
已支持
部分支持
不支持
Blazor Server
❌
CORS
✔️
gRPC
✔️
HealthChecks
✔️
HttpLogging
✔️
JWT 身份验证
✔️
本地化
✔️
最小 API
✔️
MVC
❌
OData
❌
其他身份验证
❌
OutputCaching
✔️
RateLimiting
✔️
请求解压缩
✔️
ResponseCaching
✔️
ResponseCompression
✔️
重写
✔️
会话
❌
SignalR
✔️
水疗
❌
StaticFiles
✔️
WebSocket协议
✔️
有关限制的更多信息,请参阅:
本机 AOT 部署限制
AOT 警告
已知剪裁不兼容
修复裁剪警告
验证本机 AOT 部署模型上的应用
迁移到本机 AOT 部署模型时,必须彻底测试应用。 测试 AOT 部署的应用,确认其功能与未裁剪和即时编译 (JIT) 版本的应用相同。
生成应用时,请查看并更正任何 AOT 警告。 发布期间发出 AOT 警告 的应用可能无法正常工作。 如果在发布时未发出 AOT 警告,则预计已发布的 AOT 应用的工作方式与未处理和 JIT 编译的应用相同。
发布本机 AOT 应用 (PublishAot)
使用 PublishAot MSBuild 属性为应用程序启用本机 AOT。 以下示例演示如何在项目文件中启用 Native AOT:
该 PublishAot 属性在发布过程中启用本机 AOT 编译,并在生成和编辑期间启用动态代码使用分析。 使用本机提前编译 (Native AOT) 发布的项目在本地运行时实现 JIT 编译。
AOT 应用与 JIT 编译的应用有以下区别:
与本机 AOT 不兼容的功能会被禁用,并在运行时引发异常。
启用源分析器以突出显示与本机 AOT 不兼容的代码。 在发布时,将再次分析整个应用(包括 NuGet 包)是否兼容。
本机 AOT 分析涵盖了所有应用程序代码以及应用依赖的库。 查看本机 AOT 警告并采取纠正措施。 建议经常发布应用,以在开发生命周期的早期发现问题。
在 .NET 8 及更高版本中,以下 ASP.NET Core 应用类型支持本机 AOT:
Minimal APIs - 有关详细信息,请参阅本文后面部分中的 “查看 Web API(原生 AOT)模板”。
gRPC - 有关详细信息,请参阅 gRPC 和原生 AOT。
工作服务 - 有关详细信息,请参阅 ASP.NET Core 中托管服务与 Native AOT 的>。
查看 Web API(本机 AOT)模板
ASP.NET Core Web API(本机 AOT)模板(短名称webapiaot)创建启用了 AOT 的项目。 该模板与标准 Web API 项目模板不同,方法如下:
仅使用最小 API,因为 MVC 尚与本机 AOT 不兼容。
CreateSlimBuilder()使用 API 确保默认仅启用基本功能,从而最大程度地减少应用的已部署大小。
配置为仅侦听 HTTP。 HTTPS 流量通常由云原生部署中的入口服务处理。
不包括用于在 IIS 或 IIS Express 下运行的启动配置文件。
创建一个配置了示例 HTTP 请求的 .http 文件 ,该文件可以发送到应用的终结点。
包含一个示例 Todo API,而不是天气预报示例。
如PublishAot,将属性添加到项目文件。
启用 JSON 序列化程序源生成器。 源代码生成器用于在构建时生成序列化代码,这是本机 AOT 编译所必需的。
JSON 序列化的代码更新(Program.cs)
修改 Program.cs 文件中的代码,以提供对 JSON 序列化源生成的支持。
以下代码片段显示了代码的更改:
using MyFirstAotWebApi;
+using System.Text.Json.Serialization;
-var builder = WebApplication.CreateBuilder();
+var builder = WebApplication.CreateSlimBuilder(args);
+builder.Services.ConfigureHttpJsonOptions(options =>
+{
+ options.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonSerializerContext.Default);
+});
var app = builder.Build();
var sampleTodos = TodoGenerator.GenerateTodos().ToArray();
var todosApi = app.MapGroup("/todos");
todosApi.MapGet("/", () => sampleTodos);
todosApi.MapGet("/{id}", (int id) =>
sampleTodos.FirstOrDefault(a => a.Id == id) is { } todo
? Results.Ok(todo)
: Results.NotFound());
app.Run();
+[JsonSerializable(typeof(Todo[]))]
+internal partial class AppJsonSerializerContext : JsonSerializerContext
+{
+
+}
如果不修改代码,System.Text.Json 将使用反射来序列化和反序列化 JSON。 本机 AOT 不支持反射。
有关详细信息,请参阅:
合并源生成器
TypeInfoResolverChain
启动配置文件 (launchSettings.json) 的代码更改
Web API (本机 AOT) 模板创建 launchSettings.json 文件。 与标准启动文件相比,生成的文件不包含 iisSettings 该节或 IIS Express 配置文件。
以下代码片段显示了排除的部分(彩色红色):
{
"$schema": "http://json.schemastore.org/launchsettings.json",
- "iisSettings": {
- "windowsAuthentication": false,
- "anonymousAuthentication": true,
- "iisExpress": {
- "applicationUrl": "http://localhost:11152",
- "sslPort": 0
- }
- },
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "todos",
"applicationUrl": "http://localhost:5102",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
- "IIS Express": {
- "commandName": "IISExpress",
- "launchBrowser": true,
- "launchUrl": "todos",
- "environmentVariables": {
- "ASPNETCORE_ENVIRONMENT": "Development"
- }
- }
}
}
为最小应用默认值调用 CreateSlimBuilder()
Web API (本机 AOT) 模板使用CreateSlimBuilder()方法而不是CreateBuilder()方法。
using System.Text.Json.Serialization;
using MyFirstAotWebApi;
var builder = WebApplication.CreateSlimBuilder(args);
builder.Logging.AddConsole();
builder.Services.ConfigureHttpJsonOptions(options =>
{
options.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonSerializerContext.Default);
});
var app = builder.Build();
var sampleTodos = TodoGenerator.GenerateTodos().ToArray();
var todosApi = app.MapGroup("/todos");
todosApi.MapGet("/", () => sampleTodos);
todosApi.MapGet("/{id}", (int id) =>
sampleTodos.FirstOrDefault(a => a.Id == id) is { } todo
? Results.Ok(todo)
: Results.NotFound());
app.Run();
[JsonSerializable(typeof(Todo[]))]
internal partial class AppJsonSerializerContext : JsonSerializerContext
{
}
CreateSlimBuilder 方法使用运行应用所需的最少 ASP.NET Core 功能初始化 WebApplicationBuilder。
如前所述,该方法 CreateSlimBuilder 不包括对 HTTPS 或 HTTP/3 的支持。 在 TLS 终止代理后面运行的应用通常不需要这些协议。 例如,请参阅将 TLS 终止和端到端 TLS 与应用程序网关结合使用。 可以通过调用生成器来启用 HTTPS 。WebHost.UseKestrelHttpsConfiguration 方法,或通过调用生成器启用 HTTP/3 。WebHost.UseQuic。
比较 CreateSlimBuilder() 和 CreateBuilder()
CreateSlimBuilder 方法提供对由 CreateBuilder 方法提供的部分应用功能的访问权限。 如前所述,Web API (Native AOT) 模板调用 CreateSlimBuilder初始化 WebApplicationBuilder,因此生成器使用运行应用所需的最低 ASP.NET Core功能。
这两种方法都为高效开发体验提供了必要的功能:
appsettings.json 和 appsettings.{EnvironmentName}.json 文件的配置
用户机密配置
控制台日志输出
日志记录配置
包括最小功能对修剪和 AOT 都有好处。 有关详细信息,请参阅剪裁自包含部署和可执行文件。
如果希望使用省略所有功能的生成器,请参阅 WebApplication.CreateEmptyBuilder 方法。
CreateSlimBuilder 中的不可用功能
该CreateSlimBuilder方法不提供以下功能,这些功能在CreateBuilder中可用:
加载启动程序集
UseStartup 方法
日志记录提供程序:
Windows 事件日志
调试
EventSource
Web 托管功能:
UseStaticWebAssets 方法
IIS 集成
Kestrel 配置:
HTTPS 终结点
QUIC (HTTP/3)
路由中使用的正则表达式和字母约束(GitHub /dotnet/aspnetcore/issues #46142)
有关详细信息,请参阅 比较 WebApplication.CreateBuilder 与 CreateSlimBuilder
使用源生成器并避免反射
在本地 AOT 的发布过程中,将精简任何未使用的代码。 因此,应用无法在运行时使用未绑定的反射。 可以使用 源生成器 来生成代码,从而避免使用反射。 在某些情况下,即使不需要生成器,源生成器也会输出针对 AOT 优化的代码。
若要查看生成的源代码,请将 EmitCompilerGeneratedFiles 属性添加到应用程序项目 (.csproj) 文件:
若要查看生成的代码,请运行 dotnet build 该命令。 该命令编译源文件,并生成在开发环境中运行应用所需的中间文件。 输出包括一个 obj/Debug/<.NET version>/generated/ 目录,其中包含项目的所有生成的文件。
若要为部署准备应用,请运行 dotnet publish 该命令。 该命令编译源文件并生成部署应用所需的所有文件。 它将生成的程序集传递给本机 IL 编译器,后者生成本机可执行文件。 本机可执行文件包含本机计算机代码。
将库与 Native AOT 一起使用
ASP.NET Core项目中使用的许多常用库在集成到面向本机AOT的项目时,目前存在一些兼容性问题,例如:
使用反射检查和发现类型
在运行时有条件地加载库
动态生成代码以实现功能
使用这些动态功能的库需要进行更新,以便兼容本机 AOT。 各种工具可用于应用必要的更新,例如 Roslyn 源生成器。
鼓励希望支持本机 AOT 的库作者查看以下文章:
本机 AOT 部署
准备 .NET 库以进行精简
使用最小 API 和 JSON 有效负载
最小 API 框架已针对使用 System.Text.Json 来接收和返回 JSON 有效负载进行了优化。
命名空间对 JSON 和本机 AOT 施加兼容性要求。
它需要使用 System.Text.Json 源生成器。
在最小 API 应用中,作为 HTTP 正文的一部分传输或从请求委托返回的所有类型都必须在 JsonSerializerContext 实例上进行配置。 必须在 ASP.NET Core 的依赖注入中注册实例:
using System.Text.Json.Serialization;
using MyFirstAotWebApi;
var builder = WebApplication.CreateSlimBuilder(args);
builder.Logging.AddConsole();
builder.Services.ConfigureHttpJsonOptions(options =>
{
options.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonSerializerContext.Default);
});
var app = builder.Build();
var sampleTodos = TodoGenerator.GenerateTodos().ToArray();
var todosApi = app.MapGroup("/todos");
todosApi.MapGet("/", () => sampleTodos);
todosApi.MapGet("/{id}", (int id) =>
sampleTodos.FirstOrDefault(a => a.Id == id) is { } todo
? Results.Ok(todo)
: Results.NotFound());
app.Run();
[JsonSerializable(typeof(Todo[]))]
internal partial class AppJsonSerializerContext : JsonSerializerContext
{
}
JSON 序列化程序上下文已注册到 DI 容器。 有关详细信息,请参阅 合并源生成器 和 TypeInfoResolverChain.
该自定义 JsonSerializerContext 使用 JsonSerializable 属性标注,这个特性为 ToDo 类型启用了源代码生成的 JSON 序列化器代码。
未绑定到正文的委托参数不需要具备可序列化特性。 例如,查询字符串参数可以是实现 IParsable
public class Todo
{
public int Id { get; set; }
public string? Title { get; set; }
public DateOnly? DueBy { get; set; }
public bool IsComplete { get; set; }
}
static class TodoGenerator
{
private static readonly (string[] Prefixes, string[] Suffixes)[] _parts = new[]
{
(new[] { "Walk the", "Feed the" }, new[] { "dog", "cat", "goat" }),
(new[] { "Do the", "Put away the" }, new[] { "groceries", "dishes", "laundry" }),
(new[] { "Clean the" }, new[] { "bathroom", "pool", "blinds", "car" })
};
// Remaining code omitted for brevity.
查看已知问题
若要报告或查看 ASP.NET Core 中本机 AOT 支持的问题,请参阅 GitHub /dotnet/core/issues #8288)。
相关内容
使用 Native AOT 发布 ASP.NET Core 应用
本机 AOT 部署
优化 AOT 部署