obsługa platformy ASP.NET Core dla natywnej usługi AOT

Autor: Mitch Denny

Publikowanie i wdrażanie natywnie kompilowanych aplikacji AOT w ASP.NET Core oferuje kilka korzyści:

  • Zminimalizowane zużycie dysku. Podczas publikowania aplikacji przy użyciu natywnej funkcji AOT proces tworzy pojedynczy plik wykonywalny. Plik wykonywalny zawiera tylko kod z zależności zewnętrznych wymaganych do obsługi aplikacji. Zmniejszony rozmiar pliku wykonywalnego może prowadzić do:

    • Mniejsze obrazy kontenerów, na przykład w scenariuszach wdrażania konteneryzowanego.
    • Skrócony czas wdrażania dzięki mniejszym obrazom.
  • Skrócony czas uruchamiania. Natywne aplikacje AOT mogą wymagać mniejszego czasu uruchamiania, co umożliwia:

    • Aplikacja do szybszego realizowania żądań.
    • Ulepszone wdrożenie, w którym koordynatorzy kontenerów zarządzają przejściem z jednej wersji aplikacji do innej.
  • Zmniejszone zapotrzebowanie na pamięć. Natywne aplikacje AOT mogą wymagać mniejszej ilości pamięci, w zależności od pracy wykonywanej przez aplikację. Zmniejszenie zużycia pamięci może prowadzić do większej gęstości wdrożenia i zwiększenia skalowalności.

Wykres poniżej przedstawia wyniki testu porównawczego różnych aplikacji ze wzorcami. Test porównawczy porównuje wydajność opublikowanej aplikacji AOT (pomarańczowy pasek), przyciętej aplikacji środowiska uruchomieniowego (zielony pasek) i niezatrimowanej aplikacji środowiska uruchomieniowego (żółty pasek). Test wykazał, że aplikacja natywna AOT pokazuje mniejszy rozmiar aplikacji, użycie pamięci i czas uruchamiania.

Wykres przedstawiający porównanie rozmiaru aplikacji, użycia pamięci i metryk czasu uruchamiania. Wykres porównuje opublikowaną natywną aplikację AOT, przyciętą aplikację środowiska uruchomieniowego i nietrimowaną aplikację środowiska uruchomieniowego.

W tym artykule opisano obsługę natywnych aplikacji AOT w ASP.NET Core, w tym omówienie publikowania i wdrażania.

Aby uzyskać Natywne wytyczne dotyczące ASP.NET Core Blazor WebAssembly AOT, dodające lub zastępujące wskazówki zawarte w tym artykule, zobacz ASP.NET Core Blazor WebAssembly narzędzia do budowy i kompilacji AOT.

Przegląd zgodności ASP.NET Core i natywnej funkcji AOT

Nie wszystkie funkcje w systemie ASP.NET Core są obecnie zgodne z natywną funkcją AOT.

Poniższa tabela zawiera podsumowanie zgodności funkcji ASP.NET Core z natywną funkcją AOT.

Funkcja Supported Częściowa obsługa Niewspierane
Blazor Server ❌
CORS ✔️
gRPC ✔️
Kontrole kondycji ✔️
Logowanie HTTP ✔️
JWT Uwierzytelniania ✔️
Lokalizacja ✔️
Minimalne API ✔️
MVC ❌
OData ❌
Inne uwierzytelnianie ❌
BuforowanieWyników ✔️
Ograniczanie częstotliwości ✔️
Żądanie dekompresji ✔️
BuforowanieOdpowiedzi ✔️
Kompresja odpowiedzi ✔️
Przepisać ✔️
Sesja ❌
SignalR ✔️
Uzdrowisko ❌
StaticFiles ✔️
WebSocket ✔️

Aby uzyskać więcej informacji na temat ograniczeń, zobacz:

Weryfikowanie aplikacji w natywnym modelu wdrażania AOT

Ważne jest, aby dokładnie przetestować aplikację podczas przechodzenia do natywnego modelu wdrażania AOT. Przetestuj aplikację wdrożoną za pomocą AOT i upewnij się, że funkcjonalność jest niezmieniona w porównaniu z nieprzyciętą i skompilowaną just-in-time (JIT) aplikacją.

Kiedy kompilujesz aplikację, przejrzyj i popraw wszelkie ostrzeżenia dotyczące AOT. Aplikacja, która wyświetla ostrzeżenia AOT podczas publikowania, może nie działać poprawnie. Jeśli w czasie publikacji nie są wydawane żadne ostrzeżenia AOT, możesz oczekiwać, że opublikowana aplikacja AOT będzie działać tak samo jak nieskrócona i skompilowana JIT aplikacja.

Publikowanie natywnej aplikacji AOT (PublishAot)

Włącz natywną funkcję AOT dla aplikacji przy użyciu PublishAot właściwości MSBuild. W poniższym przykładzie pokazano, jak włączyć natywną funkcję AOT w pliku projektu:

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

Właściwość PublishAot włącza natywną kompilację AOT podczas procesu publikowania i umożliwia dynamiczną analizę użycia kodu podczas kompilacji i edycji. Projekt korzystający z natywnego publikowania AOT implementuje kompilację JIT podczas uruchamiania lokalnie.

Aplikacja AOT ma następujące różnice w porównaniu z aplikacją skompilowana w trybie JIT:

  • Cechy, które nie są zgodne z natywnym AOT, są wyłączane i zgłaszają wyjątki w czasie działania programu.
  • Analizator źródła został włączony, aby wyróżnić kod, który nie jest zgodny z Native AOT. W czasie publikowania cała aplikacja, w tym pakiety NuGet, jest ponownie analizowana pod kątem zgodności.

Natywna analiza AOT obejmuje cały kod aplikacji i biblioteki, od których zależy aplikacja. Przejrzyj ostrzeżenia dotyczące natywnej usługi AOT i wykonaj kroki naprawcze. Dobrym pomysłem jest częste publikowanie aplikacji w celu wykrycia problemów na wczesnym etapie cyklu projektowania.

W .NET 8 lub nowszych następujące typy aplikacji ASP.NET Core obsługują natywną AOT:

  • Minimalne API — aby uzyskać więcej informacji, zobacz Przegląd szablonu interfejsu API (natywne AOT) w dalszej części tego artykułu.
  • gRPC — aby uzyskać więcej informacji, zobacz gRPC i Native AOT.
  • Worker services — Aby uzyskać więcej informacji, zapoznaj się z zadaniami w tle z hostowanymi usługami w ASP.NET Core oraz Native AOT.

Przeglądanie szablonu interfejsu API sieci webowej (natywne AOT)

Szablon ASP.NET Core Web API (Native AOT) (krótka nazwa webapiaot) tworzy projekt z włączoną funkcją AOT. Szablon różni się od standardowego szablonu projektu internetowego interfejsu API w następujący sposób:

  • Używa tylko minimalnych interfejsów API, ponieważ MVC nie jest jeszcze zgodne z Native AOT.
  • Używa interfejsu CreateSlimBuilder() API, aby upewnić się, że domyślnie są włączone tylko podstawowe funkcje, co minimalizuje rozmiar wdrożonej aplikacji.
  • Jest skonfigurowany do nasłuchiwania tylko w protokole HTTP. Ruch HTTPS jest często obsługiwany przez usługę ruchu przychodzącego we wdrożeniach natywnych dla chmury.
  • Nie zawiera profilu uruchamiania do działania w środowiskach IIS lub IIS Express.
  • Tworzy plik HTTP skonfigurowany przy użyciu przykładowych żądań HTTP, które można wysyłać do punktów końcowych aplikacji.
  • Zawiera przykładowy interfejs API Todo zamiast przykładowej prognozy pogody.
  • Dodaje właściwość PublishAot do pliku projektu, jak wcześniej opisano.
  • Włącza generatory źródłowe serializatora JSON. Generator źródła służy do generowania kodu serializacji w czasie kompilacji, który jest wymagany do kompilacji natywnej AOT.

Aktualizacje kodu serializacji JSON (Program.cs)

Kod w pliku Program.cs jest modyfikowany w celu zapewnienia obsługi generowania źródła serializacji JSON.

Poniższy fragment kodu przedstawia zmiany w kodzie:

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
+{
+
+}

Jeśli nie zmodyfikujesz kodu, System.Text.Json użyje refleksji w celu serializacji i deserializacji JSON. Refleksja nie jest obsługiwana w natywnej AOT.

Aby uzyskać więcej informacji, zobacz:

Zmiany kodu profilu uruchamiania (launchSettings.json)

Szablon internetowego interfejsu API (natywny AOT) tworzy plik launchSettings.json . W przeciwieństwie do standardowego pliku uruchamiania wygenerowany plik nie zawiera iisSettings sekcji ani IIS Express profilu.

Poniższy fragment kodu przedstawia wykluczone sekcje (kolor czerwony):

{
  "$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"
-      }
-    }
  }
}

Metoda CreateSlimBuilder() wywoływana dla minimalnych wartości domyślnych aplikacji

Szablon Web API (natywnego AOT) używa metody CreateSlimBuilder() zamiast 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
{
}

Metoda CreateSlimBuilder inicjuje WebApplicationBuilder z minimalnym zestawem funkcji ASP.NET Core niezbędnymi do uruchomienia aplikacji.

Jak opisano wcześniej, CreateSlimBuilder metoda nie obejmuje obsługi protokołu HTTPS ani HTTP/3. Te protokoły zazwyczaj nie są wymagane w przypadku aplikacji uruchamianych za serwerem proxy zakończenia protokołu TLS. Zobacz na przykład terminację TLS i szyfrowanie TLS typu end-to-end za pomocą usługi Application Gateway. Protokół HTTPS można włączyć, wywołując metodę builder.WebHost.UseKestrelHttpsConfiguration, albo włączyć protokół HTTP/3 poprzez wywołanie builder.WebHost.UseQuic.

Porównaj CreateSlimBuilder() i CreateBuilder()

Metoda CreateSlimBuilder zapewnia dostęp do części funkcji aplikacji dostępnych w metodzie CreateBuilder . Jak opisano wcześniej, szablon Web API (Native AOT) wywołuje , aby zainicjować , dlatego konstruktor używa minimalnych funkcji ASP.NET Core koniecznych do działania aplikacji.

Obie metody zapewniają niezbędne funkcje do wydajnego środowiska programistycznego:

  • Konfiguracja appsettings.json i appsettings.{ EnvironmentName}.json plików
  • Konfiguracja wpisów tajnych użytkownika
  • Rejestrowanie konsoli
  • Konfiguracja rejestrowania

Uwzględnienie minimalnych funkcji przynosi korzyści dla przycinania oraz AOT. Aby uzyskać więcej informacji, zobacz Przycinanie samodzielnych wdrożeń i plików wykonywalnych.

Jeśli wolisz użyć konstruktora, który pomija wszystkie funkcje, zobacz metodę WebApplication.CreateEmptyBuilder .

Niedostępne funkcje w programie CreateSlimBuilder

Metoda CreateSlimBuildernie udostępnia następujących funkcji, które są dostępne w programie CreateBuilder:

Aby uzyskać bardziej szczegółowe informacje, zobacz Porównanie elementu WebApplication.CreateBuilder z CreateSlimBuilder

Używanie generatorów źródłowych i unikanie odbicia

Podczas procesu publikowania dla natywnej AOT wszystkie nieużywane kody są usuwane. W związku z tym aplikacja nie może używać niezwiązanego odbicia w czasie wykonywania. Możesz użyć generatorów źródłowych , które generują kod, który pozwala uniknąć konieczności odbicia. W niektórych przypadkach generatory źródeł generują kod wyjściowy zoptymalizowany pod kątem AOT nawet wtedy, gdy generator nie jest wymagany.

  • Aby wyświetlić wygenerowany kod źródłowy, dodaj właściwość EmitCompilerGeneratedFiles do pliku projektu aplikacji (csproj):

    <Project Sdk="Microsoft.NET.Sdk.Web">
    
       <PropertyGroup>
         <!-- Other properties omitted for brevity -->
         <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
       </PropertyGroup>
    
    </Project>
    
  • Aby wyświetlić wygenerowany kod, uruchom dotnet build polecenie . Polecenie kompiluje pliki źródłowe i generuje pliki pośrednie potrzebne do uruchomienia aplikacji w środowisku programistycznym. Dane wyjściowe obejmują katalog obj/Debug/<.NET wersja>/generated/, który zawiera wszystkie wygenerowane pliki dla projektu.

  • Aby przygotować aplikację do wdrożenia, uruchom dotnet publish polecenie . Polecenie kompiluje pliki źródłowe i generuje wszystkie pliki wymagane do wdrożenia aplikacji. Przekazuje wygenerowane zestawy do natywnego kompilatora IL, który generuje natywny plik wykonywalny. Natywny plik wykonywalny zawiera natywny kod maszyny.

Używanie bibliotek z natywnym AOT

Wiele popularnych bibliotek używanych w projektach ASP.NET Core ma obecnie pewne problemy ze zgodnością, gdy są one włączone do projektów przeznaczonych do pracy z Native AOT, takich jak:

  • Używanie odbicia do sprawdzania i odnajdywania typów
  • Ładowanie bibliotek warunkowo podczas wykonywania programu
  • Generowanie kodu na bieżąco w celu zaimplementowania funkcji

Biblioteki korzystające z tych funkcji dynamicznych wymagają aktualizacji do pracy z natywną funkcją AOT. Dostępne są różne narzędzia do stosowania niezbędnych aktualizacji, takich jak generatory źródeł Roslyn.

Autorzy bibliotek, którzy chcą wspierać natywny AOT, są zachęcani do przejrzenia następujących artykułów:

Praca z minimalnymi interfejsami API i ładunkami JSON

Minimalna struktura interfejsu API jest zoptymalizowana pod kątem odbierania i zwracania ładunków JSON przy użyciu elementu System.Text.Json.

Wszystkie typy przesyłane jako część treści HTTP lub zwracane przez delegatów żądań w aplikacjach typu Minimal API muszą zostać skonfigurowane na instancji JsonSerializerContext. Wystąpienie musi zostać zarejestrowane za pomocą iniekcji zależności 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
{
}
  • Kontekst serializatora JSON jest zarejestrowany w kontenerze DI. Aby uzyskać więcej informacji, zobacz Łączenie generatorów źródeł oraz TypeInfoResolverChain.

  • Element niestandardowy JsonSerializerContext jest oznaczony adnotacją z użyciem atrybutu JsonSerializable, co umożliwia generowanie na poziomie źródła kodu serializatora JSON dla typu ToDo.

Parametr delegata, który nie jest powiązany z treścią , nie musi być serializowalny. Na przykład parametr ciągu zapytania może być bogatym typem obiektu, który implementuje element 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.

Przejrzyj znane problemy

Aby zgłosić lub przejrzeć problemy z natywną obsługą AOT w ASP.NET Core, zobacz GitHub /dotnet/core/issues #8288).

Platforma .NET 8 wprowadza obsługę natywnej kompilacji .NET wykonywanej z wyprzedzeniem (AOT).

Dlaczego warto używać natywnej AOT z platformą ASP.NET Core

Publikowanie i wdrażanie natywnej aplikacji AOT zapewnia następujące korzyści:

  • Zminimalizowane zużycie dysku: podczas publikowania przy użyciu natywnej funkcji AOT jest tworzony pojedynczy plik wykonywalny zawierający tylko kod z zależności zewnętrznych, które są potrzebne do obsługi programu. Zmniejszony rozmiar pliku wykonywalnego może prowadzić do:
    • Mniejsze obrazy kontenerów, na przykład w scenariuszach wdrażania konteneryzowanego.
    • Skrócony czas wdrażania dzięki mniejszym obrazom.
  • Skrócony czas uruchamiania: natywne aplikacje AOT mogą pokazywać skrócone czasy uruchamiania, co oznacza
    • Aplikacja jest gotowa do szybszego obsługi żądań.
    • Ulepszone wdrożenie, w którym koordynatorzy kontenerów muszą zarządzać przejściem z jednej wersji aplikacji do innej.
  • Mniejsze zapotrzebowanie na pamięć: natywne aplikacje AOT mogą mieć mniejsze zapotrzebowanie na pamięć w zależności od pracy wykonywanej przez aplikację. Zmniejszenie zużycia pamięci może prowadzić do większej gęstości wdrożenia i zwiększenia skalowalności.

Aplikacja szablonu została uruchomiona w naszym laboratorium porównawczym, aby porównać wydajność aplikacji opublikowanej w trybie AOT, aplikacji wykonanej w przyciętym środowisku uruchomieniowym i aplikacji wykonanej w nieprzyciętym środowisku uruchomieniowym. Na poniższym wykresie przedstawiono wyniki testów porównawczych:

Wykres przedstawiający porównanie metryk rozmiaru aplikacji, użycia pamięci i czasu uruchamiania aplikacji opublikowanej z użyciem AOT, przycinanej aplikacji środowiska uruchomieniowego oraz nieskracanej aplikacji środowiska uruchomieniowego.

Na poprzednim wykresie pokazano, że natywna usługa AOT ma mniejszy rozmiar aplikacji, użycie pamięci i czas uruchamiania.

Kompatybilność ASP.NET Core i Native AOT

Nie wszystkie funkcje w systemie ASP.NET Core są obecnie zgodne z natywną funkcją AOT. Poniższa tabela zawiera podsumowanie zgodności funkcji ASP.NET Core z natywną funkcją AOT.

Funkcja W pełni obsługiwane Częściowo wspierane Nie jest obsługiwany
gRPC W pełni obsługiwane
Minimalne API Częściowo obsługiwane
MVC Nieobsługiwane
Blazor Server Nieobsługiwane
SignalR Nieobsługiwane
JWT Uwierzytelniania W pełni obsługiwane
Inne uwierzytelnianie Nieobsługiwane
CORS W pełni obsługiwane
Kontrole kondycji W pełni obsługiwane
Logowanie HTTP W pełni obsługiwane
Lokalizacja W pełni obsługiwane
BuforowanieWyników W pełni obsługiwane
Ograniczanie częstotliwości W pełni obsługiwane
Żądanie dekompresji W pełni obsługiwane
BuforowanieOdpowiedzi W pełni obsługiwane
Kompresja odpowiedzi W pełni obsługiwane
Przepisać W pełni obsługiwane
Sesja Nieobsługiwane
Uzdrowisko Nieobsługiwane
StaticFiles W pełni obsługiwane
WebSocket W pełni obsługiwane

Aby uzyskać więcej informacji na temat ograniczeń, zobacz:

Ważne jest, aby dokładnie przetestować aplikację podczas przechodzenia do natywnego modelu wdrażania AOT. Aplikacja AOT wdrożona powinna zostać przetestowana w celu sprawdzenia, czy funkcjonalność pozostała niezmieniona w porównaniu do nietrimowanej i skompilowanej za pomocą JIT aplikacji. Podczas kompilowania aplikacji przejrzyj i popraw ostrzeżenia dotyczące AOT. Aplikacja, która wystawia ostrzeżenia AOT podczas publikowania, może nie działać poprawnie. Jeśli w czasie publikowania nie zostaną wydane żadne ostrzeżenia dotyczące funkcji AOT, opublikowana aplikacja AOT powinna działać tak samo jak aplikacja nieskrócona i skompilowana za pomocą JIT.

Publikowanie natywne AOT

Natywna funkcja AOT jest włączona z właściwością PublishAot MSBuild. W poniższym przykładzie pokazano, jak włączyć natywną funkcję AOT w pliku projektu:

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

To ustawienie umożliwia natywną kompilację AOT podczas publikowania i umożliwia dynamiczną analizę użycia kodu podczas kompilacji i edycji. Projekt korzystający z natywnego publikowania AOT używa kompilacji JIT podczas uruchamiania lokalnego. Aplikacja AOT ma następujące różnice w porównaniu z aplikacją skompilowana w trybie JIT:

  • Cechy, które nie są zgodne z natywnym AOT, są wyłączane i zgłaszają wyjątki w czasie działania programu.
  • Analizator źródła został włączony, aby wyróżnić kod, który nie jest zgodny z Native AOT. W czasie publikowania cała aplikacja, w tym pakiety NuGet, jest ponownie analizowana pod kątem zgodności.

Natywna analiza AOT obejmuje cały kod aplikacji i biblioteki, od których zależy aplikacja. Przejrzyj ostrzeżenia dotyczące natywnej usługi AOT i wykonaj kroki naprawcze. Dobrym pomysłem jest częste publikowanie aplikacji w celu wykrycia problemów na wczesnym etapie cyklu projektowania.

Na platformie .NET 8 natywna funkcja AOT jest obsługiwana przez następujące typy aplikacji ASP.NET Core:

Szablon interfejsu API sieci Web (natywne AOT)

Szablon ASP.NET Core Web API (Native AOT) (krótkie oznaczenie webapiaot) tworzy projekt z włączoną funkcją AOT. Szablon różni się od szablonu projektu Web API w następujący sposób:

  • Używa tylko minimalnych interfejsów API, ponieważ MVC nie jest jeszcze zgodne z Native AOT.
  • Używa interfejsu CreateSlimBuilder() API, aby upewnić się, że tylko podstawowe funkcje są domyślnie włączone, minimalizując rozmiar wdrożonej aplikacji.
  • Jest skonfigurowany do nasłuchiwania tylko w protokole HTTP, ponieważ ruch HTTPS jest często obsługiwany przez usługę ruchu przychodzącego we wdrożeniach natywnych dla chmury.
  • Nie zawiera profilu uruchamiania do działania w środowiskach IIS lub IIS Express.
  • .http Tworzy plik skonfigurowany przy użyciu przykładowych żądań HTTP, które można wysyłać do punktów końcowych aplikacji.
  • Zawiera przykładowy interfejs API Todo zamiast przykładowej prognozy pogody.
  • Dodaje PublishAot do pliku projektu, jak pokazano wcześniej w tym artykule.
  • Włącza generatory źródłowe serializatora JSON. Generator źródła służy do generowania kodu serializacji w czasie kompilacji, który jest wymagany do kompilacji natywnej AOT.

Zmiany w zakresie obsługi generowania kodu źródłowego

W poniższym przykładzie pokazano kod dodany do Program.cs pliku w celu obsługi generowania źródła serializacji 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
+{
+
+}

Bez tego dodanego kodu System.Text.Json używa refleksji w celu serializacji i deserializacji JSON. Refleksja nie jest obsługiwana w natywnej AOT.

Aby uzyskać więcej informacji, zobacz:

Zmiany do launchSettings.json

Plik launchSettings.json utworzony przez szablon Web API (natywny AOT) ma usuniętą sekcję iisSettings oraz profil 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"
-      }
-    }
  }
}

Metoda CreateSlimBuilder

Szablon używa CreateSlimBuilder() metody zamiast CreateBuilder() metody .

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
{
}

Metoda CreateSlimBuilder inicjuje WebApplicationBuilder z minimalnym zestawem funkcji ASP.NET Core niezbędnymi do uruchomienia aplikacji.

Jak wspomniano wcześniej, CreateSlimBuilder metoda nie obejmuje obsługi protokołu HTTPS lub HTTP/3. Te protokoły zazwyczaj nie są wymagane w przypadku aplikacji uruchamianych za serwerem proxy zakończenia protokołu TLS. Zobacz na przykład terminację TLS i szyfrowanie TLS typu end-to-end za pomocą usługi Application Gateway. Protokół HTTPS można włączyć, wywołując konstruktora builder.WebHost.UseKestrelHttpsConfiguration. Protokół HTTP/3 można włączyć, wywołując konstruktora builder.WebHost.UseQuic.

Klasa CreateSlimBuilder a klasa CreateBuilder

Metoda CreateSlimBuilder nie obsługuje następujących funkcji obsługiwanych przez metodę CreateBuilder :

Metoda CreateSlimBuilder zawiera następujące funkcje potrzebne do wydajnego środowiska programistycznego:

  • Konfiguracja pliku JSON dla elementów appsettings.json i appsettings.{EnvironmentName}.json.
  • Konfiguracja tajnych danych użytkownika.
  • Logowanie konsoli.
  • Konfiguracja rejestrowania.

Aby zapoznać się z narzędziem budowania, które pomija wcześniejsze funkcjonalności, zobacz Metoda CreateEmptyBuilder.

Uwzględnienie minimalnych funkcji przynosi korzyści dla przycinania oraz AOT. Aby uzyskać więcej informacji, zobacz Przycinanie samodzielnych wdrożeń i plików wykonywalnych.

Aby uzyskać bardziej szczegółowe informacje, zobacz Porównanie WebApplication.CreateBuilder z CreateSlimBuilder

Generatory źródeł

Ponieważ nieużywany kod jest usuwany podczas publikowania w kontekście natywnego AOT, aplikacja nie może używać nieograniczonego odbicia w czasie wykonywania. Generatory źródeł są używane do tworzenia kodu, który pozwala uniknąć konieczności odbicia. W niektórych przypadkach generatory źródłowe generują kod zoptymalizowany pod kątem AOT nawet wtedy, gdy generator nie jest wymagany.

Aby wyświetlić wygenerowany kod źródłowy, dodaj właściwość EmitCompilerGeneratedFiles do pliku .csproj aplikacji, jak pokazano w poniższym przykładzie.

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

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

</Project>

Uruchom polecenie , dotnet build aby wyświetlić wygenerowany kod. Dane wyjściowe zawierają obj/Debug/net8.0/generated/ katalog zawierający wszystkie wygenerowane pliki dla projektu.

Polecenie dotnet publish kompiluje również pliki źródłowe i generuje skompilowane pliki. Ponadto dotnet publish przekazuje wygenerowane zestawy do natywnego kompilatora IL. Kompilator IL tworzy natywny plik wykonywalny. Natywny plik wykonywalny zawiera natywny kod maszyny.

Używanie bibliotek z natywnym AOT

Wiele popularnych bibliotek używanych w projektach ASP.NET Core ma obecnie pewne problemy ze zgodnością, gdy są one włączone do projektów przeznaczonych do pracy z Native AOT, takich jak:

  • Używanie odbicia do sprawdzania i odnajdywania typów
  • Ładowanie bibliotek warunkowo podczas wykonywania programu
  • Generowanie kodu na bieżąco w celu zaimplementowania funkcji

Biblioteki korzystające z tych funkcji dynamicznych wymagają aktualizacji do pracy z natywną funkcją AOT. Dostępne są różne narzędzia do stosowania niezbędnych aktualizacji, takich jak generatory źródeł Roslyn.

Autorzy bibliotek, którzy chcą wspierać natywny AOT, są zachęcani do przejrzenia następujących artykułów:

Minimalne interfejsy API i ładunki JSON

Minimalna struktura interfejsu API jest zoptymalizowana pod kątem odbierania i zwracania ładunków JSON przy użyciu polecenia System.Text.Json. System.Text.Json:

  • Nakłada wymagania dotyczące zgodności dla formatu JSON i natywnego AOT.
  • Wymaga użycia generatora źródeł System.Text.Json.

Wszystkie typy przesyłane jako część treści żądania HTTP lub zwracane przez delegaty żądań w aplikacjach Minimal APIs muszą być skonfigurowane w elemencie JsonSerializerContext, który jest zarejestrowany w mechanizmie wstrzykiwania zależności 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
{
}

W poprzednim wyróżnionym kodzie:

Parametr delegata, który nie jest powiązany z treścią i nie musi być serializowalny. Na przykład parametr ciągu zapytania, który jest bogatym typem obiektu i implementuje element 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.

Znane problemy

Zobacz to zadanie GitHub, aby zgłosić lub przejrzeć problemy z natywną obsługą Native AOT w ASP.NET Core.

Zobacz też