ASP.NET Core in Azure Service Fabric Reliable Services

ASP.NET Core is een opensource- en platformoverschrijdend framework. Dit framework is ontworpen voor het bouwen van cloudtoepassingen die zijn verbonden met internet, zoals web-apps, IoT-apps en mobiele back-ends.

Dit artikel is een uitgebreide handleiding voor het hosten van ASP.NET Core services in Service Fabric Reliable Services met behulp van de Microsoft.ServiceFabric.AspNetCore. set NuGet-pakketten.

Zie Zelfstudie: Een toepassing maken en implementeren met een ASP.NET Core web-API-front-endservice en een stateful back-endservice voor een inleidende zelfstudie over ASP.NET Core in Service Fabric en instructies voor het instellen van uw ontwikkelomgeving.

In de rest van dit artikel wordt ervan uitgegaan dat u al bekend bent met ASP.NET Core. Zo niet, lees dan de basisprincipes van de ASP.NET Core door.

ASP.NET Core in de Service Fabric-omgeving

Zowel ASP.NET Core- als Service Fabric-apps kunnen worden uitgevoerd op .NET Core of volledige .NET Framework. U kunt ASP.NET Core op twee verschillende manieren gebruiken in Service Fabric:

  • Gehost als een uitvoerbare gast. Deze manier wordt voornamelijk gebruikt voor het uitvoeren van bestaande ASP.NET Core toepassingen op Service Fabric zonder codewijzigingen.
  • Voer uit binnen een betrouwbare service. Op deze manier is een betere integratie met de Service Fabric-runtime mogelijk en staat stateful ASP.NET Core-services toe.

In de rest van dit artikel wordt uitgelegd hoe u ASP.NET Core in een betrouwbare service kunt gebruiken via de ASP.NET Core integratieonderdelen die worden geleverd met de Service Fabric SDK.

Service Fabric-servicehosting

In Service Fabric worden een of meer exemplaren en/of replica's van uw service uitgevoerd in een servicehostproces: een uitvoerbaar bestand waarmee uw servicecode wordt uitgevoerd. U, als serviceauteur, bent de eigenaar van het servicehostproces en Service Fabric activeert en bewaakt dit voor u.

Traditionele ASP.NET (tot MVC 5) is nauw gekoppeld aan IIS via System.Web.dll. ASP.NET Core biedt een scheiding tussen de webserver en uw webtoepassing. Door deze scheiding kunnen webtoepassingen overdraagbaar zijn tussen verschillende webservers. Hiermee kunnen webservers ook zelf-hosten. Dit betekent dat u een webserver in uw eigen proces kunt starten, in plaats van een proces dat eigendom is van toegewezen webserversoftware, zoals IIS.

Als u een Service Fabric-service en ASP.NET wilt combineren, als uitvoerbare gast of in een betrouwbare service, moet u ASP.NET kunnen starten binnen het proces van de servicehost. ASP.NET Core self-hosting stelt u in staat om dit te doen.

Hosting ASP.NET Core in een betrouwbare service

Normaal gesproken maken zelf-hostende ASP.NET Core toepassingen een webhost in het toegangspunt van een toepassing, zoals de static void Main() methode in Program.cs. In dit geval is de levenscyclus van de WebHost gebonden aan de levenscyclus van het proces.

Hosting ASP.NET Core in een proces

Maar het ingangspunt van de toepassing is niet de juiste plek om een webhost te maken in een betrouwbare service. Dat komt omdat het toegangspunt van de toepassing alleen wordt gebruikt om een servicetype te registreren bij de Service Fabric-runtime, zodat er exemplaren van dat servicetype kunnen worden gemaakt. De webhost moet worden gemaakt in een betrouwbare service zelf. Binnen het servicehostproces kunnen service-exemplaren en/of replica's meerdere levenscycluscycli doorlopen.

Een Reliable Service-exemplaar wordt vertegenwoordigd door uw serviceklasse die is afgeleid van StatelessService of StatefulService. De communicatiestack voor een service is opgenomen in een ICommunicationListener implementatie in uw serviceklasse. De Microsoft.ServiceFabric.AspNetCore.* NuGet-pakketten bevatten implementaties van ICommunicationListener die de ASP.NET Core WebHost starten en beheren voor Kestrel of HTTP.sys in een betrouwbare service.

Diagram voor het hosten van ASP.NET Core in een betrouwbare service

ASP.NET Core ICommunicationListeners

De ICommunicationListener implementaties voor Kestrel en HTTP.sys in de Microsoft.ServiceFabric.AspNetCore.* NuGet-pakketten hebben vergelijkbare gebruikspatronen. Maar ze voeren iets verschillende acties uit die specifiek zijn voor elke webserver.

Beide communicatielisteners bieden een constructor met de volgende argumenten:

  • ServiceContext serviceContext: dit is het ServiceContext object dat informatie bevat over de actieve service.
  • string endpointName: dit is de naam van een Endpoint configuratie in ServiceManifest.xml. Dit is voornamelijk waar de twee communicatielisteners verschillen. HTTP.sys vereist een Endpoint configuratie, maar Kestrel niet.
  • Func<string, AspNetCoreCommunicationListener, IWebHost> build: dit is een lambda die u implementeert, waarin u een maakt en retourneert IWebHost. Hiermee kunt u configureren IWebHost zoals u dat normaal zou doen in een ASP.NET Core-toepassing. De lambda biedt een URL die voor u wordt gegenereerd, afhankelijk van de Service Fabric-integratieopties die u gebruikt en de Endpoint configuratie die u opgeeft. Vervolgens kunt u die URL wijzigen of gebruiken om de webserver te starten.

Service Fabric-integratie-middleware

Het Microsoft.ServiceFabric.AspNetCore NuGet-pakket bevat de UseServiceFabricIntegration extensiemethode op IWebHostBuilder waarmee Service Fabric-compatibele middleware wordt toegevoegd. Deze middleware configureert de Kestrel of HTTP.sys ICommunicationListener om een unieke service-URL te registreren bij de Service Fabric-naamgevingsservice. Vervolgens worden clientaanvragen gevalideerd om ervoor te zorgen dat clients verbinding maken met de juiste service.

Deze stap is nodig om te voorkomen dat clients per ongeluk verbinding maken met de verkeerde service. Dat komt doordat in een omgeving met gedeelde host, zoals Service Fabric, meerdere webtoepassingen kunnen worden uitgevoerd op dezelfde fysieke of virtuele machine, maar geen unieke hostnamen gebruiken. Dit scenario wordt uitgebreid beschreven in de volgende sectie.

Een geval van verkeerde identiteit

Servicereplica's, ongeacht het protocol, luisteren op een unieke combinatie van IP:poort. Zodra een servicereplica is begonnen met luisteren op een IP:poort-eindpunt, rapporteert het dat eindpuntadres aan de Service Fabric-naamgevingsservice. Daar kunnen klanten of andere services het detecteren. Als services dynamisch toegewezen toepassingspoorten gebruiken, kan een servicereplica per ongeluk hetzelfde IP:poorteindpunt van een andere service gebruiken op dezelfde fysieke of virtuele machine. Dit kan ertoe leiden dat een client per ongeluk verbinding maakt met de verkeerde service. Dit scenario kan het gevolg zijn als de volgende reeks gebeurtenissen zich voordoet:

  1. Service A luistert op 10.0.0.1:30000 via HTTP.
  2. Client zet Service A om en krijgt adres 10.0.0.1:30000.
  3. Service A wordt verplaatst naar een ander knooppunt.
  4. Service B wordt op 10.0.0.1 geplaatst en gebruikt toevallig dezelfde poort 30000.
  5. Client probeert verbinding te maken met service A met in de cache opgeslagen adres 10.0.0.1:30000.
  6. De client is nu verbonden met service B en realiseert zich niet dat deze is verbonden met de verkeerde service.

Dit kan op willekeurige momenten fouten veroorzaken die moeilijk te diagnosticeren zijn.

Unieke service-URL's gebruiken

Om deze fouten te voorkomen, kunnen services een eindpunt naar de naamgevingsservice posten met een unieke id en deze unieke id vervolgens valideren tijdens clientaanvragen. Dit is een samenwerkingsactie tussen services in een niet-vijandige tenant vertrouwde omgeving. Het biedt geen veilige serviceverificatie in een omgeving met vijandige tenants.

In een vertrouwde omgeving voegt de middleware die door de UseServiceFabricIntegration methode wordt toegevoegd, automatisch een unieke id toe aan het adres dat is gepost in de naamgevingsservice. Deze id wordt voor elke aanvraag gevalideerd. Als de id niet overeenkomt, retourneert de middleware onmiddellijk een HTTP 410 Gone-antwoord.

Services die gebruikmaken van een dynamisch toegewezen poort, moeten gebruikmaken van deze middleware.

Services die gebruikmaken van een vaste unieke poort hebben dit probleem niet in een samenwerkingsomgeving. Een vaste unieke poort wordt doorgaans gebruikt voor extern gerichte services die een bekende poort nodig hebben voor clienttoepassingen om verbinding mee te maken. De meeste internetgerichte webtoepassingen gebruiken bijvoorbeeld poort 80 of 443 voor webbrowserverbindingen. In dit geval mag de unieke id niet worden ingeschakeld.

In het volgende diagram ziet u de aanvraagstroom met de middleware ingeschakeld:

Service Fabric ASP.NET Core-integratie

Zowel Kestrel als HTTP.sys ICommunicationListener implementaties gebruiken dit mechanisme op precies dezelfde manier. Hoewel HTTP.sys aanvragen intern kunt onderscheiden op basis van unieke URL-paden met behulp van de onderliggende functie voor het delen van poortenHTTP.sys , wordt deze functionaliteit niet gebruikt door de HTTP.sys-implementatie ICommunicationListener . Dat komt omdat dit resulteert in HTTP 503- en HTTP 404-foutcodes in het eerder beschreven scenario. Dit maakt het op zijn beurt moeilijk voor clients om de intentie van de fout te bepalen, omdat HTTP 503 en HTTP 404 vaak worden gebruikt om andere fouten aan te geven.

Zowel Kestrel- als HTTP.sys-implementaties ICommunicationListener standaardiseren dus op middleware die wordt geleverd door de UseServiceFabricIntegration extensiemethode. Daarom hoeven clients alleen een actie voor het opnieuw omzetten van een service-eindpunt uit te voeren op HTTP 410-antwoorden.

HTTP.sys in Reliable Services

U kunt HTTP.sys in Reliable Services gebruiken door het NuGet-pakket Microsoft.ServiceFabric.AspNetCore.HttpSys te importeren. Dit pakket bevat HttpSysCommunicationListener, een implementatie van ICommunicationListener. HttpSysCommunicationListenerhiermee kunt u een ASP.NET Core WebHost binnen een betrouwbare service maken door HTTP.sys als webserver te gebruiken.

HTTP.sys is gebaseerd op de Windows HTTP Server-API. Deze API maakt gebruik van het HTTP.sys kernelstuurprogramma om HTTP-aanvragen te verwerken en deze te routeren naar processen die webtoepassingen uitvoeren. Hierdoor kunnen meerdere processen op dezelfde fysieke of virtuele machine webtoepassingen hosten op dezelfde poort, ondubbelzinnig door een uniek URL-pad of een hostnaam. Deze functies zijn handig in Service Fabric voor het hosten van meerdere websites in hetzelfde cluster.

Notitie

HTTP.sys implementatie werkt alleen op het Windows-platform.

In het volgende diagram ziet u hoe HTTP.sys het HTTP.sys kernelstuurprogramma in Windows gebruikt voor het delen van poorten:

HTTP.sys diagram

HTTP.sys in een stateless service

Als u wilt gebruiken HttpSys in een staatloze service, overschrijft u de CreateServiceInstanceListeners methode en retourneert u een HttpSysCommunicationListener exemplaar:

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 in een stateful service

HttpSysCommunicationListener is momenteel niet ontworpen voor gebruik in stateful services vanwege complicaties met de onderliggende functie voor het delen van poortenHTTP.sys . Zie de volgende sectie over dynamische poorttoewijzing met HTTP.sys voor meer informatie. Voor stateful services is Kestrel de voorgestelde webserver.

Eindpuntconfiguratie

Er is een Endpoint configuratie vereist voor webservers die gebruikmaken van de Windows HTTP Server-API, inclusief HTTP.sys. Webservers die gebruikmaken van de Windows HTTP Server-API moeten eerst hun URL bij HTTP.sys reserveren (dit wordt normaal gesproken gedaan met het hulpprogramma netsh ).

Voor deze actie zijn verhoogde bevoegdheden vereist die uw services niet standaard hebben. De opties 'http' of 'https' voor de Protocol eigenschap van de Endpoint configuratie in ServiceManifest.xml worden specifiek gebruikt om de Service Fabric-runtime te instrueren om namens u een URL met HTTP.sys te registreren. Dit doet u met behulp van het sterke URL-voorvoegsel met jokertekens .

Als u bijvoorbeeld wilt reserveren http://+:80 voor een service, gebruikt u de volgende configuratie in ServiceManifest.xml:

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

</ServiceManifest>

En de naam van het eindpunt moet worden doorgegeven aan de HttpSysCommunicationListener constructor:

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

Gebruik HTTP.sys met een statische poort

Als u een statische poort wilt gebruiken met HTTP.sys, geeft u het poortnummer op in de Endpoint configuratie:

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

Gebruik HTTP.sys met een dynamische poort

Als u een dynamisch toegewezen poort met HTTP.sys wilt gebruiken, laat u de Port eigenschap weg in de Endpoint configuratie:

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

Een dynamische poort die is toegewezen door een Endpoint configuratie, biedt slechts één poort per hostproces. Met het huidige Service Fabric-hostingmodel kunnen meerdere service-exemplaren en/of replica's in hetzelfde proces worden gehost. Dit betekent dat elke poort dezelfde poort deelt wanneer deze wordt toegewezen via de Endpoint configuratie. Meerdere HTTP.sys-exemplaren kunnen een poort delen met behulp van de onderliggende functieHTTP.sys poort delen. Maar het wordt niet ondersteund door HttpSysCommunicationListener vanwege de complicaties die het introduceert voor clientaanvragen. Voor dynamisch poortgebruik is Kestrel de voorgestelde webserver.

Kestrel in Reliable Services

U kunt Kestrel in Reliable Services gebruiken door het NuGet-pakket Microsoft.ServiceFabric.AspNetCore.Kestrel te importeren. Dit pakket bevat KestrelCommunicationListener, een implementatie van ICommunicationListener. KestrelCommunicationListenerhiermee kunt u een ASP.NET Core WebHost binnen een betrouwbare service maken door Kestrel als webserver te gebruiken.

Kestrel is een platformoverschrijdende webserver voor ASP.NET Core. In tegenstelling tot HTTP.sys gebruikt Kestrel geen gecentraliseerd eindpuntbeheer. In tegenstelling tot HTTP.sys biedt Kestrel geen ondersteuning voor het delen van poorten tussen meerdere processen. Elk exemplaar van Kestrel moet een unieke poort gebruiken. Zie implementatiedetails voor meer informatie over Kestrel.

Kestreldiagram

Kestrel in een staatloze service

Als u wilt gebruiken Kestrel in een staatloze service, overschrijft u de CreateServiceInstanceListeners methode en retourneert u een KestrelCommunicationListener exemplaar:

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 in een stateful service

Als u wilt gebruiken Kestrel in een stateful service, overschrijft u de CreateServiceReplicaListeners methode en retourneert u een KestrelCommunicationListener exemplaar:

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

In dit voorbeeld wordt een singleton-exemplaar van IReliableStateManager opgegeven voor de webhost-afhankelijkheidsinjectiecontainer. Dit is niet strikt noodzakelijk, maar hiermee kunt u betrouwbare verzamelingen gebruiken IReliableStateManager in de actiemethoden van uw MVC-controller.

Er Endpoint is geen configuratienaam opgegeven voor KestrelCommunicationListener in een stateful service. Dit wordt gedetailleerder uitgelegd in de volgende sectie.

Kestrel configureren voor gebruik van HTTPS

Wanneer u HTTPS inschakelt met Kestrel in uw service, moet u verschillende luisteropties instellen. Werk de ServiceInstanceListener bij om een EndpointHttps-eindpunt te gebruiken en te luisteren op een specifieke poort (zoals poort 443). Wanneer u de webhost configureert voor het gebruik van de Kestrel-webserver, moet u Kestrel configureren om te luisteren naar IPv6-adressen op alle netwerkinterfaces:

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

Zie Kestrel configureren voor het gebruik van HTTPS voor een volledig voorbeeld in een zelfstudie.

Eindpuntconfiguratie

Er Endpoint is geen configuratie vereist om Kestrel te gebruiken.

Kestrel is een eenvoudige zelfstandige webserver. In tegenstelling tot HTTP.sys (of HttpListener) is er geen configuratie nodig Endpoint in ServiceManifest.xml omdat hiervoor geen URL-registratie is vereist voordat u begint.

Kestrel gebruiken met een statische poort

U kunt een statische poort configureren in de Endpoint configuratie van ServiceManifest.xml voor gebruik met Kestrel. Hoewel dit niet strikt noodzakelijk is, biedt het twee potentiële voordelen:

  • Als de poort niet binnen het bereik van de toepassingspoort valt, wordt deze geopend via de firewall van het besturingssysteem door Service Fabric.
  • De URL die u via KestrelCommunicationListener krijgt, gebruikt deze poort.
  <Resources>
    <Endpoints>
      <Endpoint Protocol="http" Name="ServiceEndpoint" Port="80" />
    </Endpoints>
  </Resources>

Als een Endpoint is geconfigureerd, moet de naam ervan worden doorgegeven aan de KestrelCommunicationListener constructor:

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

Als ServiceManifest.xml geen configuratie gebruikt Endpoint , laat u de naam weg in de KestrelCommunicationListener constructor. In dit geval wordt een dynamische poort gebruikt. Zie de volgende sectie voor meer informatie hierover.

Kestrel gebruiken met een dynamische poort

Kestrel kan de automatische poorttoewijzing uit de Endpoint configuratie in ServiceManifest.xml niet gebruiken. Dat komt doordat automatische poorttoewijzing vanuit een Endpoint configuratie een uniek poortproces per host toewijst en één hostproces meerdere Kestrel-exemplaren kan bevatten. Dit werkt niet met Kestrel omdat het delen van poorten niet ondersteunt. Daarom moet elk exemplaar van Kestrel worden geopend op een unieke poort.

Als u dynamische poorttoewijzing wilt gebruiken met Kestrel, laat u de Endpoint configuratie als volgt weg in ServiceManifest.xml en geeft u geen eindpuntnaam door aan de KestrelCommunicationListener constructor:

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

In deze configuratie KestrelCommunicationListener selecteert automatisch een ongebruikte poort in het bereik van de toepassingspoort.

Voor HTTPS moet het eindpunt zijn geconfigureerd met het HTTPS-protocol zonder een poort die is opgegeven in ServiceManifest.xml en moet de naam van het eindpunt worden doorgegeven aan de constructor KestrelCommunicationListener.

Integratie van IHost en minimale hosting

Naast IWebHost/IWebHostBuilder en KestrelCommunicationListenerHttpSysCommunicationListener ondersteuning voor het bouwen van ASP.NET Core services met behulp van IHost/IHostBuilder. Dit is beschikbaar vanaf v5.2.1363 van Microsoft.ServiceFabric.AspNetCore.Kestrel pakketten en 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();
            }))
    };
}

Notitie

Aangezien KestrelCommunicationListener en HttpSysCommunicationListener zijn bedoeld voor webservices, moet u een webserver registreren/configureren (met behulp van de methode ConfigureWebHostDefaults of ConfigureWebHost ) via de IHost

ASP.NET 6 heeft het model Minimale hosting geïntroduceerd. Dit is een eenvoudigere en gestroomlijnde manier om webtoepassingen te maken. Minimaal hostingmodel kan ook worden gebruikt met KestrelCommunicationListener en 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-configuratieprovider

App-configuratie in ASP.NET Core is gebaseerd op sleutel-waardeparen die zijn ingesteld door de configuratieprovider. Lees Configuratie in ASP.NET Core voor meer informatie over algemene ondersteuning voor ASP.NET Core configuratie.

In deze sectie wordt beschreven hoe de Service Fabric-configuratieprovider kan worden geïntegreerd met ASP.NET Core configuratie door het Microsoft.ServiceFabric.AspNetCore.Configuration NuGet-pakket te importeren.

AddServiceFabricConfiguration-opstartextensies

Nadat u het Microsoft.ServiceFabric.AspNetCore.Configuration NuGet-pakket hebt geïmporteerd, moet u de Service Fabric-configuratiebron registreren bij ASP.NET Core configuratie-API. U doet dit door AddServiceFabricConfiguration-extensies in de Microsoft.ServiceFabric.AspNetCore.Configuration naamruimte te controleren op 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; }

De ASP.NET Core-service heeft nu toegang tot de configuratie-instellingen van Service Fabric, net als alle andere toepassingsinstellingen. U kunt bijvoorbeeld het optiepatroon gebruiken om instellingen te laden in sterk getypte objecten.

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

Standaardsleuteltoewijzing

Standaard bevat de Service Fabric-configuratieprovider de pakketnaam, sectienaam en eigenschapsnaam. Samen vormen deze als volgt de ASP.NET Core configuratiesleutel:

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

Als u bijvoorbeeld een configuratiepakket met de naam MyConfigPackage met de volgende inhoud hebt, is de configuratiewaarde beschikbaar op 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>

Service Fabric-configuratieopties

De Service Fabric-configuratieprovider ondersteunt ServiceFabricConfigurationOptions ook het wijzigen van het standaardgedrag van sleuteltoewijzing.

Versleutelde instellingen

Service Fabric ondersteunt versleutelde instellingen, net als de Service Fabric-configuratieprovider. De versleutelde instellingen worden niet standaard ontsleuteld naar ASP.NET CoreIConfiguration. De versleutelde waarden worden daar opgeslagen. Maar als u de waarde wilt ontsleutelen die moet worden opgeslagen in ASP.NET Core IConfiguration, kunt u de vlag DecryptValue als volgt instellen op false in de AddServiceFabricConfiguration extensie:

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

Meerdere configuratiepakketten

Service Fabric ondersteunt meerdere configuratiepakketten. Standaard is de pakketnaam opgenomen in de configuratiesleutel. Maar u kunt de IncludePackageName vlag als volgt instellen op onwaar:

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

Aangepaste sleuteltoewijzing, waardeextractie en gegevenspopulatie

De Service Fabric-configuratieprovider ondersteunt ook geavanceerdere scenario's voor het aanpassen van de sleuteltoewijzing met ExtractKeyFunc en het extraheren van de waarden met ExtractValueFunc. U kunt zelfs het hele proces van het invullen van gegevens van Service Fabric-configuratie wijzigen in ASP.NET Core-configuratie met behulp van ConfigAction.

In de volgende voorbeelden ziet u hoe u ConfigAction gegevenspopulatie kunt aanpassen:

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

Configuratie-updates

De Service Fabric-configuratieprovider ondersteunt ook configuratie-updates. U kunt ASP.NET Core IOptionsMonitor gebruiken om wijzigingsmeldingen te ontvangen en vervolgens gebruiken IOptionsSnapshot om configuratiegegevens opnieuw te laden. Zie ASP.NET Core opties voor meer informatie.

Deze opties worden standaard ondersteund. Er is geen verdere codering nodig om configuratie-updates in te schakelen.

Scenario's en configuraties

Deze sectie bevat de combinatie van webserver, poortconfiguratie, Service Fabric-integratieopties en diverse instellingen die we aanraden om de volgende scenario's op te lossen:

  • Extern beschikbaar ASP.NET Core stateless services
  • Alleen interne ASP.NET Core staatloze services
  • Alleen interne ASP.NET Core stateful services

Een extern beschikbaar gemaakte service is een service die een eindpunt beschikbaar maakt dat van buiten het cluster wordt aangeroepen, meestal via een load balancer.

Een interne service is een service waarvan het eindpunt alleen vanuit het cluster wordt aangeroepen.

Notitie

Stateful service-eindpunten mogen over het algemeen niet worden blootgesteld aan internet. Clusters achter load balancers die niet op de hoogte zijn van Service Fabric-serviceomzetting, zoals Azure Load Balancer, kunnen stateful services niet beschikbaar maken. Dat komt omdat de load balancer geen verkeer kan vinden en routeren naar de juiste stateful servicereplica.

Extern beschikbaar ASP.NET Core stateless services

Kestrel is de voorgestelde webserver voor front-endservices die externe, internetgerichte HTTP-eindpunten beschikbaar maken. In Windows kunt HTTP.sys de mogelijkheid voor het delen van poorten bieden, zodat u meerdere webservices op dezelfde set knooppunten kunt hosten met dezelfde poort. In dit scenario worden de webservices onderscheiden op hostnaam of -pad, zonder dat ze afhankelijk zijn van een front-endproxy of gateway om HTTP-routering te bieden.

Wanneer een staatloze service wordt blootgesteld aan internet, moet een bekend en stabiel eindpunt worden gebruikt dat bereikbaar is via een load balancer. U geeft deze URL op aan de gebruikers van uw toepassing. We raden de volgende configuratie aan:

Type Aanbeveling Notities
Webserver Torenvalk Kestrel is de voorkeurswebserver, omdat deze wordt ondersteund in Windows en Linux.
Poortconfiguratie statisch Een bekende statische poort moet worden geconfigureerd in de Endpoints configuratie van ServiceManifest.xml, zoals 80 voor HTTP of 443 voor HTTPS.
ServiceFabricIntegrationOptions Geen Gebruik de optie bij het ServiceFabricIntegrationOptions.None configureren van Service Fabric-integratie-middleware, zodat de service niet probeert binnenkomende aanvragen te valideren voor een unieke id. Externe gebruikers van uw toepassing kennen de unieke identificatiegegevens die de middleware gebruikt niet.
Aantal instanties -1 In typische gebruiksvoorbeelden moet de instelling voor het aantal exemplaren worden ingesteld op -1. Dit wordt gedaan zodat een exemplaar beschikbaar is op alle knooppunten die verkeer van een load balancer ontvangen.

Als meerdere extern beschikbaar gestelde services dezelfde set knooppunten delen, kunt u HTTP.sys gebruiken met een uniek, maar stabiel URL-pad. U kunt dit doen door de URL te wijzigen die is opgegeven bij het configureren van IWebHost. Houd er rekening mee dat dit alleen van toepassing is op HTTP.sys.

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

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

Alleen interne staatloze ASP.NET Core-service

Stateless services die alleen vanuit het cluster worden aangeroepen, moeten gebruikmaken van unieke URL's en dynamisch toegewezen poorten om samenwerking tussen meerdere services te garanderen. We raden de volgende configuratie aan:

Type Aanbeveling Notities
Webserver Torenvalk Hoewel u HTTP.sys kunt gebruiken voor interne stateless services, is Kestrel de beste server om meerdere service-exemplaren toe te staan een host te delen.
Poortconfiguratie dynamisch toegewezen Meerdere replica's van een stateful service delen mogelijk een hostproces of hostbesturingssysteem en hebben daarom unieke poorten nodig.
ServiceFabricIntegrationOptions UseUniqueServiceUrl Met dynamische poorttoewijzing voorkomt deze instelling het eerder beschreven verkeerde identiteitsprobleem.
InstanceCount alle De instelling voor het aantal exemplaren kan worden ingesteld op elke waarde die nodig is om de service uit te voeren.

Alleen interne stateful ASP.NET Core-service

Stateful services die alleen vanuit het cluster worden aangeroepen, moeten dynamisch toegewezen poorten gebruiken om samenwerking tussen meerdere services te garanderen. We raden de volgende configuratie aan:

Type Aanbeveling Notities
Webserver Torenvalk De HttpSysCommunicationListener is niet ontworpen voor gebruik door stateful services waarin replica's een hostproces delen.
Poortconfiguratie dynamisch toegewezen Meerdere replica's van een stateful service delen mogelijk een hostproces of hostbesturingssysteem en hebben daarom unieke poorten nodig.
ServiceFabricIntegrationOptions UseUniqueServiceUrl Met dynamische poorttoewijzing voorkomt deze instelling het eerder beschreven verkeerde identiteitsprobleem.

Volgende stappen

Foutopsporing uitvoeren in uw Service Fabric-toepassing met behulp van Visual Studio