поддержка ASP.NET Core для машинного AOT

ASP.NET Core 8.0 предоставляет поддержку .NET native перед временем (AOT).

Зачем использовать собственный AOT с ASP.NET Core

Публикация и развертывание собственного приложения AOT обеспечивают следующие преимущества:

  • Минимальное место на диске: при публикации с помощью машинного AOT создается один исполняемый файл, содержащий только код из внешних зависимостей, необходимых для поддержки программы. Уменьшенный размер исполняемого файла может привести к следующим:
    • Небольшие образы контейнеров, например в сценариях контейнерного развертывания.
    • Сокращение времени развертывания из небольших образов.
  • Сокращение времени запуска: собственные приложения AOT могут отображать сокращенное время запуска, что означает
    • Приложение готово к обработке запросов быстрее.
    • Улучшено развертывание, в котором оркестраторы контейнеров должны управлять переходом из одной версии приложения в другую.
  • Сокращение спроса на память: собственные приложения AOT могут снизить спрос на память в зависимости от того, что выполняет приложение. Снижение потребления памяти может привести к повышению плотности развертывания и повышению масштабируемости.

Приложение шаблона было запущено в нашей лаборатории тестирования для сравнения производительности опубликованного приложения AOT, обрезаемого приложения среды выполнения и нетримированного приложения среды выполнения. На следующей диаграмме показаны результаты проверки производительности:

Chart showing comparison of application size, memory use, and startup time metrics of an AOT published app, a runtime app that is trimmed, and an untrimmed runtime app.

На приведенной выше диаграмме показано, что собственный AOT имеет меньший размер приложения, использование памяти и время запуска.

совместимость ASP.NET Core и Native AOT

В настоящее время не все функции в ASP.NET Core совместимы с Native AOT. В следующей таблице приводится сводка ASP.NET совместимость основных функций с машинным AOT:

Функция Полностью поддерживается Частично поддерживается Не поддерживается
gRPC; Полностью поддерживается
Минимальные API Частично поддерживается
MVC Не поддерживаются
Blazor Server Не поддерживаются
SignalR Не поддерживаются
Проверка подлинности JWT Полностью поддерживается
Другая проверка подлинности Не поддерживаются
CORS Полностью поддерживается
HealthChecks Полностью поддерживается
HttpLogging Полностью поддерживается
Локализация Полностью поддерживается
Кэширование выходных данных Полностью поддерживается
RateLimiting Полностью поддерживается
RequestDecompression Полностью поддерживается
Кэширование ответов Полностью поддерживается
ResponseCompression Полностью поддерживается
Переписать Полностью поддерживается
Сеанс Не поддерживаются
Спа Не поддерживаются
StaticFiles Полностью поддерживается
WebSockets Полностью поддерживается

Дополнительные сведения об ограничениях см. в следующем разделе:

Важно тщательно протестировать приложение при переходе к модели развертывания AOT в машинном коде. Развернутое приложение AOT должно быть проверено, чтобы убедиться, что функциональные возможности не изменились с нетриммированного и скомпилированного JIT-приложения. При создании приложения просмотрите и исправьте предупреждения AOT. Приложение, которое выдает предупреждения AOT во время публикации , может работать неправильно. Если предупреждения AOT не выдаются во время публикации, опубликованное приложение AOT должно работать так же, как и неисполнимое и скомпилированное JIT-приложение.

Публикация AOT в собственном коде

Собственный AOT включен со свойством PublishAot MSBuild. В следующем примере показано, как включить Собственный AOT в файле проекта:

<PropertyGroup>
  <PublishAot>true</PublishAot>
</PropertyGroup>

Этот параметр включает компиляцию машинного AOT во время публикации и включает динамический анализ использования кода во время сборки и редактирования. Проект, использующий публикацию Native AOT, использует JIT-компиляцию при локальном запуске. Приложение AOT имеет следующие отличия от скомпилированного JIT-приложения:

  • Функции, несовместимые с машинным AOT, отключены и создают исключения во время выполнения.
  • Исходный анализатор включен для выделения кода, несовместимого с машинным AOT. Во время публикации все приложение, включая пакеты NuGet, анализируется повторно для совместимости.

Анализ собственного AOT включает весь код приложения и библиотеки, от которые приложение зависит. Просмотрите предупреждения AOT в собственном коде и выполните действия по исправлению. Рекомендуется часто публиковать приложения для обнаружения проблем в начале жизненного цикла разработки.

В .NET 8 собственный AOT поддерживается следующими типами приложений ASP.NET Core:

  • Минимальные API- Дополнительные сведения см . в разделе шаблона веб-API (Native AOT) далее в этой статье.
  • gRPC — дополнительные сведения см. в разделе gRPC и Native AOT.
  • Службы рабочей роли. Дополнительные сведения см. в статье AOT в шаблонах службы рабочей роли.

Шаблон веб-API (собственный AOT)

Шаблон ASP.NET Core Web API (native AOT) (короткое имяwebapiaot) создает проект с включенным AOT. Шаблон отличается от шаблона проекта веб-API следующим образом:

  • Использует только минимальные API, так как MVC еще не совместим с машинным AOT.
  • CreateSlimBuilder() Использует API для обеспечения включения только основных функций по умолчанию, минимизируя развернутый размер приложения.
  • Настроен только для прослушивания HTTP, так как трафик HTTPS обычно обрабатывается службой входящего трафика в облачных развертываниях.
  • Не включает профиль запуска для запуска в службах IIS или IIS Express.
  • Создает файл, настроенный с примерами .http HTTP-запросов, которые можно отправлять в конечные точки приложения.
  • Включает пример Todo API вместо примера прогноза погоды.
  • Добавляет PublishAot в файл проекта, как показано ранее в этой статье.
  • JSВключает генераторы источников сериализатора ON. Генератор источника используется для создания кода сериализации во время сборки, который требуется для компиляции Машинного AOT.

Изменения для поддержки создания источника

В следующем примере показан код, добавленный в Program.cs файл для поддержки JSсоздания источника сериализации ON:

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. Рефлексия ion не поддерживается в машинном AOT.

Дополнительные сведения см. в разделе:

Изменения в launchSettings.json

Файл launchSettings.json , созданный шаблоном веб-API (Native AOT), содержит 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

Шаблон использует 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 инициализирует WebApplicationBuilder с минимальными функциями ASP.NET Core, необходимыми для запуска приложения.

Как отмечалось ранее, CreateSlimBuilder метод не поддерживает HTTPS или HTTP/3. Обычно эти протоколы не требуются для приложений, работающих за прокси-сервером завершения TLS. Например, ознакомьтесь с завершением TLS и завершением tls с помощью Шлюз приложений. HTTPS можно включить, вызвав построитель вызовов . WebHost.UseKestrelHttpsConfiguration HTTP/3 можно включить с помощью построителя вызовов . WebHost.UseQuic.

CreateSlimBuilder и CreateBuilder

Метод CreateSlimBuilder не поддерживает следующие функции, поддерживаемые методом CreateBuilder :

Этот CreateSlimBuilder метод включает следующие функции, необходимые для эффективной разработки.

  • JSКонфигурация ФАЙЛА ON для appsettings.json и appsettings.{EnvironmentName}.json.
  • Конфигурация секретов пользователей.
  • Ведение журнала консоли.
  • Конфигурация ведения журнала.

Построитель, который исключает предыдущие функции, см. в разделе " CreateEmptyBuilder Метод".

Включая минимальные функции имеют преимущества для обрезки, а также AOT. Дополнительные сведения см. в статье Обрезка автономных развертываний и исполняемых файлов.

Дополнительные сведения см. в разделе "Сравнение WebApplication.CreateBuilder с" CreateSlimBuilder

Генераторы исходного кода

Так как неиспользуемый код обрезается во время публикации для Машинного AOT, приложение не может использовать незавязанное отражение во время выполнения. Генераторы источников используются для создания кода, который позволяет избежать необходимости отражения. В некоторых случаях генераторы источников создают код, оптимизированный для AOT, даже если генератор не требуется.

Чтобы просмотреть созданный исходный код, добавьте EmitCompilerGeneratedFiles свойство в файл приложения .csproj , как показано в следующем примере:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <!-- Other properties omitted for brevity -->
    <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
  </PropertyGroup>

</Project>

dotnet build Выполните команду, чтобы просмотреть созданный код. Выходные данные включают obj/Debug/net8.0/generated/ каталог, содержащий все созданные файлы для проекта.

Команда dotnet publish также компилирует исходные файлы и создает скомпилированные файлы. Кроме того, dotnet publish передает созданные сборки собственному компилятору IL. Компилятор IL создает собственный исполняемый файл. Собственный исполняемый файл содержит машинный код.

Библиотеки и собственный AOT

Многие популярные библиотеки, используемые в проектах ASP.NET Core, в настоящее время имеют некоторые проблемы совместимости при использовании в проекте, предназначенных для собственного AOT, например:

  • Использование отражения для проверки и обнаружения типов.
  • Условное загрузка библиотек во время выполнения.
  • Создание кода на лету для реализации функциональных возможностей.

Библиотеки, использующие эти динамические функции, необходимо обновить для работы с машинным AOT. Их можно обновить с помощью таких средств, как генераторы источников Roslyn.

Авторы библиотеки, надеясь поддержать Собственный AOT, рекомендуется:

Минимальные API и JSполезные данные ON

Минимальная платформа API оптимизирована для получения и возврата JSполезных данных ON с помощью System.Text.Json. System.Text.Json:

  • Накладывает требования к совместимости для JSON и Native AOT.
  • Требуется использование генератора System.Text.Json источника.

Все типы, передаваемые в составе текста HTTP или возвращенные делегатами запросов в приложениях Минимальных API, должны быть настроены для 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
{

}

В предыдущем выделенном коде:

Параметр делегата, который не привязан к тексту и не должен быть сериализуемым. Например, параметр строки запроса, который является типом расширенных объектов и реализует IParsable<T>.

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.

Известные проблемы

Ознакомьтесь с этой проблемой GitHub, чтобы сообщить о проблемах с поддержкой Native AOT в ASP.NET Core.

См. также