ASP.NET Core i Azure Service Fabric Reliable Services

ASP.NET Core är ett ramverk med öppen källkod och plattformsoberoende. Det här ramverket är utformat för att skapa molnbaserade, Internetanslutna program, till exempel webbappar, IoT-appar och mobila serverdelar.

Den här artikeln är en djupgående guide för att vara värd för ASP.NET Core-tjänster i Service Fabric Reliable Services med hjälp av uppsättningen Microsoft.ServiceFabric.AspNetCore. med NuGet-paket.

En introduktionskurs om ASP.NET Core i Service Fabric och instruktioner för hur du konfigurerar utvecklingsmiljön finns i Självstudie: Skapa och distribuera ett program med en klientdelstjänst för ASP.NET Core Web API och en tillståndskänslig serverdelstjänst.

Resten av den här artikeln förutsätter att du redan är bekant med ASP.NET Core. Om inte kan du läsa igenom grunderna i ASP.NET Core.

ASP.NET Core i Service Fabric-miljön

Både ASP.NET Core- och Service Fabric-appar kan köras på .NET Core eller fullständigt .NET Framework. Du kan använda ASP.NET Core på två olika sätt i Service Fabric:

  • Körs som körbar gäst. Det här sättet används främst för att köra befintliga ASP.NET Core-program på Service Fabric utan kodändringar.
  • Kör i en tillförlitlig tjänst. På så sätt kan du bättre integrera med Service Fabric-körningen och tillåta tillståndskänsliga ASP.NET Core-tjänster.

Resten av den här artikeln förklarar hur du använder ASP.NET Core i en tillförlitlig tjänst, via ASP.NET Core-integreringskomponenter som levereras med Service Fabric SDK.

Service Fabric-tjänstvärd

I Service Fabric körs en eller flera instanser och/eller repliker av tjänsten i en tjänstvärdprocess: en körbar fil som kör tjänstkoden. Som tjänstförfattare äger du tjänstvärdprocessen och Service Fabric aktiverar och övervakar den åt dig.

Traditionella ASP.NET (upp till MVC 5) är tätt kopplade till IIS genom System.Web.dll. ASP.NET Core ger en separation mellan webbservern och webbappen. Den här separationen gör att webbprogram kan vara portabla mellan olika webbservrar. Det gör också att webbservrar kan vara lokalt installerade. Det innebär att du kan starta en webbserver i din egen process, till skillnad från en process som ägs av dedikerad webbserverprogramvara, till exempel IIS.

Om du vill kombinera en Service Fabric-tjänst och ASP.NET, antingen som körbar gäst eller i en tillförlitlig tjänst, måste du kunna starta ASP.NET i tjänstvärdprocessen. ASP.NET Core självvärd kan du göra detta.

Värd för ASP.NET Core i en tillförlitlig tjänst

Vanligtvis skapar lokalt installerade ASP.NET Core-program en WebHost i ett programs startpunkt, till exempel static void Main() metoden i Program.cs. I det här fallet är livscykeln för WebHost bunden till processens livscykel.

Värd för ASP.NET Core i en process

Men programmets startpunkt är inte rätt plats för att skapa en WebHost i en tillförlitlig tjänst. Det beror på att programmets startpunkt endast används för att registrera en tjänsttyp med Service Fabric-körningen, så att den kan skapa instanser av den tjänsttypen. WebHost ska skapas i en tillförlitlig tjänst. I tjänstvärdprocessen kan tjänstinstanser och/eller repliker genomgå flera livscykelr.

En Reliable Service-instans representeras av din tjänstklass som härleds från StatelessService eller StatefulService. Kommunikationsstacken för en tjänst finns i en ICommunicationListener implementering i din tjänstklass. NuGet-paketen Microsoft.ServiceFabric.AspNetCore.* innehåller implementeringar av ICommunicationListener som startar och hanterar ASP.NET Core WebHost för antingen Kestrel eller HTTP.sys i en tillförlitlig tjänst.

Diagram över värdtjänster för ASP.NET Core i en tillförlitlig tjänst

ASP.NET Core ICommunicationListeners

Implementeringarna ICommunicationListener för Kestrel och HTTP.sys i NuGet-paketen Microsoft.ServiceFabric.AspNetCore.* har liknande användningsmönster. Men de utför lite olika åtgärder som är specifika för varje webbserver.

Båda kommunikationslyssnare tillhandahåller en konstruktor som använder följande argument:

  • ServiceContext serviceContext: Det här är objektet ServiceContext som innehåller information om den tjänst som körs.
  • string endpointName: Det här är namnet på en Endpoint konfiguration i ServiceManifest.xml. Det är främst där de två kommunikationslyssnarna skiljer sig åt. HTTP.sys kräver en Endpoint konfiguration, medan Kestrel inte gör det.
  • Func<string, AspNetCoreCommunicationListener, IWebHost> build: Det här är en lambda som du implementerar, där du skapar och returnerar en IWebHost. Det gör att du kan konfigurera IWebHost det sätt som du normalt skulle göra i ett ASP.NET Core-program. Lambda innehåller en URL som genereras åt dig, beroende på vilka Service Fabric-integreringsalternativ du använder och den Endpoint konfiguration du anger. Du kan sedan ändra eller använda webbadressen för att starta webbservern.

Mellanprogram för Service Fabric-integrering

Microsoft.ServiceFabric.AspNetCore NuGet-paketet innehåller UseServiceFabricIntegration tilläggsmetoden på IWebHostBuilder som lägger till Service Fabric-medvetna mellanprogram. Det här mellanprogrammet konfigurerar Kestrel eller HTTP.sys ICommunicationListener för att registrera en unik tjänst-URL med Service Fabric Naming Service. Sedan valideras klientbegäranden för att säkerställa att klienter ansluter till rätt tjänst.

Det här steget är nödvändigt för att förhindra att klienter felaktigt ansluter till fel tjänst. Det beror på att i en miljö med delad värd, till exempel Service Fabric, kan flera webbprogram köras på samma fysiska eller virtuella dator men inte använda unika värdnamn. Det här scenariot beskrivs mer detaljerat i nästa avsnitt.

Ett fall av felaktig identitet

Tjänstrepliker, oavsett protokoll, lyssnar på en unik IP:portkombination. När en tjänstreplik har börjat lyssna på en IP:portslutpunkt rapporterar den slutpunktsadressen till Service Fabric Naming Service. Där kan klienter eller andra tjänster identifiera det. Om tjänster använder dynamiskt tilldelade programportar kan en tjänstreplik av en tillfällighet använda samma IP:portslutpunkt för en annan tjänst tidigare på samma fysiska eller virtuella dator. Detta kan leda till att en klient felaktigt ansluter till fel tjänst. Det här scenariot kan uppstå om följande sekvens av händelser inträffar:

  1. Service A lyssnar på 10.0.0.1:30000 via HTTP.
  2. Klienten löser service A och hämtar adressen 10.0.0.1:30000.
  3. Tjänst A flyttas till en annan nod.
  4. Service B är placerad på 10.0.0.1 och använder av en tillfällighet samma port 30000.
  5. Klienten försöker ansluta till tjänst A med cachelagrad adress 10.0.0.1:30000.
  6. Klienten är nu ansluten till tjänst B, utan att inse att den är ansluten till fel tjänst.

Detta kan orsaka buggar vid slumpmässiga tidpunkter som kan vara svåra att diagnostisera.

Använda unika tjänst-URL:er

För att förhindra dessa buggar kan tjänster publicera en slutpunkt till namngivningstjänsten med en unik identifierare och sedan verifiera den unika identifieraren under klientbegäranden. Det här är en samarbetsåtgärd mellan tjänster i en icke-fientlig klientorganisations betrodd miljö. Den tillhandahåller inte säker tjänstautentisering i en miljö med fientlig klientorganisation.

I en betrodd miljö lägger mellanprogrammet som läggs till av UseServiceFabricIntegration metoden automatiskt till en unik identifierare till den adress som publiceras i namngivningstjänsten. Den verifierar identifieraren för varje begäran. Om identifieraren inte matchar returnerar mellanprogrammet omedelbart ett HTTP 410 Gone-svar.

Tjänster som använder en dynamiskt tilldelad port bör använda det här mellanprogrammet.

Tjänster som använder en fast unik port har inte det här problemet i en samarbetsmiljö. En fast unik port används vanligtvis för externt riktade tjänster som behöver en välkänd port för klientprogram att ansluta till. De flesta internetuppkopplade webbprogram använder till exempel port 80 eller 443 för webbläsaranslutningar. I det här fallet ska den unika identifieraren inte vara aktiverad.

Följande diagram visar begärandeflödet med mellanprogrammet aktiverat:

Service Fabric ASP.NET Core-integrering

Både Kestrel och HTTP.sys ICommunicationListener implementeringar använder den här mekanismen på exakt samma sätt. Även om HTTP.sys internt kan skilja begäranden baserat på unika URL-sökvägar med hjälp av den underliggande HTTP.sys portdelningsfunktionen, används inte den funktionen av HTTP.sys ICommunicationListener implementeringen. Det beror på att det resulterar i HTTP 503- och HTTP 404-felstatuskoder i scenariot som beskrevs tidigare. Det gör det i sin tur svårt för klienter att fastställa avsikten med felet, eftersom HTTP 503 och HTTP 404 ofta används för att indikera andra fel.

Därför standardiseras både Kestrel- och HTTP.sys-implementeringar ICommunicationListener på mellanprogram som tillhandahålls av UseServiceFabricIntegration tilläggsmetoden. Därför behöver klienter bara utföra en åtgärd för att matcha om en tjänstslutpunkt på HTTP 410-svar.

HTTP.sys i Reliable Services

Du kan använda HTTP.sys i Reliable Services genom att importera NuGet-paketet Microsoft.ServiceFabric.AspNetCore.HttpSys . Det här paketet innehåller HttpSysCommunicationListener, en implementering av ICommunicationListener. HttpSysCommunicationListener gör att du kan skapa en ASP.NET Core WebHost i en tillförlitlig tjänst med hjälp av HTTP.sys som webbserver.

HTTP.sys bygger på Windows HTTP Server API. Det här API:et använder HTTP.sys kerneldrivrutin för att bearbeta HTTP-begäranden och dirigera dem till processer som kör webbprogram. Detta gör att flera processer på samma fysiska eller virtuella dator kan vara värdar för webbprogram på samma port, vilket är tvetydigt med antingen en unik URL-sökväg eller ett värdnamn. Dessa funktioner är användbara i Service Fabric för att vara värd för flera webbplatser i samma kluster.

Kommentar

HTTP.sys-implementeringen fungerar bara på Windows-plattformen.

Följande diagram visar hur HTTP.sys använder HTTP.sys kerneldrivrutin i Windows för portdelning:

HTTP.sys diagram

HTTP.sys i en tillståndslös tjänst

Om du vill använda HttpSys i en tillståndslös tjänst åsidosätter du CreateServiceInstanceListeners metoden och returnerar en HttpSysCommunicationListener instans:

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 i en tillståndskänslig tjänst

HttpSysCommunicationListener är för närvarande inte utformat för användning i tillståndskänsliga tjänster på grund av komplikationer med den underliggande HTTP.sys portdelningsfunktionen. Mer information finns i följande avsnitt om dynamisk portallokering med HTTP.sys. För tillståndskänsliga tjänster är Kestrel den föreslagna webbservern.

Slutpunktskonfiguration

En Endpoint konfiguration krävs för webbservrar som använder Windows HTTP Server API, inklusive HTTP.sys. Webbservrar som använder Windows HTTP Server API måste först reservera sin URL med HTTP.sys (detta utförs normalt med netsh-verktyget ).

Den här åtgärden kräver utökade privilegier som dina tjänster inte har som standard. Alternativen "http" eller "https" för egenskapen för Protocol konfigurationen Endpoint i ServiceManifest.xml används specifikt för att instruera Service Fabric-körningen att registrera en URL med HTTP.sys åt dig. Det gör den med hjälp av det starka url-prefixet för jokertecken .

Om du till exempel vill reservera http://+:80 för en tjänst använder du följande konfiguration i ServiceManifest.xml:

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

</ServiceManifest>

Och slutpunktsnamnet måste skickas till HttpSysCommunicationListener konstruktorn:

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

Använda HTTP.sys med en statisk port

Om du vill använda en statisk port med HTTP.sys anger du portnumret i konfigurationen Endpoint :

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

Använda HTTP.sys med en dynamisk port

Om du vill använda en dynamiskt tilldelad port med HTTP.sys utelämnar Port du egenskapen i konfigurationen Endpoint :

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

En dynamisk port som allokeras av en Endpoint konfiguration ger endast en port per värdprocess. Den aktuella Service Fabric-värdmodellen gör att flera tjänstinstanser och/eller repliker kan hanteras i samma process. Det innebär att var och en delar samma port när den allokeras via konfigurationen Endpoint . Flera HTTP.sys instanser kan dela en port med hjälp av den underliggande HTTP.sys portdelningsfunktionen. Men det stöds inte av på grund av HttpSysCommunicationListener de komplikationer som den introducerar för klientbegäranden. För dynamisk portanvändning är Kestrel den föreslagna webbservern.

Kestrel i Reliable Services

Du kan använda Kestrel i Reliable Services genom att importera NuGet-paketet Microsoft.ServiceFabric.AspNetCore.Kestrel . Det här paketet innehåller KestrelCommunicationListener, en implementering av ICommunicationListener. KestrelCommunicationListener gör att du kan skapa en ASP.NET Core WebHost i en tillförlitlig tjänst med hjälp av Kestrel som webbserver.

Kestrel är en plattformsoberoende webbserver för ASP.NET Core. Till skillnad från HTTP.sys använder Kestrel inte en centraliserad slutpunktshanterare. Till skillnad från HTTP.sys stöder Kestrel inte portdelning mellan flera processer. Varje instans av Kestrel måste använda en unik port. Mer information om Kestrel finns i Implementeringsinformation.

Kestrel-diagram

Kestrel i en tillståndslös tjänst

Om du vill använda Kestrel i en tillståndslös tjänst åsidosätter du CreateServiceInstanceListeners metoden och returnerar en KestrelCommunicationListener instans:

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 i en tillståndskänslig tjänst

Om du vill använda Kestrel i en tillståndskänslig tjänst åsidosätter du CreateServiceReplicaListeners metoden och returnerar en KestrelCommunicationListener instans:

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();
            ))
    };
}

I det här exemplet tillhandahålls en singleton-instans av IReliableStateManager till containern webhost-beroendeinmatning. Detta är inte absolut nödvändigt, men det gör att du kan använda IReliableStateManager och tillförlitliga samlingar i dina MVC-kontrollantåtgärder.

Ett Endpoint konfigurationsnamn anges inte i KestrelCommunicationListener en tillståndskänslig tjänst. Detta förklaras mer detaljerat i följande avsnitt.

Konfigurera Kestrel för användning av HTTPS

När du aktiverar HTTPS med Kestrel i din tjänst måste du ange flera lyssningsalternativ. ServiceInstanceListener Uppdatera för att använda en EndpointHttps-slutpunkt och lyssna på en specifik port (till exempel port 443). När du konfigurerar webbvärden för att använda Kestrel-webbservern måste du konfigurera Kestrel att lyssna efter IPv6-adresser i alla nätverksgränssnitt:

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();
        }))

Ett fullständigt exempel i en självstudiekurs finns i Konfigurera Kestrel att använda HTTPS.

Slutpunktskonfiguration

En Endpoint konfiguration krävs inte för att använda Kestrel.

Kestrel är en enkel fristående webbserver. Till skillnad från HTTP.sys (eller HttpListener) behöver den inte någon Endpoint konfiguration i ServiceManifest.xml eftersom den inte kräver URL-registrering innan du startar.

Använda Kestrel med en statisk port

Du kan konfigurera en statisk port i konfigurationen Endpoint av ServiceManifest.xml för användning med Kestrel. Även om detta inte är absolut nödvändigt erbjuder det två potentiella fördelar:

  • Om porten inte hamnar i programmets portintervall öppnas den via operativsystemets brandvägg av Service Fabric.
  • Den URL som du får via KestrelCommunicationListener använder den här porten.
  <Resources>
    <Endpoints>
      <Endpoint Protocol="http" Name="ServiceEndpoint" Port="80" />
    </Endpoints>
  </Resources>

Om en Endpoint har konfigurerats måste dess namn skickas till KestrelCommunicationListener konstruktorn:

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

Om ServiceManifest.xml inte använder någon Endpoint konfiguration utelämnar du namnet i KestrelCommunicationListener konstruktorn. I det här fallet använder den en dynamisk port. Mer information om detta finns i nästa avsnitt.

Använda Kestrel med en dynamisk port

Kestrel kan inte använda den automatiska porttilldelningen från konfigurationen Endpoint i ServiceManifest.xml. Det beror på att automatisk porttilldelning från en Endpoint konfiguration tilldelar en unik port per värdprocess, och en enda värdprocess kan innehålla flera Kestrel-instanser. Detta fungerar inte med Kestrel eftersom det inte stöder portdelning. Därför måste varje Kestrel-instans öppnas på en unik port.

Om du vill använda dynamisk porttilldelning med Kestrel utelämnar du konfigurationen Endpoint i ServiceManifest.xml helt och skickar inte ett slutpunktsnamn till KestrelCommunicationListener konstruktorn på följande sätt:

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

I den här konfigurationen KestrelCommunicationListener väljer du automatiskt en port som inte används från programmets portintervall.

För HTTPS bör slutpunkten konfigureras med HTTPS-protokollet utan en port som anges i ServiceManifest.xml och skicka slutpunktsnamnet till konstruktorn KestrelCommunicationListener.

IHost och minimal värdintegrering

Förutom IWebHost/IWebHostBuilder KestrelCommunicationListener och HttpSysCommunicationListener stöd för att skapa ASP.NET Core-tjänster med hjälp av IHost/IHostBuilder. Detta är tillgängligt från och med v5.2.1363 av Microsoft.ServiceFabric.AspNetCore.Kestrel och Microsoft.ServiceFabric.AspNetCore.HttpSys paket.

// 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();
            }))
    };
}

Kommentar

Eftersom KestrelCommunicationListener och HttpSysCommunicationListener är avsedda för webbtjänster måste du registrera/konfigurera en webbserver (med metoden ConfigureWebHostDefaults eller ConfigureWebHost ) via IHost

ASP.NET 6 introducerade modellen Minimal Hosting som är ett mer förenklat och effektiviserat sätt att skapa webbprogram. Minimal värdmodell kan också användas med KestrelCommunicationListener och 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;
            }))
    };
}

Service Fabric-konfigurationsprovider

Appkonfigurationen i ASP.NET Core baseras på nyckel/värde-par som upprättats av konfigurationsprovidern. Läs Konfiguration i ASP.NET Core om du vill veta mer om allmän ASP.NET Core-konfigurationsstöd.

I det här avsnittet beskrivs hur Service Fabric-konfigurationsprovidern integreras med ASP.NET Core-konfiguration genom att importera NuGet-paketet Microsoft.ServiceFabric.AspNetCore.Configuration .

Starttillägg för AddServiceFabricConfiguration

När du har importerat Microsoft.ServiceFabric.AspNetCore.Configuration NuGet-paketet måste du registrera Service Fabric-konfigurationskällan med ASP.NET Core-konfigurations-API. Det gör du genom att kontrollera Tillägg för Microsoft.ServiceFabric.AspNetCore.Configuration AddServiceFabricConfiguration i namnområdet mot IConfigurationBuilder.

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

Nu kan ASP.NET Core-tjänsten komma åt Service Fabric-konfigurationsinställningarna, precis som andra programinställningar. Du kan till exempel använda alternativmönstret för att läsa in inställningar i starkt skrivna objekt.

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

Standardnyckelmappning

Som standard innehåller Service Fabric-konfigurationsprovidern paketnamnet, avsnittsnamnet och egenskapsnamnet. Tillsammans utgör dessa konfigurationsnyckeln ASP.NET Core enligt följande:

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

Om du till exempel har ett konfigurationspaket med namnet MyConfigPackage med följande innehåll blir konfigurationsvärdet tillgängligt på ASP.NET Core IConfiguration via 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>

Konfigurationsalternativ för Service Fabric

Service Fabric-konfigurationsprovidern har också stöd ServiceFabricConfigurationOptions för att ändra standardbeteendet för nyckelmappning.

Krypterade inställningar

Service Fabric stöder krypterade inställningar, liksom Service Fabric-konfigurationsprovidern. De krypterade inställningarna dekrypteras inte till ASP.NET Core IConfiguration som standard. De krypterade värdena lagras där i stället. Men om du vill dekryptera värdet som ska lagras i ASP.NET Core IConfiguration kan du ange flaggan DecryptValue till false i AddServiceFabricConfiguration tillägget enligt följande:

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();
}

Flera konfigurationspaket

Service Fabric stöder flera konfigurationspaket. Som standard ingår paketnamnet i konfigurationsnyckeln. Men du kan ställa in flaggan på IncludePackageName false enligt följande:

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

Anpassad nyckelmappning, värdeextrahering och datapopulation

Service Fabric-konfigurationsprovidern har också stöd för mer avancerade scenarier för att anpassa nyckelmappningen med ExtractKeyFunc och extrahera värdena med ExtractValueFunc. Du kan till och med ändra hela processen för att fylla i data från Service Fabric-konfigurationen till ASP.NET Core-konfiguration med hjälp ConfigActionav .

Följande exempel visar hur du använder ConfigAction för att anpassa datapopulationen:

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();
}

Konfigurationsuppdateringar

Service Fabric-konfigurationsprovidern stöder även konfigurationsuppdateringar. Du kan använda ASP.NET Core IOptionsMonitor för att ta emot ändringsmeddelanden och sedan använda IOptionsSnapshot för att läsa in konfigurationsdata igen. Mer information finns i ASP.NET Core-alternativ.

De här alternativen stöds som standard. Ingen ytterligare kodning krävs för att aktivera konfigurationsuppdateringar.

Scenarier och konfigurationer

Det här avsnittet innehåller kombinationen av webbserver, portkonfiguration, Service Fabric-integreringsalternativ och diverse inställningar som vi rekommenderar för att felsöka följande scenarier:

  • Externt exponerade ASP.NET Tillståndslösa kärntjänster
  • Tillståndslösa tjänster med endast internt ASP.NET Core
  • Tillståndskänsliga tjänster med endast intern ASP.NET Core

En externt exponerad tjänst är en tjänst som exponerar en slutpunkt som anropas utanför klustret, vanligtvis via en lastbalanserare.

En intern tjänst är en vars slutpunkt bara anropas inifrån klustret.

Kommentar

Tillståndskänsliga tjänstslutpunkter bör vanligtvis inte exponeras för Internet. Kluster bakom lastbalanserare som inte känner till Service Fabric-tjänstmatchning, till exempel Azure Load Balancer, kommer inte att kunna exponera tillståndskänsliga tjänster. Det beror på att lastbalanseraren inte kan hitta och dirigera trafik till lämplig tillståndskänslig tjänstreplik.

Externt exponerade ASP.NET Tillståndslösa kärntjänster

Kestrel är den föreslagna webbservern för klientdelstjänster som exponerar externa, Internetuppkopplade HTTP-slutpunkter. I Windows kan HTTP.sys tillhandahålla portdelningsfunktioner, vilket gör att du kan vara värd för flera webbtjänster på samma uppsättning noder med samma port. I det här scenariot särskiljs webbtjänsterna efter värdnamn eller sökväg, utan att förlita sig på en klientdelsproxy eller gateway för att tillhandahålla HTTP-routning.

När den exponeras för Internet bör en tillståndslös tjänst använda en välkänd och stabil slutpunkt som kan nås via en lastbalanserare. Du anger den här URL:en till programmets användare. Vi rekommenderar följande konfiguration:

Typ Rekommendation Kommentar
Webbserver Kestrel Kestrel är den föredragna webbservern eftersom den stöds i Windows och Linux.
Portkonfiguration static En välkänd statisk port bör konfigureras i konfigurationen Endpoints av ServiceManifest.xml, till exempel 80 för HTTP eller 443 för HTTPS.
ServiceFabricIntegrationOptions Ingen Använd alternativet ServiceFabricIntegrationOptions.None när du konfigurerar Service Fabric-integreringsmellanprogram, så att tjänsten inte försöker verifiera inkommande begäranden för en unik identifierare. Externa användare av ditt program känner inte till den unika identifieringsinformation som mellanprogrammet använder.
Antal instanser -1 I vanliga användningsfall bör inställningen för antal instanser anges till -1. Detta görs så att en instans är tillgänglig på alla noder som tar emot trafik från en lastbalanserare.

Om flera externt exponerade tjänster delar samma uppsättning noder kan du använda HTTP.sys med en unik men stabil URL-sökväg. Du kan göra detta genom att ändra url:en som angavs när du konfigurerade IWebHost. Observera att detta endast gäller för HTTP.sys.

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

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

Tillståndslös ASP.NET Core-tjänst endast internt

Tillståndslösa tjänster som endast anropas inifrån klustret bör använda unika URL:er och dynamiskt tilldelade portar för att säkerställa samarbete mellan flera tjänster. Vi rekommenderar följande konfiguration:

Typ Rekommendation Kommentar
Webbserver Kestrel Även om du kan använda HTTP.sys för interna tillståndslösa tjänster är Kestrel den bästa servern för att tillåta flera tjänstinstanser att dela en värd.
Portkonfiguration dynamiskt tilldelad Flera repliker av en tillståndskänslig tjänst kan dela en värdprocess eller värdoperativsystem och behöver därför unika portar.
ServiceFabricIntegrationOptions UseUniqueServiceUrl Med dynamisk porttilldelning förhindrar den här inställningen det felaktiga identitetsproblem som beskrevs tidigare.
InstanceCount någon Instansantalsinställningen kan ställas in på valfritt värde som krävs för att använda tjänsten.

Tillståndskänslig ASP.NET Core-tjänst endast internt

Tillståndskänsliga tjänster som endast anropas inifrån klustret bör använda dynamiskt tilldelade portar för att säkerställa samarbete mellan flera tjänster. Vi rekommenderar följande konfiguration:

Typ Rekommendation Kommentar
Webbserver Kestrel HttpSysCommunicationListener Är inte utformad för användning av tillståndskänsliga tjänster där repliker delar en värdprocess.
Portkonfiguration dynamiskt tilldelad Flera repliker av en tillståndskänslig tjänst kan dela en värdprocess eller värdoperativsystem och behöver därför unika portar.
ServiceFabricIntegrationOptions UseUniqueServiceUrl Med dynamisk porttilldelning förhindrar den här inställningen det felaktiga identitetsproblem som beskrevs tidigare.

Nästa steg

Felsöka ditt Service Fabric-program med Visual Studio