Udostępnij za pośrednictwem


ASP.NET Core w usłudze Azure Service Fabric Reliable Services

ASP.NET Core to platforma typu open source i międzyplatformowa. Ta struktura jest przeznaczona do tworzenia opartych na chmurze aplikacji połączonych z Internetem, takich jak aplikacje internetowe, aplikacje IoT i zaplecza mobilne.

Ten artykuł zawiera szczegółowy przewodnik dotyczący hostowania usług ASP.NET Core w usługach Reliable Services w usłudze Service Fabric przy użyciu zestawu pakietów NuGet Microsoft.ServiceFabric.AspNetCore.

Aby zapoznać się z samouczkiem wprowadzającym dotyczącym platformy ASP.NET Core w usłudze Service Fabric i instrukcjami dotyczącymi konfigurowania środowiska deweloperskiego, zobacz Samouczek: tworzenie i wdrażanie aplikacji przy użyciu usługi frontonu internetowego interfejsu API platformy ASP.NET Core oraz stanowej usługi zaplecza.

W pozostałej części tego artykułu założono, że znasz już ASP.NET Core. Jeśli nie, zapoznaj się z podstawami ASP.NET Core.

ASP.NET Core w środowisku usługi Service Fabric

Aplikacje ASP.NET Core i Service Fabric mogą być uruchamiane na platformie .NET Core lub w pełnym programie .NET Framework. Można użyć ASP.NET Core na dwa różne sposoby w usłudze Service Fabric:

  • Hostowane jako plik wykonywalny gościa. W ten sposób jest używany głównie do uruchamiania istniejących aplikacji ASP.NET Core w usłudze Service Fabric bez zmian w kodzie.
  • Uruchamianie wewnątrz niezawodnej usługi. Dzięki temu można lepiej zintegrować ze środowiskiem uruchomieniowym usługi Service Fabric i umożliwia stanowe usługi ASP.NET Core.

W pozostałej części tego artykułu wyjaśniono, jak używać platformy ASP.NET Core w niezawodnej usłudze za pośrednictwem składników integracji ASP.NET Core, które są dostarczane z zestawem SDK usługi Service Fabric.

Hosting usługi Service Fabric

W usłudze Service Fabric co najmniej jedno wystąpienie i/lub repliki usługi są uruchamiane w procesie hosta usługi: plik wykonywalny, który uruchamia kod usługi. Ty, jako autor usługi, jesteś właścicielem procesu hosta usługi, a usługa Service Fabric aktywuje i monitoruje go za Ciebie.

Tradycyjne ASP.NET (do MVC 5) są ściśle powiązane z usługami IIS za pośrednictwem System.Web.dll. ASP.NET Core zapewnia separację między serwerem internetowym a aplikacją internetową. Ta separacja umożliwia przenoszenie aplikacji internetowych między różnymi serwerami internetowymi. Umożliwia również serwerom internetowym samodzielne hostowania. Oznacza to, że można uruchomić serwer internetowy we własnym procesie, w przeciwieństwie do procesu należącego do dedykowanego oprogramowania serwera internetowego, takiego jak usługi IIS.

Aby połączyć usługę Service Fabric i ASP.NET, jako plik wykonywalny gościa lub w niezawodnej usłudze, musisz mieć możliwość uruchomienia ASP.NET wewnątrz procesu hosta usługi. ASP.NET Core self-hosting pozwala to zrobić.

Hosting ASP.NET Core w niezawodnej usłudze

Zazwyczaj aplikacje ASP.NET Core ( self-hosted) tworzą host internetowy w punkcie wejścia aplikacji, takim jak static void Main() metoda w Program.cspliku . W takim przypadku cykl życia hosta internetowego jest powiązany z cyklem życia procesu.

Hosting ASP.NET Core w procesie

Jednak punkt wejścia aplikacji nie jest właściwym miejscem do utworzenia hosta internetowego w niezawodnej usłudze. Wynika to z faktu, że punkt wejścia aplikacji jest używany tylko do rejestrowania typu usługi w środowisku uruchomieniowym usługi Service Fabric, dzięki czemu może tworzyć wystąpienia tego typu usługi. Host internetowy powinien zostać utworzony w niezawodnej usłudze. W ramach procesu hosta usługi wystąpienia usług i/lub repliki mogą przechodzić przez wiele cykli życia.

Wystąpienie usługi Reliable Service jest reprezentowane przez klasę usługi pochodzącą z StatelessService klasy usług lub StatefulService. Stos komunikacji dla usługi jest zawarty w ICommunicationListener implementacji w klasie usługi. Pakiety Microsoft.ServiceFabric.AspNetCore.* NuGet zawierają implementacje ICommunicationListener tego uruchamiania i zarządzania ASP.NET Core WebHost dla biblioteki Kestrel lub HTTP.sys w niezawodnej usłudze.

Diagram hostowania ASP.NET Core w niezawodnej usłudze

ASP.NET Core ICommunicationListeners

Implementacje ICommunicationListener biblioteki Kestrel i HTTP.sys w Microsoft.ServiceFabric.AspNetCore.* pakietach NuGet mają podobne wzorce użycia. Jednak wykonują nieco inne akcje specyficzne dla każdego serwera internetowego.

Oba odbiorniki komunikacji zapewniają konstruktor, który przyjmuje następujące argumenty:

  • ServiceContext serviceContext: jest ServiceContext to obiekt zawierający informacje o uruchomionej usłudze.
  • string endpointName: jest to nazwa Endpoint konfiguracji w ServiceManifest.xml. Jest to przede wszystkim miejsce, w którym dwa odbiorniki komunikacji różnią się. HTTP.sys wymaga Endpoint konfiguracji, a Kestrel nie.
  • Func<string, AspNetCoreCommunicationListener, IWebHost> build: Jest to zaimplementowana funkcja lambda, w której tworzysz i zwracasz element IWebHost. Umożliwia ona skonfigurowanie IWebHost sposobu, w jaki zwykle występuje w aplikacji ASP.NET Core. Rozszerzenie lambda udostępnia adres URL, który jest generowany dla Ciebie, w zależności od używanych opcji integracji usługi Service Fabric i podanej Endpoint konfiguracji. Następnie można zmodyfikować ten adres URL lub użyć go do uruchomienia serwera internetowego.

Oprogramowanie pośredniczące integracji usługi Service Fabric

Pakiet Microsoft.ServiceFabric.AspNetCore NuGet zawiera metodę UseServiceFabricIntegration rozszerzenia, IWebHostBuilder która dodaje oprogramowanie pośredniczące obsługujące usługę Service Fabric. To oprogramowanie pośredniczące konfiguruje bibliotekę Kestrel lub HTTP.sys ICommunicationListener w celu zarejestrowania unikatowego adresu URL usługi za pomocą usługi Service Fabric Naming Service. Następnie weryfikuje żądania klientów, aby upewnić się, że klienci łączą się z odpowiednią usługą.

Ten krok jest niezbędny, aby zapobiec błędnym połączeniu klientów z niewłaściwą usługą. Dzieje się tak dlatego, że w środowisku współużytkowanego hosta, takim jak usługa Service Fabric, wiele aplikacji internetowych może działać na tej samej maszynie fizycznej lub wirtualnej, ale nie używa unikatowych nazw hostów. Ten scenariusz został opisany bardziej szczegółowo w następnej sekcji.

Przypadek błędnej tożsamości

Repliki usług, niezależnie od protokołu, nasłuchują unikatowej kombinacji adresów IP:portów. Gdy replika usługi zaczęła nasłuchiwać w punkcie końcowym IP:port, zgłasza ten adres punktu końcowego do usługi Service Fabric Naming Service. W tym miejscu klienci lub inne usługi mogą je odnajdywać. Jeśli usługi używają dynamicznie przypisanych portów aplikacji, replika usługi może przypadkowo używać tego samego punktu końcowego IP:port innej usługi wcześniej na tej samej maszynie fizycznej lub wirtualnej. Może to spowodować, że klient błędnie nawiązał połączenie z niewłaściwą usługą. Ten scenariusz może spowodować wystąpienie następującej sekwencji zdarzeń:

  1. Usługa A nasłuchuje 10.0.0.1:30000 za pośrednictwem protokołu HTTP.
  2. Klient rozpoznaje usługę A i otrzymuje adres 10.0.0.1:30000.
  3. Usługa A przechodzi do innego węzła.
  4. Usługa B jest umieszczana na 10.0.0.1 i przypadkowo używa tego samego portu 30000.
  5. Klient próbuje nawiązać połączenie z usługą A z adresem buforowanym 10.0.0.1:30000.
  6. Klient jest teraz pomyślnie połączony z usługą B, nie zdając sobie sprawy, że jest połączony z niewłaściwą usługą.

Może to spowodować błędy w losowych czasach, które mogą być trudne do zdiagnozowania.

Używanie unikatowych adresów URL usługi

Aby zapobiec tym usterce, usługi mogą publikować punkt końcowy w usłudze Nazewnictwa z unikatowym identyfikatorem, a następnie weryfikować ten unikatowy identyfikator podczas żądań klientów. Jest to akcja współpracy między usługami w nieprzyjaznym środowisku zaufanym dzierżawcy. Nie zapewnia bezpiecznego uwierzytelniania usług w środowisku wrogiej dzierżawy.

W zaufanym środowisku oprogramowanie pośredniczące dodane przez UseServiceFabricIntegration metodę automatycznie dołącza unikatowy identyfikator do adresu opublikowanego w usłudze Naming Service. Sprawdza poprawność tego identyfikatora dla każdego żądania. Jeśli identyfikator nie jest zgodny, oprogramowanie pośredniczące natychmiast zwraca odpowiedź HTTP 410 Gone.

Usługi korzystające z dynamicznie przypisanego portu powinny korzystać z tego oprogramowania pośredniczącego.

Usługi korzystające z stałego unikatowego portu nie mają tego problemu w środowisku współpracy. Stały unikatowy port jest zwykle używany w przypadku usług zewnętrznych, z którymi muszą łączyć się dobrze znane porty dla aplikacji klienckich. Na przykład większość internetowych aplikacji internetowych będzie używać portu 80 lub 443 dla połączeń przeglądarki internetowej. W takim przypadku nie należy włączać unikatowego identyfikatora.

Na poniższym diagramie przedstawiono przepływ żądania z włączonym oprogramowaniem pośredniczącym:

Integracja usługi Service Fabric ASP.NET Core

Zarówno Kestrel, jak i HTTP.sys ICommunicationListener implementacje używają tego mechanizmu w dokładnie taki sam sposób. Mimo że HTTP.sys mogą wewnętrznie rozróżniać żądania na podstawie unikatowych ścieżek URL przy użyciu podstawowej funkcji udostępniania portów HTTP.sys, ta funkcja nie jest używana przez implementację HTTP.sysICommunicationListener. Dzieje się tak, ponieważ powoduje to kod stanu błędów HTTP 503 i HTTP 404 w opisanym wcześniej scenariuszu. To z kolei utrudnia klientom określenie intencji błędu, ponieważ protokół HTTP 503 i HTTP 404 są często używane do wskazywania innych błędów.

W związku z tym zarówno Kestrel, jak i HTTP.sys ICommunicationListener implementacje standandaryzują oprogramowanie pośredniczące dostarczone przez metodę UseServiceFabricIntegration rozszerzenia. W związku z tym klienci muszą wykonać akcję ponownego rozpoznawania punktu końcowego usługi w odpowiedziach HTTP 410.

HTTP.sys w usługach Reliable Services

Możesz użyć HTTP.sys w usługach Reliable Services, importując pakiet NuGet Microsoft.ServiceFabric.AspNetCore.HttpSys . Ten pakiet zawiera HttpSysCommunicationListenerimplementację .ICommunicationListener HttpSysCommunicationListener umożliwia utworzenie ASP.NET Core WebHost wewnątrz niezawodnej usługi przy użyciu HTTP.sys jako serwera internetowego.

HTTP.sys jest oparta na interfejsie API systemu Windows HTTP Server. Ten interfejs API używa sterownika jądra HTTP.sys do przetwarzania żądań HTTP i kierowania ich do procesów, które uruchamiają aplikacje internetowe. Dzięki temu wiele procesów na tej samej maszynie fizycznej lub wirtualnej może hostować aplikacje internetowe na tym samym porcie, uściślane przez unikatową ścieżkę adresu URL lub nazwę hosta. Te funkcje są przydatne w usłudze Service Fabric do hostowania wielu witryn internetowych w tym samym klastrze.

Uwaga

HTTP.sys implementacja działa tylko na platformie Windows.

Na poniższym diagramie pokazano, jak HTTP.sys używa sterownika jądra HTTP.sys w systemie Windows do udostępniania portów:

diagram HTTP.sys

HTTP.sys w usłudze bezstanowej

Aby użyć HttpSys w usłudze bezstanowej, zastąpij metodę HttpSysCommunicationListener CreateServiceInstanceListeners i zwróć wystąpienie:

protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
    return new ServiceInstanceListener[]
    {
        new ServiceInstanceListener(serviceContext =>
            new HttpSysCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
                new WebHostBuilder()
                    .UseHttpSys()
                    .ConfigureServices(
                        services => services
                            .AddSingleton<StatelessServiceContext>(serviceContext))
                    .UseContentRoot(Directory.GetCurrentDirectory())
                    .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
                    .UseStartup<Startup>()
                    .UseUrls(url)
                    .Build()))
    };
}

HTTP.sys w usłudze stanowej

HttpSysCommunicationListenernie jest obecnie przeznaczony do użytku w usługach stanowych z powodu komplikacji związanych z funkcją udostępniania portów HTTP.sys bazowych. Aby uzyskać więcej informacji, zobacz następującą sekcję dotyczącą dynamicznej alokacji portów przy użyciu HTTP.sys. W przypadku usług stanowych usługa Kestrel jest sugerowanym serwerem internetowym.

Konfiguracja punktu końcowego

Konfiguracja jest wymagana Endpoint dla serwerów internetowych korzystających z interfejsu API systemu Windows HTTP Server, w tym HTTP.sys. Serwery sieci Web korzystające z interfejsu API systemu Windows HTTP Server muszą najpierw zarezerwować adres URL za pomocą HTTP.sys (zwykle odbywa się to za pomocą narzędzia netsh ).

Ta akcja wymaga podniesionych uprawnień, których usługi nie mają domyślnie. Opcje "http" lub "https" dla Protocol właściwości Endpoint konfiguracji w ServiceManifest.xml są używane specjalnie do poinstruowania środowiska uruchomieniowego usługi Service Fabric w celu zarejestrowania adresu URL za pomocą HTTP.sys w Twoim imieniu. Robi to przy użyciu silnego prefiksu adresu URL z symbolami wieloznacznymi .

Aby na przykład zarezerwować http://+:80 usługę, użyj następującej konfiguracji w ServiceManifest.xml:

<ServiceManifest ... >
    ...
    <Resources>
        <Endpoints>
            <Endpoint Name="ServiceEndpoint" Protocol="http" Port="80" />
        </Endpoints>
    </Resources>

</ServiceManifest>

Nazwa punktu końcowego musi zostać przekazana do konstruktora HttpSysCommunicationListener :

 new HttpSysCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
 {
     return new WebHostBuilder()
         .UseHttpSys()
         .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
         .UseUrls(url)
         .Build();
 })

Używanie HTTP.sys ze statycznym portem

Aby użyć portu statycznego z HTTP.sys, podaj numer portu w Endpoint konfiguracji:

  <Resources>
    <Endpoints>
      <Endpoint Protocol="http" Name="ServiceEndpoint" Port="80" />
    </Endpoints>
  </Resources>

Używanie HTTP.sys z portem dynamicznym

Aby użyć dynamicznie przypisanego portu z HTTP.sys, pomiń Port właściwość w Endpoint konfiguracji:

  <Resources>
    <Endpoints>
      <Endpoint Protocol="http" Name="ServiceEndpoint" />
    </Endpoints>
  </Resources>

Port dynamiczny przydzielony przez konfigurację Endpoint zapewnia tylko jeden port na proces hosta. Bieżący model hostingu usługi Service Fabric umożliwia hostowanie wielu wystąpień usług i/lub replik w tym samym procesie. Oznacza to, że każdy z nich będzie współużytkowył ten sam port po przydzieleniu Endpoint za pośrednictwem konfiguracji. Wiele wystąpień HTTP.sys może współużytkować port przy użyciu podstawowej funkcji udostępniania portów HTTP.sys . Ale nie jest obsługiwany przez HttpSysCommunicationListener ze względu na komplikacje wprowadzone dla żądań klientów. W przypadku dynamicznego użycia portów usługa Kestrel jest sugerowanym serwerem internetowym.

Kestrel w usługach Reliable Services

Usługi Kestrel można używać w usługach Reliable Services, importując pakiet NuGet Microsoft.ServiceFabric.AspNetCore.Kestrel . Ten pakiet zawiera KestrelCommunicationListenerimplementację .ICommunicationListener KestrelCommunicationListener Umożliwia utworzenie ASP.NET Core WebHost wewnątrz niezawodnej usługi przy użyciu usługi Kestrel jako serwera internetowego.

Kestrel to międzyplatformowy serwer internetowy dla platformy ASP.NET Core. W przeciwieństwie do HTTP.sys usługa Kestrel nie używa scentralizowanego menedżera punktów końcowych. Również w przeciwieństwie do HTTP.sys, Kestrel nie obsługuje udostępniania portów między wieloma procesami. Każde wystąpienie usługi Kestrel musi używać unikatowego portu. Aby uzyskać więcej informacji na temat usługi Kestrel, zobacz Szczegóły implementacji.

Diagram Kestrel

Kestrel w usłudze bezstanowej

Aby użyć Kestrel w usłudze bezstanowej, zastąpij metodę KestrelCommunicationListener CreateServiceInstanceListeners i zwróć wystąpienie:

protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
    return new ServiceInstanceListener[]
    {
        new ServiceInstanceListener(serviceContext =>
            new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
                new WebHostBuilder()
                    .UseKestrel()
                    .ConfigureServices(
                        services => services
                            .AddSingleton<StatelessServiceContext>(serviceContext))
                    .UseContentRoot(Directory.GetCurrentDirectory())
                    .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.UseUniqueServiceUrl)
                    .UseStartup<Startup>()
                    .UseUrls(url)
                    .Build();
            ))
    };
}

Kestrel w usłudze stanowej

Aby użyć Kestrel w usłudze stanowej, zastąpij metodę CreateServiceReplicaListeners i zwróć KestrelCommunicationListener wystąpienie:

protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
{
    return new ServiceReplicaListener[]
    {
        new ServiceReplicaListener(serviceContext =>
            new KestrelCommunicationListener(serviceContext, (url, listener) =>
                new WebHostBuilder()
                    .UseKestrel()
                    .ConfigureServices(
                         services => services
                             .AddSingleton<StatefulServiceContext>(serviceContext)
                             .AddSingleton<IReliableStateManager>(this.StateManager))
                    .UseContentRoot(Directory.GetCurrentDirectory())
                    .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.UseUniqueServiceUrl)
                    .UseStartup<Startup>()
                    .UseUrls(url)
                    .Build();
            ))
    };
}

W tym przykładzie pojedyncze wystąpienie IReliableStateManager klasy jest udostępniane kontenerowi iniekcji zależności WebHost. Nie jest to absolutnie konieczne, ale umożliwia używanie IReliableStateManager i niezawodne kolekcje w metodach akcji kontrolera MVC.

Nazwa Endpoint konfiguracji nie jest podana KestrelCommunicationListener w usłudze stanowej. Bardziej szczegółowo wyjaśniono to w poniższej sekcji.

Konfigurowanie usługi Kestrel do używania protokołu HTTPS

Podczas włączania protokołu HTTPS z usługą Kestrel należy ustawić kilka opcji nasłuchiwania. Zaktualizuj element ServiceInstanceListener , aby używać punktu końcowego EndpointHttps i nasłuchiwać na określonym porcie (np. na porcie 443). Podczas konfigurowania hosta internetowego do korzystania z serwera internetowego Kestrel należy skonfigurować usługę Kestrel do nasłuchiwania adresów IPv6 we wszystkich interfejsach sieciowych:

new ServiceInstanceListener(
serviceContext =>
    new KestrelCommunicationListener(
        serviceContext,
        "EndpointHttps",
        (url, listener) =>
        {
            ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting Kestrel on {url}");

            return new WebHostBuilder()
                .UseKestrel(opt =>
                {
                    int port = serviceContext.CodePackageActivationContext.GetEndpoint("EndpointHttps").Port;
                    opt.Listen(IPAddress.IPv6Any, port, listenOptions =>
                    {
                        listenOptions.UseHttps(GetCertificateFromStore());
                        listenOptions.NoDelay = true;
                    });
                })
                .ConfigureAppConfiguration((builderContext, config) =>
                {
                    config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
                })

                .ConfigureServices(
                    services => services
                        .AddSingleton<HttpClient>(new HttpClient())
                        .AddSingleton<FabricClient>(new FabricClient())
                        .AddSingleton<StatelessServiceContext>(serviceContext))
                .UseContentRoot(Directory.GetCurrentDirectory())
                .UseStartup<Startup>()
                .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
                .UseUrls(url)
                .Build();
        }))

Pełny przykład w samouczku można znaleźć w temacie Configure Kestrel to use HTTPS (Konfigurowanie usługi Kestrel do korzystania z protokołu HTTPS).

Konfiguracja punktu końcowego

Do korzystania z usługi Kestrel nie jest wymagana Endpoint konfiguracja.

Kestrel to prosty autonomiczny serwer internetowy. W przeciwieństwie do HTTP.sys (lub HttpListener) nie wymaga konfiguracji w ServiceManifest.xml, ponieważ nie wymaga Endpoint rejestracji adresu URL przed rozpoczęciem.

Używanie biblioteki Kestrel z portem statycznym

Port statyczny można skonfigurować w Endpoint konfiguracji ServiceManifest.xml do użycia z usługą Kestrel. Chociaż nie jest to absolutnie konieczne, oferuje ona dwie potencjalne korzyści:

  • Jeśli port nie mieści się w zakresie portów aplikacji, zostanie otwarty za pośrednictwem zapory systemu operacyjnego przez usługę Service Fabric.
  • Podany przez Ciebie KestrelCommunicationListener adres URL będzie używać tego portu.
  <Resources>
    <Endpoints>
      <Endpoint Protocol="http" Name="ServiceEndpoint" Port="80" />
    </Endpoints>
  </Resources>

Jeśli element Endpoint jest skonfigurowany, jego nazwa musi zostać przekazana do konstruktora KestrelCommunicationListener :

new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) => ...

Jeśli ServiceManifest.xml nie używa Endpoint konfiguracji, pomiń nazwę w konstruktorze KestrelCommunicationListener . W takim przypadku użyje portu dynamicznego. Aby uzyskać więcej informacji na ten temat, zobacz następną sekcję.

Używanie platformy Kestrel z portem dynamicznym

Kestrel nie może użyć automatycznego przypisania portu z Endpoint konfiguracji w ServiceManifest.xml. Dzieje się tak, ponieważ automatyczne przypisywanie portów z Endpoint konfiguracji przypisuje unikatowy port na proces hosta, a pojedynczy proces hosta może zawierać wiele wystąpień Kestrel. Nie działa to z usługą Kestrel, ponieważ nie obsługuje udostępniania portów. W związku z tym każde wystąpienie usługi Kestrel musi być otwarte na unikatowym porcie.

Aby użyć przypisania portu dynamicznego z językiem Kestrel, pomiń Endpoint konfigurację w ServiceManifest.xml całkowicie i nie przekazuj nazwy punktu końcowego do konstruktora KestrelCommunicationListener w następujący sposób:

new KestrelCommunicationListener(serviceContext, (url, listener) => ...

W tej konfiguracji KestrelCommunicationListener automatycznie wybierze nieużywany port z zakresu portów aplikacji.

W przypadku protokołu HTTPS powinien on mieć punkt końcowy skonfigurowany przy użyciu protokołu HTTPS bez portu określonego w ServiceManifest.xml i przekazać nazwę punktu końcowego do konstruktora KestrelCommunicationListener.

Integracja hostów IHost i minimalnych hostów

Oprócz interfejsu IWebHost/IWebHostBuilder KestrelCommunicationListener i HttpSysCommunicationListener obsługi kompilowania usług ASP.NET Core przy użyciu interfejsu IHost/IHostBuilder. Jest to dostępne począwszy od wersji 5.2.1363 pakietów Microsoft.ServiceFabric.AspNetCore.Kestrel i Microsoft.ServiceFabric.AspNetCore.HttpSys .

// Stateless Service
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
    return new ServiceInstanceListener[]
    {
        new ServiceInstanceListener(serviceContext =>
            new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
            {
                return Host.CreateDefaultBuilder()
                        .ConfigureWebHostDefaults(webBuilder =>
                        {
                            webBuilder.UseKestrel()
                                .UseStartup<Startup>()
                                .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
                                .UseContentRoot(Directory.GetCurrentDirectory())
                                .UseUrls(url);
                        })
                        .ConfigureServices(services => services.AddSingleton<StatelessServiceContext>(serviceContext))
                        .Build();
            }))
    };
}

// Stateful Service
protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
{
    return new ServiceReplicaListener[]
    {
        new ServiceReplicaListener(serviceContext =>
            new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
            {
                return Host.CreateDefaultBuilder()
                        .ConfigureWebHostDefaults(webBuilder =>
                        {
                            webBuilder.UseKestrel()
                                .UseStartup<Startup>()
                                .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.UseUniqueServiceUrl)
                                .UseContentRoot(Directory.GetCurrentDirectory())
                                .UseUrls(url);
                        })
                        .ConfigureServices(services =>
                        {
                            services.AddSingleton<StatefulServiceContext>(serviceContext);
                            services.AddSingleton<IReliableStateManager>(this.StateManager);
                        })
                        .Build();
            }))
    };
}

Uwaga

Ponieważ program KestrelCommunicationListener i HttpSysCommunicationListener są przeznaczone dla usług sieci Web, wymagane jest zarejestrowanie/skonfigurowanie serwera internetowego (przy użyciu metody ConfigureWebHostDefaults lub ConfigureWebHost) za pośrednictwem hosta IHost

ASP.NET 6 wprowadzono model minimalnego hostingu, który jest bardziej uproszczony i usprawniony sposób tworzenia aplikacji internetowych. Minimalny model hostingu może być również używany z KestrelCommunicationListener i HttpSysCommunicationListener.

// Stateless Service
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
    return new ServiceInstanceListener[]
    {
        new ServiceInstanceListener(serviceContext =>
            new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
            {
                var builder = WebApplication.CreateBuilder();

                builder.Services.AddSingleton<StatelessServiceContext>(serviceContext);
                builder.WebHost
                            .UseKestrel()
                            .UseContentRoot(Directory.GetCurrentDirectory())
                            .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
                            .UseUrls(url);

                builder.Services.AddControllersWithViews();

                var app = builder.Build();

                if (!app.Environment.IsDevelopment())
                {
                    app.UseExceptionHandler("/Home/Error");
                }

                app.UseHttpsRedirection();
                app.UseStaticFiles();
                app.UseRouting();
                app.UseAuthorization();
                app.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");

                return app;
            }))
    };
}
// Stateful Service
protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
{
    return new ServiceReplicaListener[]
    {
        new ServiceReplicaListener(serviceContext =>
            new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
            {
                var builder = WebApplication.CreateBuilder();

                builder.Services
                            .AddSingleton<StatefulServiceContext>(serviceContext)
                            .AddSingleton<IReliableStateManager>(this.StateManager);
                builder.WebHost
                            .UseKestrel()
                            .UseContentRoot(Directory.GetCurrentDirectory())
                            .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.UseUniqueServiceUrl)
                            .UseUrls(url);

                builder.Services.AddControllersWithViews();

                var app = builder.Build();

                if (!app.Environment.IsDevelopment())
                {
                    app.UseExceptionHandler("/Home/Error");
                }
                app.UseStaticFiles();
                app.UseRouting();
                app.UseAuthorization();
                app.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");

                return app;
            }))
    };
}

Dostawca konfiguracji usługi Service Fabric

Konfiguracja aplikacji w programie ASP.NET Core jest oparta na parach klucz-wartość ustanowionych przez dostawcę konfiguracji. Przeczytaj artykuł Configuration in ASP.NET Core (Konfiguracja w programie ASP.NET Core ), aby dowiedzieć się więcej na temat ogólnej obsługi konfiguracji ASP.NET Core.

W tej sekcji opisano sposób integracji dostawcy konfiguracji usługi Service Fabric z konfiguracją ASP.NET Core przez zaimportowanie Microsoft.ServiceFabric.AspNetCore.Configuration pakietu NuGet.

AddServiceFabricConfiguration — rozszerzenia uruchamiania

Po zaimportowaniu pakietu NuGet należy zarejestrować źródło konfiguracji usługi Service Fabric przy użyciu interfejsu Microsoft.ServiceFabric.AspNetCore.Configuration API konfiguracji ASP.NET Core. W tym celu należy sprawdzić rozszerzenia AddServiceFabricConfiguration w Microsoft.ServiceFabric.AspNetCore.Configuration przestrzeni nazw względem IConfigurationBuilderelementu .

using Microsoft.ServiceFabric.AspNetCore.Configuration;

public Startup(IHostingEnvironment env)
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
        .AddServiceFabricConfiguration() // Add Service Fabric configuration settings.
        .AddEnvironmentVariables();
    Configuration = builder.Build();
}

public IConfigurationRoot Configuration { get; }

Teraz usługa ASP.NET Core może uzyskiwać dostęp do ustawień konfiguracji usługi Service Fabric, podobnie jak w przypadku innych ustawień aplikacji. Na przykład można użyć wzorca opcji, aby załadować ustawienia do silnie typiowanych obiektów.

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<MyOptions>(Configuration);  // Strongly typed configuration object.
    services.AddMvc();
}

Domyślne mapowanie klucza

Domyślnie dostawca konfiguracji usługi Service Fabric zawiera nazwę pakietu, nazwę sekcji i nazwę właściwości. Razem tworzą one klucz konfiguracji ASP.NET Core w następujący sposób:

$"{this.PackageName}{ConfigurationPath.KeyDelimiter}{section.Name}{ConfigurationPath.KeyDelimiter}{property.Name}"

Jeśli na przykład masz pakiet konfiguracji o nazwie o następującej MyConfigPackage zawartości, wartość konfiguracji będzie dostępna w ASP.NET Core IConfiguration za pośrednictwem myConfigPackage :MyConfigSection:MyParameter.

<?xml version="1.0" encoding="utf-8" ?>
<Settings xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/2011/01/fabric">  
  <Section Name="MyConfigSection">
    <Parameter Name="MyParameter" Value="Value1" />
  </Section>  
</Settings>

Opcje konfiguracji usługi Service Fabric

Dostawca konfiguracji usługi Service Fabric obsługuje ServiceFabricConfigurationOptions również zmianę domyślnego zachowania mapowania kluczy.

Ustawienia zaszyfrowane

Usługa Service Fabric obsługuje zaszyfrowane ustawienia, podobnie jak dostawca konfiguracji usługi Service Fabric. Ustawienia zaszyfrowane nie są domyślnie odszyfrowywane do ASP.NET Core IConfiguration . Zaszyfrowane wartości są tam przechowywane. Jeśli jednak chcesz odszyfrować wartość do przechowywania w ASP.NET Core IConfiguration, możesz ustawić flagę DecryptValue na false w rozszerzeniu w AddServiceFabricConfiguration następujący sposób:

public Startup()
{
    ICodePackageActivationContext activationContext = FabricRuntime.GetActivationContext();
    var builder = new ConfigurationBuilder()        
        .AddServiceFabricConfiguration(activationContext, (options) => options.DecryptValue = false); // set flag to decrypt the value
    Configuration = builder.Build();
}

Wiele pakietów konfiguracji

Usługa Service Fabric obsługuje wiele pakietów konfiguracji. Domyślnie nazwa pakietu jest uwzględniona w kluczu konfiguracji. Można jednak ustawić flagę IncludePackageName na false w następujący sposób:

public Startup()
{
    ICodePackageActivationContext activationContext = FabricRuntime.GetActivationContext();
    var builder = new ConfigurationBuilder()        
        // exclude package name from key.
        .AddServiceFabricConfiguration(activationContext, (options) => options.IncludePackageName = false); 
    Configuration = builder.Build();
}

Niestandardowe mapowanie kluczy, wyodrębnianie wartości i populacja danych

Dostawca konfiguracji usługi Service Fabric obsługuje również bardziej zaawansowane scenariusze dostosowywania mapowania kluczy za pomocą ExtractKeyFunc polecenia i wyodrębniania wartości za pomocą polecenia ExtractValueFunc. Można nawet zmienić cały proces wypełniania danych z konfiguracji usługi Service Fabric na konfigurację ASP.NET Core przy użyciu polecenia ConfigAction.

Poniższe przykłady ilustrują sposób dostosowywania ConfigAction populacji danych:

public Startup()
{
    ICodePackageActivationContext activationContext = FabricRuntime.GetActivationContext();
    
    this.valueCount = 0;
    this.sectionCount = 0;
    var builder = new ConfigurationBuilder();
    builder.AddServiceFabricConfiguration(activationContext, (options) =>
        {
            options.ConfigAction = (package, configData) =>
            {
                ILogger logger = new ConsoleLogger("Test", null, false);
                logger.LogInformation($"Config Update for package {package.Path} started");

                foreach (var section in package.Settings.Sections)
                {
                    this.sectionCount++;

                    foreach (var param in section.Parameters)
                    {
                        configData[options.ExtractKeyFunc(section, param)] = options.ExtractValueFunc(section, param);
                        this.valueCount++;
                    }
                }

                logger.LogInformation($"Config Update for package {package.Path} finished");
            };
        });
  Configuration = builder.Build();
}

Aktualizacje konfiguracji

Dostawca konfiguracji usługi Service Fabric obsługuje również aktualizacje konfiguracji. Możesz użyć ASP.NET Core IOptionsMonitor do odbierania powiadomień o zmianie, a następnie użyć IOptionsSnapshot polecenia w celu ponownego załadowania danych konfiguracji. Aby uzyskać więcej informacji, zobacz opcje ASP.NET Core.

Te opcje są domyślnie obsługiwane. Do włączenia aktualizacji konfiguracji nie jest potrzebne żadne dalsze kodowanie.

Scenariusze i konfiguracje

Ta sekcja zawiera kombinację serwerów sieci Web, konfiguracji portów, opcji integracji usługi Service Fabric i różnych ustawień, które zalecamy w celu rozwiązania następujących scenariuszy:

  • Zewnętrznie uwidocznione usługi bezstanowe ASP.NET Core
  • Usługi bezstanowe podstawowe ASP.NET tylko wewnętrzne
  • Usługi stanowe podstawowe ASP.NET tylko wewnętrzne

Zewnętrznie uwidoczniona usługa to usługa, która uwidacznia punkt końcowy wywoływany spoza klastra, zwykle za pośrednictwem modułu równoważenia obciążenia.

Usługa tylko wewnętrzna to usługa, której punkt końcowy jest wywoływany tylko z poziomu klastra.

Uwaga

Punkty końcowe usługi stanowej zwykle nie powinny być uwidocznione w Internecie. Klastry za modułami równoważenia obciążenia, które nie wiedzą o rozpoznawaniu usługi Service Fabric, takiej jak Usługa Azure Load Balancer, nie będą mogły uwidocznić usług stanowych. Dzieje się tak, ponieważ moduł równoważenia obciążenia nie będzie mógł zlokalizować i kierować ruchu do odpowiedniej repliki usługi stanowej.

Zewnętrznie uwidocznione usługi bezstanowe ASP.NET Core

Kestrel to sugerowany serwer internetowy dla usług frontonu, które uwidaczniają zewnętrzne, internetowe punkty końcowe HTTP. W systemie Windows HTTP.sys może zapewnić możliwość udostępniania portów, która umożliwia hostowanie wielu usług sieci Web w tym samym zestawie węzłów przy użyciu tego samego portu. W tym scenariuszu usługi internetowe są rozróżniane według nazwy hosta lub ścieżki bez polegania na serwerze proxy frontonu lub bramie w celu zapewnienia routingu HTTP.

W przypadku uwidocznienia internetu usługa bezstanowa powinna używać dobrze znanego i stabilnego punktu końcowego dostępnego za pośrednictwem modułu równoważenia obciążenia. Ten adres URL zostanie wyświetlony użytkownikom aplikacji. Zalecamy następującą konfigurację:

Typ Zalecenie Uwagi
Serwer sieci Web Kestrel Kestrel jest preferowanym serwerem internetowym, ponieważ jest obsługiwany w systemach Windows i Linux.
Konfiguracja portów static Dobrze znany port statyczny należy skonfigurować w Endpoints konfiguracji ServiceManifest.xml, na przykład 80 dla protokołu HTTP lub 443 dla protokołu HTTPS.
ServiceFabricIntegrationOptions Brak ServiceFabricIntegrationOptions.None Użyj opcji podczas konfigurowania oprogramowania pośredniczącego integracji usługi Service Fabric, aby usługa nie próbowała zweryfikować przychodzących żądań dla unikatowego identyfikatora. Użytkownicy zewnętrzni aplikacji nie będą znali unikatowych informacji identyfikacyjnych używanych przez oprogramowanie pośredniczące.
Liczba wystąpień -1 W typowych przypadkach użycia ustawienie liczba wystąpień powinno być ustawione na -1. Dzieje się tak, aby wystąpienie było dostępne we wszystkich węzłach, które odbierają ruch z modułu równoważenia obciążenia.

Jeśli wiele usług uwidocznionych zewnętrznie współużytkuje ten sam zestaw węzłów, można użyć HTTP.sys z unikatową, ale stabilną ścieżką adresu URL. Można to zrobić, modyfikując adres URL podany podczas konfigurowania elementu IWebHost. Należy pamiętać, że dotyczy to tylko HTTP.sys.

new HttpSysCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
{
    url += "/MyUniqueServicePath";

    return new WebHostBuilder()
        .UseHttpSys()
        ...
        .UseUrls(url)
        .Build();
})

Bezstanowa usługa ASP.NET Core tylko wewnętrznych

Usługi bezstanowe, które są wywoływane tylko z poziomu klastra, powinny używać unikatowych adresów URL i dynamicznie przypisanych portów w celu zapewnienia współpracy między wieloma usługami. Zalecamy następującą konfigurację:

Typ Zalecenie Uwagi
Serwer sieci Web Kestrel Chociaż można użyć HTTP.sys dla wewnętrznych usług bezstanowych, Kestrel jest najlepszym serwerem, aby umożliwić wielu wystąpieniom usług współużytkowanie hosta.
Konfiguracja portów dynamicznie przypisywane Wiele replik usługi stanowej może współużytkować proces hosta lub system operacyjny hosta, a tym samym będzie potrzebować unikatowych portów.
ServiceFabricIntegrationOptions UseUniqueServiceUrl W przypadku przypisania portu dynamicznego to ustawienie uniemożliwia błędny problem z tożsamością opisany wcześniej.
InstanceCount dowolny Ustawienie liczby wystąpień można ustawić na dowolną wartość niezbędną do obsługi usługi.

Stanowa usługa ASP.NET Core tylko wewnętrznych

Usługi stanowe, które są wywoływane tylko z poziomu klastra, powinny używać dynamicznie przypisanych portów w celu zapewnienia współpracy między wieloma usługami. Zalecamy następującą konfigurację:

Typ Zalecenie Uwagi
Serwer sieci Web Kestrel Element HttpSysCommunicationListener nie jest przeznaczony do użytku przez usługi stanowe, w których repliki współużytkuje proces hosta.
Konfiguracja portów dynamicznie przypisywane Wiele replik usługi stanowej może współużytkować proces hosta lub system operacyjny hosta, a tym samym będzie potrzebować unikatowych portów.
ServiceFabricIntegrationOptions UseUniqueServiceUrl W przypadku przypisania portu dynamicznego to ustawienie uniemożliwia błędny problem z tożsamością opisany wcześniej.

Następne kroki

Debug your Service Fabric application by using Visual Studio (Debugowanie aplikacji usługi Service Fabric przy użyciu programu Visual Studio)