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 aplikacji opartych na chmurze, 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 Service Fabric Reliable Services przy użyciu zestawu pakietów NuGet Microsoft.ServiceFabric.AspNetCore.

Aby zapoznać się z samouczkiem wprowadzającym dotyczącym 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 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 tak nie jest, zapoznaj się z ASP.NET Core podstawami.

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

Aplikacje ASP.NET Core i Service Fabric można uruchamiać na platformie .NET Core lub w pełnym .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.
  • Uruchom wewnątrz niezawodnej usługi. Dzięki temu można lepiej zintegrować środowisko uruchomieniowe usługi Service Fabric i umożliwia stanowe ASP.NET Core usług.

W dalszej części tego artykułu wyjaśniono, jak używać ASP.NET Core wewnątrz niezawodnej usługi 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 przenośnie 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 samoobsługowego hostingu pozwala to zrobić.

Hostowanie ASP.NET Core w niezawodnej usłudze

Zazwyczaj własne aplikacje ASP.NET Core tworzą obiekt WebHost w punkcie wejścia aplikacji, na przykład metodę static void Main() w elemecie Program.cs. W takim przypadku cykl życia hosta internetowego jest powiązany z cyklem życia procesu.

Hostowanie ASP.NET Core w procesie

Jednak punkt wejścia aplikacji nie jest właściwym miejscem do utworzenia hosta internetowego w niezawodnej usłudze. Dzieje się tak, ponieważ 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 sieci Web 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ługi lub StatefulService. Stos komunikacji dla usługi jest zawarty w ICommunicationListener implementacji w klasie usług. Microsoft.ServiceFabric.AspNetCore.* Pakiety NuGet zawierają implementacje ICommunicationListener tego uruchomienia 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 pakietach Microsoft.ServiceFabric.AspNetCore.* NuGet mają podobne wzorce użycia. Jednak wykonują nieco inne akcje specyficzne dla każdego serwera internetowego.

Oba odbiorniki komunikacji udostępniają 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 wymagaEndpoint konfiguracji, a Kestrel nie.
  • Func<string, AspNetCoreCommunicationListener, IWebHost> build: Jest to implementowana funkcja lambda, w której tworzysz i zwracasz element IWebHost. Umożliwia ona skonfigurowanie IWebHost sposobu, w jaki zwykle byłyby w aplikacji ASP.NET Core. Element lambda udostępnia wygenerowany adres URL w zależności od używanych opcji integracji usługi Service Fabric i podanej Endpoint konfiguracji. Następnie można zmodyfikować lub użyć tego adresu URL, aby uruchomić serwer internetowy.

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

Pakiet Microsoft.ServiceFabric.AspNetCore NuGet zawiera metodę UseServiceFabricIntegration rozszerzenia, która IWebHostBuilder 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 hosta współdzielonego, 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łuchiwanie na unikatowej kombinacji adresów IP:portów. Gdy replika usługi zacznie nasłuchiwać w punkcie końcowym IP:port, zgłasza ten adres punktu końcowego do usługi Service Fabric Naming Service. Tam 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ć, że wystąpi następująca sekwencja 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 w wersji 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 buforowanym adresem 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 kooperacyjna między usługami w środowisku zaufanym nieprzyjaznym dzierżawcy. Nie zapewnia bezpiecznego uwierzytelniania usługi w środowisku dzierżawcy wrogim.

W zaufanym środowisku oprogramowanie pośredniczące dodane przez UseServiceFabricIntegration metodę automatycznie dołącza unikatowy identyfikator do adresu opublikowanego w usłudze Naming Service. Weryfikuje ten identyfikator 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ść 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 żądań z włączonym oprogramowaniem pośredniczącym:

Integracja usługi Service Fabric ASP.NET Core

Zarówno Kestrel, jak i implementacje HTTP.sys ICommunicationListener używają tego mechanizmu w dokładnie taki sam sposób. Chociaż 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.sys ICommunicationListener . Wynika to z kodów 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 implementacje HTTP.sys ICommunicationListener ustandaryzują oprogramowanie pośredniczące dostarczone przez metodę UseServiceFabricIntegration rozszerzenia. W związku z tym klienci muszą wykonać akcję ponownego rozwiązania punktu końcowego usługi w odpowiedziach HTTP 410.

HTTP.sys w usługach Reliable Services

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

HTTP.sys jest oparty na interfejsie API serwera HTTP systemu Windows. 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. Umożliwia to wielu procesom na tej samej maszynie fizycznej lub wirtualnej hostowanie aplikacji internetowych na tym samym porcie, uściślanych 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:

 diagramHTTP.sys

HTTP.sys w usłudze bezstanowej

Aby użyć HttpSys w usłudze bezstanowej, zastąpij CreateServiceInstanceListeners metodę HttpSysCommunicationListener 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

HttpSysCommunicationListener nie jest obecnie przeznaczony do użytku w usługach stanowych z powodu komplikacji związanych z podstawową funkcją udostępniania portówHTTP.sys. Aby uzyskać więcej informacji, zobacz następującą sekcję dotyczącą alokacji portów dynamicznych z HTTP.sys. W przypadku usług stanowych usługa Kestrel jest sugerowanym serwerem sieci Web.

Konfiguracja punktu końcowego

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

Ta akcja wymaga uprawnień z podwyższonym poziomem 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 z HTTP.sys w Twoim imieniu. Robi to przy użyciu silnego prefiksu adresu URL symboli wieloznacznych .

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 z portem statycznym

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ółdzielił ten sam port podczas przydzielania za pośrednictwem Endpoint 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ługiwana ze HttpSysCommunicationListener względu na komplikacje wprowadzone dla żądań klientów. W przypadku użycia portu dynamicznego usługa Kestrel jest sugerowanym serwerem sieci Web.

Kestrel w usłudze Reliable Services

Bibliotekę Kestrel można użyć w usłudze Reliable Services, importując pakiet NuGet Microsoft.ServiceFabric.AspNetCore.Kestrel . Ten pakiet zawiera KestrelCommunicationListenerimplementację elementu ICommunicationListener. KestrelCommunicationListenerUmożliwia utworzenie ASP.NET Core WebHost wewnątrz niezawodnej usługi przy użyciu biblioteki Kestrel jako serwera internetowego.

Kestrel to międzyplatformowy serwer internetowy dla ASP.NET Core. W przeciwieństwie do HTTP.sys, Kestrel nie używa scentralizowanego menedżera punktów końcowych. W przeciwieństwie do HTTP.sys Kestrel nie obsługuje udostępniania portów między wieloma procesami. Każde wystąpienie 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 CreateServiceInstanceListeners metodę KestrelCommunicationListener 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 CreateServiceReplicaListeners metodę KestrelCommunicationListener i zwróć 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 elementu IReliableStateManager jest udostępniane kontenerowi wstrzykiwania zależności WebHost. Nie jest to absolutnie konieczne, ale umożliwia używanie IReliableStateManager i niezawodne kolekcje w metodach akcji kontrolera MVC.

Endpoint Nazwa 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 (na przykład na porcie 443). Podczas konfigurowania hosta internetowego do korzystania z serwera internetowego Kestrel należy skonfigurować 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();
        }))

Aby zapoznać się z pełnym przykładem samouczka, zobacz Konfigurowanie usługi Kestrel do korzystania z protokołu HTTPS.

Konfiguracja punktu końcowego

Konfiguracja nie jest wymagana Endpoint do używania narzędzia Kestrel.

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

Używanie biblioteki Kestrel ze statycznym portem

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

  • Jeśli port nie spadnie 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 temat tego, zobacz następną sekcję.

Używanie usługi Kestrel z portem dynamicznym

Kestrel nie może użyć automatycznego przypisania portów 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 Kestrel musi być otwarte na unikatowym porcie.

Aby użyć przypisania portu dynamicznego z Kestrel, pomiń Endpoint konfigurację w ServiceManifest.xml całkowicie i nie przekaż 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 z protokołem HTTPS bez portu określonego w ServiceManifest.xml i przekazać nazwę punktu końcowego do konstruktora KestrelCommunicationListener.

Integracja hostów IHost i minimalnych hostingów

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

// 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ż KestrelCommunicationListener i HttpSysCommunicationListener są przeznaczone dla usług internetowych, 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żna również używać 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 ASP.NET Core jest oparta na parach klucz-wartość ustanowionych przez dostawcę konfiguracji. Przeczytaj artykuł Configuration in ASP.NET Core (Konfiguracja w 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 Microsoft.ServiceFabric.AspNetCore.Configuration pakietu NuGet należy zarejestrować źródło konfiguracji usługi Service Fabric przy użyciu interfejsu API konfiguracji ASP.NET Core. W tym celu sprawdź 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 pakietu 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 ustawienia zaszyfrowane, podobnie jak dostawca konfiguracji usługi Service Fabric. Ustawienia zaszyfrowane nie są domyślnie odszyfrowywane do ASP.NET CoreIConfiguration. 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 wartość 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ędniana 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 niestandardowych wartości za pomocą polecenia ExtractValueFunc. Możesz nawet zmienić cały proces wypełniania danych z konfiguracji usługi Service Fabric na ASP.NET Core konfiguracji przy użyciu polecenia ConfigAction.

W poniższych przykładach pokazano, jak używać ConfigAction do dostosowywania 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 , aby ponownie załadować dane 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 tylko do użytku wewnętrznego ASP.NET Core
  • Usługi stanowe tylko ASP.NET Core

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 zazwyczaj 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 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 internetowych w tym samym zestawie węzłów przy użyciu tego samego portu. W tym scenariuszu usługi internetowe są rozróżniane przez nazwę hosta lub ścieżkę bez polegania na serwerze proxy frontonu lub bramie w celu zapewnienia routingu HTTP.

Po uwidocznieniu w Internecie 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 dla użytkowników 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ą wiedzieć unikatowych informacji identyfikujących używanych przez oprogramowanie pośredniczące.
Liczba wystąpień -1 W typowych przypadkach użycia ustawienie liczby wystąpień powinno być ustawione na wartość -1. Jest to wykonywane 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 hosta 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();
})

Usługa ASP.NET Core bezstanowa tylko wewnętrzna

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, który umożliwia wielu wystąpień usług współużytkowania 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 zapobiega błędnym problemowi z tożsamością opisanym wcześniej.
InstanceCount dowolny Ustawienie liczby wystąpień można ustawić na dowolną wartość niezbędną do obsługi usługi.

Usługa ASP.NET Core tylko stanowa

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 Nie HttpSysCommunicationListener 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 zapobiega błędnym problemowi z tożsamością opisanym 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)