Udostępnij za pośrednictwem


przegląd sieciowania wewnętrznej pętli .NET.NET Aspire

Jedną z zalet programowania przy użyciu .NET.NET Aspire jest możliwość lokalnego tworzenia, testowania i debugowania aplikacji natywnych dla chmury. Sieć w pętli wewnętrznej jest kluczowym aspektem .NET.NET Aspire, który umożliwia aplikacjom komunikowanie się ze sobą w środowisku deweloperskim. W tym artykule dowiesz się, jak .NET.NET Aspire obsługuje różne scenariusze sieciowe z serwerami proxy, punktami końcowymi, konfiguracjami punktów końcowych i profilami uruchamiania.

Sieciowanie w wewnętrznej pętli

Pętla wewnętrzna to proces tworzenia i testowania aplikacji lokalnie przed wdrożeniem jej w środowisku docelowym. .NET .NET Aspire udostępnia kilka narzędzi i funkcji, które upraszczają i rozszerzają środowisko sieciowe w pętli wewnętrznej, takie jak:

  • Profile uruchamiania: Profile uruchamiania to pliki konfiguracji określające sposób uruchamiania aplikacji lokalnie. Profile uruchamiania (takie jak plik launchSettings.json) umożliwiają definiowanie punktów końcowych, zmiennych środowiskowych i ustawień uruchamiania aplikacji.
  • konfiguracja Kestrel: konfiguracja Kestrel umożliwia określenie punktów końcowych, na których nasłuchuje serwer internetowy Kestrel. Punkty końcowe Kestrel można skonfigurować w ustawieniach aplikacji, a .NET.NET Aspire automatycznie używa tych ustawień do tworzenia punktów końcowych.
  • Konfiguracje punktów końcowych/Punkty końcowe: Punkty końcowe to połączenia między Twoją aplikacją a usługami, od których zależy, takimi jak bazy danych, kolejki komunikatów lub interfejsy API. Punkty końcowe zawierają informacje, takie jak nazwa usługi, port hosta, schemat i zmienna środowiskowa. Punkty końcowe można dodawać do aplikacji niejawnie (za pośrednictwem profilów uruchamiania) lub jawnie, wywołując WithEndpoint.
  • Proxies: .NET.NET Aspire automatycznie uruchamia serwer proxy dla każdego powiązania usługi dodawanego do aplikacji i przypisuje port, aby serwer proxy mógł nasłuchiwać. Następnie serwer proxy przekazuje żądania do portu, na którym nasłuchuje aplikacja, co może różnić się od portu serwera proxy. Dzięki temu można uniknąć konfliktów portów i uzyskać dostęp do aplikacji i usług przy użyciu spójnych i przewidywalnych adresów URL.

Jak działają punkty końcowe

Powiązanie usługi w .NET.NET Aspire obejmuje dwie integracje: usługę reprezentującą zasób zewnętrzny wymagany przez aplikację (na przykład bazę danych, kolejkę komunikatów lub interfejs API) oraz powiązanie, które ustanawia połączenie między aplikacją a usługą i udostępnia niezbędne informacje.

.NET .NET Aspire obsługuje dwa typy powiązań usługi: niejawne, automatycznie tworzone na podstawie określonych profilów uruchamiania definiujących zachowanie aplikacji w różnych środowiskach, a jawne, utworzone ręcznie przy użyciu WithEndpoint.

Podczas tworzenia połączenia, niezależnie od tego, czy jest jawne, czy ukryte, .NET.NET Aspire uruchamia lekki zwrotny serwer proxy na określonym porcie, odpowiadając za routing i równoważenie obciążenia dla żądań z aplikacji do usługi. Proxy to .NET.NET Aspire szczegół implementacji, który nie wymaga konfiguracji ani zarządzania.

Aby ułatwić wizualizację działania punktów końcowych, rozważ diagram sieci wewnętrznej pętli w szablonach startowych .NET.NET Aspire.

.NET.NET Aspire diagram sieciowy pętli wewnętrznej szablonu aplikacji startowej.

Uruchamianie profilów

Podczas wywoływania AddProjecthost aplikacji wyszukuje Właściwości/launchSettings.json w celu określenia domyślnego zestawu punktów końcowych. Host aplikacji wybiera określony profil uruchamiania przy użyciu następujących reguł:

  1. Jawny argument launchProfileName przekazywany podczas wywoływania AddProject.
  2. Zmienna środowiskowa DOTNET_LAUNCH_PROFILE. Aby uzyskać więcej informacji, zobacz sekcję zmienne środowiskowe .NET.
  3. Pierwszy profil uruchamiania zdefiniowany w launchSettings.json.

Rozważmy następujący plik launchSettings.json:

{
  "$schema": "http://json.schemastore.org/launchsettings.json",
  "profiles": {
    "http": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": false,
      "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "https": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
      "applicationUrl": "https://localhost:7239;http://localhost:5066",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

W pozostałej części tego artykułu wyobraź sobie, że utworzyłeś/-aś IDistributedApplicationBuilder i przypisałeś/-aś ją do zmiennej o nazwie builder za pomocą interfejsu API CreateBuilder().

var builder = DistributedApplication.CreateBuilder(args);

Aby określić profile uruchamiania http i https, skonfiguruj wartości applicationUrl dla obu elementów w pliku launchSettings.json. Te adresy URL są używane do tworzenia punktów końcowych dla tego projektu. Jest to odpowiednik:

builder.AddProject<Projects.Networking_Frontend>("frontend")
       .WithHttpEndpoint(port: 5066)
       .WithHttpsEndpoint(port: 7239);

Ważny

Jeśli nie ma launchSettings.json (lub profilu uruchamiania), domyślnie nie ma powiązań.

Aby uzyskać więcej informacji, zobacz .NET.NET Aspire i uruchom profile.

Skonfigurowane punkty końcowe usługi Kestrel

.NET .NET Aspire obsługuje konfigurację punktu końcowego Kestrel. Rozważmy na przykład plik appsettings.json dla projektu, który definiuje punkt końcowy Kestrel ze schematem HTTPS i portem 5271:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "Kestrel": {
    "Endpoints": {
      "Https": {
        "Url": "https://*:5271"
      }
    }
  }
}

Poprzednia konfiguracja określa punkt końcowy Https. Właściwość Url jest ustawiona na https://*:5271, co oznacza, że punkt końcowy nasłuchuje na wszystkich interfejsach na porcie 5271. Aby uzyskać więcej informacji, zobacz Konfiguruj punkty końcowe dla serwera internetowego Kestrel ASP.NET Core.

Po skonfigurowaniu punktu końcowego Kestrel projekt powinien usunąć każdą konfigurację applicationUrl z pliku launchSettings.json.

Notatka

Jeśli applicationUrl znajduje się w pliku launchSettings.json i skonfigurowano punkt końcowy Kestrel, host aplikacji zgłosi wyjątek.

Podczas dodawania zasobu projektu istnieje przeciążenie, które pozwala określić, że punkt końcowy Kestrel powinien być używany zamiast pliku launchSettings.json:

builder.AddProject<Projects.Networking_ApiService>(
    name: "apiservice",
    configure: static project =>
    {
        project.ExcludeLaunchProfile = true;
        project.ExcludeKestrelEndpoints = false;
    })
    .WithHttpsEndpoint();

Aby uzyskać więcej informacji, zobacz AddProject.

Porty i serwery proxy

Podczas definiowania powiązania usługi port hosta jest zawsze przydzielany serwerowi proxy, który jest umieszczony przed usługą. Umożliwia to, aby jedna lub wiele replik usługi mogło zachowywać się podobnie. Ponadto wszystkie zależności zasobów korzystające z interfejsu API WithReference korzystają z punktu końcowego serwera proxy ze zmiennej środowiskowej.

Rozważ następujący łańcuch metod, który najpierw wywołuje AddProject, potem WithHttpEndpoint, a następnie WithReplicas:

builder.AddProject<Projects.Networking_Frontend>("frontend")
       .WithHttpEndpoint(port: 5066)
       .WithReplicas(2);

Powyższy kod powoduje wykonanie następującego diagramu sieciowego:

.NET.NET Aspire diagram aplikacji frontowej sieci z określonym portem hosta i dwiema replikami.

Powyższy diagram przedstawia następujące elementy:

  • Przeglądarka internetowa jako punkt wejścia do aplikacji.
  • Port hosta: 5066.
  • Serwer proxy front-end znajduje się pomiędzy przeglądarką internetową a replikami usługi front-end, który nasłuchuje na porcie 5066.
  • Replika usługi frontendowej frontend_0 nasłuchuje na losowo przypisanym porcie 65001.
  • Replika usługi frontendowej frontend_1 nasłuchuje na losowo wybranym porcie 65002.

Bez odwołania do WithReplicas, istnieje tylko jedna usługa frontendowa. Serwer proxy nadal nasłuchuje na porcie 5066, ale usługa frontendowa nasłuchuje na losowym porcie.

builder.AddProject<Projects.Networking_Frontend>("frontend")
       .WithHttpEndpoint(port: 5066);

Zdefiniowano dwa porty:

  • Port hosta: 5066.
  • Losowy port serwera proxy, z którymi będzie powiązana podstawowa usługa.

.NET.NET Aspire diagram sieciowy aplikacji frontendowej z określonym portem hosta i portem losowym.

Powyższy diagram przedstawia następujące elementy:

  • Przeglądarka internetowa jako punkt wejścia do aplikacji.
  • Port hosta: 5066.
  • Serwer frontend proxy znajduje się między przeglądarką internetową a usługą frontend i nasłuchuje na porcie 5066.
  • Usługa frontend nasłuchuje na porcie 65001.

Podstawowa usługa jest zasilana za pomocą tego portu ASPNETCORE_URLS dla zasobów projektu. Inne zasoby mają dostęp do tego portu, określając zmienną środowiskową w powiązaniu usługi:

builder.AddNpmApp("frontend", "../NodeFrontend", "watch")
       .WithHttpEndpoint(port: 5067, env: "PORT");

Poprzedni kod udostępnia losowy port w zmiennej środowiskowej PORT. Aplikacja używa tego portu do nasłuchiwania połączeń przychodzących z serwera proxy. Rozważmy następujący diagram:

.NET.NET Aspire diagram sieci aplikacji frontendowej z określonym portem hosta i portem zmiennej środowiskowej.

Powyższy diagram przedstawia następujące elementy:

  • Przeglądarka internetowa jako punkt wejścia do aplikacji.
  • Port hosta 5067.
  • Serwis proxy warstwy frontowej znajduje się pomiędzy przeglądarką internetową a usługą frontend, nasłuchujący na porcie 5067.
  • Usługa frontendu nasłuchuje na porcie 65001.

Napiwek

Aby uniknąć przekierowywania punktu końcowego, ustaw właściwość IsProxied na false przy wywoływaniu metody rozszerzenia WithEndpoint. Aby uzyskać więcej informacji, zobacz Rozszerzenia punktu końcowego: dodatkowe zagadnienia.

Pomijanie portu hosta

W przypadku pominięcia portu hosta .NET.NET Aspire generuje losowy port zarówno dla hosta, jak i portu usługi. Jest to przydatne, gdy chcesz uniknąć konfliktów portów i nie zależy ci na hoście lub porcie usługi. Rozważ następujący kod:

builder.AddProject<Projects.Networking_Frontend>("frontend")
       .WithHttpEndpoint();

W tym scenariuszu zarówno porty hosta, jak i usługi są losowe, jak pokazano na poniższym diagramie:

.NET.NET Aspire diagram sieci aplikacji frontendowej z losowym portem hosta i portem proxy.

Powyższy diagram przedstawia następujące elementy:

  • Przeglądarka internetowa jako punkt wejścia do aplikacji.
  • Port hosta o losowej wartości: 65000.
  • Frontend proxy znajduje się między przeglądarką internetową a usługą frontendową, nasłuchując na porcie 65000.
  • Usługa frontendowa jest nasłuchująca na porcie 65001.

Porty kontenerowe

Po dodaniu zasobu kontenera .NET.NET Aspire automatycznie przypisuje losowy port do kontenera. Aby określić port kontenera, skonfiguruj zasób kontenera przy użyciu żądanego portu:

builder.AddContainer("frontend", "mcr.microsoft.com/dotnet/samples", "aspnetapp")
       .WithHttpEndpoint(port: 8000, targetPort: 8080);

Powyższy kod:

  • Tworzy zasób kontenera o nazwie frontendna podstawie obrazu mcr.microsoft.com/dotnet/samples:aspnetapp.
  • Uwidacznia punkt końcowy http przez powiązanie hosta z portem 8000 i mapowanie go na port 8080 kontenera.

Rozważmy następujący diagram:

.NET.NET Aspire diagram sieci aplikacji frontendowej z hosta Dockera.

Metody rozszerzenia punktu końcowego

Każdy zasób implementujący interfejs IResourceWithEndpoints może używać metod rozszerzenia WithEndpoint. Istnieje kilka wersji tego rozszerzenia, co umożliwia określenie schematu, portu kontenera, portu hosta, nazwy zmiennej środowiskowej i tego, czy punkt końcowy jest przekierowany.

Istnieje również przeciążenie, które umożliwia określenie delegata do konfiguracji punktu końcowego. Jest to przydatne, gdy trzeba skonfigurować punkt końcowy na podstawie środowiska lub innych czynników. Rozważ następujący kod:

builder.AddProject<Projects.Networking_ApiService>("apiService")
       .WithEndpoint(
            endpointName: "admin",
            callback: static endpoint =>
       {
           endpoint.Port = 17003;
           endpoint.UriScheme = "http";
           endpoint.Transport = "http";
       });

Powyższy kod udostępnia delegata wywołania zwrotnego w celu skonfigurowania punktu końcowego. Punkt końcowy nosi nazwę admin i jest skonfigurowany do używania schematu http i transportu, a także portu hosta 17003. Konsument odwołuje się do tego punktu końcowego po nazwie; rozważ następujące wywołanie AddHttpClient:

builder.Services.AddHttpClient<WeatherApiClient>(
    client => client.BaseAddress = new Uri("http://_admin.apiservice"));

Uri jest konstruowany przy użyciu nazwy punktu końcowego admin poprzedzonej sentinelem _. Jest to konwencja wskazująca, że segment admin jest nazwą punktu końcowego należącego do usługi apiservice. Aby uzyskać więcej informacji, zobacz .NET.NET Aspire service discovery.

Dodatkowe zagadnienia

Podczas wywoływania metody rozszerzenia WithEndpoint przeciążenie callback uwidacznia nieprzetworzone EndpointAnnotation, co umożliwia użytkownikowi dostosowanie wielu aspektów punktu końcowego.

Właściwość AllocatedEndpoint umożliwia uzyskanie lub ustawienie punktu końcowego dla usługi. Właściwości IsExternal i IsProxied określają sposób zarządzania i uwidocznienia punktu końcowego: IsExternal decyduje, czy ma być publicznie dostępny, a IsProxied zapewnia zarządzanie nim przez DCP, co pozwala na wewnętrzne różnice portów i replikację.

Napiwek

Jeśli hostujesz zewnętrzny wykonywalny, który uruchamia własny serwer proxy i napotyka problemy z powiązaniem portu z powodu już powiązanego portu DCP, spróbuj ustawić właściwość IsProxied na wartość false. To uniemożliwia DCP zarządzanie serwerem proxy, dzięki czemu plik wykonywalny może pomyślnie powiązać port.

Właściwość Name identyfikuje usługę, natomiast właściwości Port i TargetPort określają odpowiednio docelowe i nasłuchujące porty.

W przypadku komunikacji sieciowej właściwość Protocol obsługuje TCP i UDP, z możliwością zwiększenia w przyszłości, a właściwość Transport wskazuje protokół transportowy (HTTP, HTTP2, HTTP3). Na koniec, jeśli usługa jest adresowalna za pomocą URI, właściwość UriScheme zapewnia schemat identyfikatora URI do konstruowania URI usługi.

Aby uzyskać więcej informacji, zobacz dostępne właściwości EndpointAnnotation.

Filtrowanie punktów końcowych

Wszystkie punkty końcowe zasobów projektów .NET.NET Aspire wykorzystują zestaw domyślnych heurystyk. Niektóre punkty końcowe są uwzględniane w ASPNETCORE_URLS w czasie wykonywania, niektóre są publikowane jako HTTP/HTTPS_PORTS, a niektóre konfiguracje są rozwiązywane z konfiguracji Kestrel. Niezależnie od domyślnego zachowania można filtrować punkty końcowe uwzględnione w zmiennych środowiskowych przy użyciu metody rozszerzenia WithEndpointsInEnvironment:

builder.AddProject<Projects.Networking_ApiService>("apiservice")
    .WithHttpsEndpoint() // Adds a default "https" endpoint
    .WithHttpsEndpoint(port: 19227, name: "admin")
    .WithEndpointsInEnvironment(
        filter: static endpoint =>
        {
            return endpoint.Name is not "admin";
        });

Powyższy kod dodaje domyślny punkt końcowy HTTPS, a także punkt końcowy admin na porcie 19227. Jednak punkt końcowy admin jest wykluczony ze zmiennych środowiskowych. Jest to przydatne, gdy chcesz uwidocznić punkt końcowy tylko do użytku wewnętrznego.