Delen via


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.

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

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 ASP.NET Core.

ASP.NET Core in de Service Fabric-omgeving

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

  • Gehost als een uitvoerbaar gastbestand. Op deze manier wordt voornamelijk gebruikgemaakt van het uitvoeren van bestaande ASP.NET Core-toepassingen in Service Fabric zonder codewijzigingen.
  • Voer in een betrouwbare service uit. Op deze manier kunt u betere integratie met de Service Fabric-runtime en stateful ASP.NET Core-services toestaan.

In de rest van dit artikel wordt uitgelegd hoe u ASP.NET Core binnen 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 auteur van de service, bent eigenaar van het servicehostproces en Service Fabric activeert en bewaakt het 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. Met deze scheiding kunnen webtoepassingen draagbaar zijn tussen verschillende webservers. Hiermee kunnen webservers ook zelf worden gehost. 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 uitvoerbaar gastbestand of in een betrouwbare service, moet u ASP.NET binnen het servicehostproces kunnen starten. ASP.NET Core selfhosting kunt u dit 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.

Hosten ASP.NET Core in een proces

Maar het ingangspunt van de toepassing is niet de juiste plaats om een WebHost in een betrouwbare service te maken. Dat komt doordat het invoerpunt van de toepassing alleen wordt gebruikt voor het registreren van een servicetype 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 levenscycluss doorlopen.

Een Reliable Service-exemplaar wordt vertegenwoordigd door uw serviceklasse die is afgeleid van StatelessService of StatefulService. De communicatiestack voor een service bevindt zich in een ICommunicationListener implementatie in uw serviceklasse. De Microsoft.ServiceFabric.AspNetCore.* NuGet-pakketten bevatten implementaties van ICommunicationListener die start en beheer de ASP.NET Core WebHost 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 andere acties uit die specifiek zijn voor elke webserver.

Beide communicatielisteners bieden een constructor die de volgende argumenten gebruikt:

  • 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. Het is voornamelijk waar de twee communicatielisteners verschillen. HTTP.sys vereist een Endpoint configuratie, terwijl Kestrel dat niet doet.
  • Func<string, AspNetCoreCommunicationListener, IWebHost> build: Dit is een lambda die u implementeert, waarin u een IWebHost. Hiermee kunt u de manier configureren IWebHost waarop u normaal gesproken zou werken 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 waarmee IWebHostBuilder 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 Naming Service. 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 gedeelde hostomgeving, zoals Service Fabric, meerdere webtoepassingen op dezelfde fysieke of virtuele machine kunnen worden uitgevoerd, 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 naar een unieke combinatie van IP:poort. Zodra een servicereplica is begonnen met luisteren op een IP:poorteindpunt, wordt dat eindpuntadres gerapporteerd aan de Service Fabric Naming Service. Daar kunnen clients of andere services deze detecteren. Als services dynamisch toegewezen toepassingspoorten gebruiken, kan een servicereplica mogelijk hetzelfde IP:poorteindpunt van een andere service gebruiken die eerder op dezelfde fysieke of virtuele machine stond. Dit kan ertoe leiden dat een client per ongeluk verbinding maakt met de verkeerde service. Dit scenario kan resulteren als de volgende reeks gebeurtenissen optreedt:

  1. Service A luistert op 10.0.0.1:30000 via HTTP.
  2. De client lost Service A op en haalt adres 10.0.0.1:30000 op.
  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 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 posten naar de Naamgevingsservice met een unieke id en vervolgens die unieke id valideren tijdens clientaanvragen. Dit is een samenwerkingsactie tussen services in een niet-vijandige tenant vertrouwde omgeving. Het biedt geen beveiligde serviceverificatie in een vijandige tenantomgeving.

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 Naming Service. De id wordt gevalideerd voor elke aanvraag. 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 coöperatieve omgeving. Een vaste unieke poort wordt doorgaans gebruikt voor extern gerichte services die een bekende poort nodig hebben om verbinding te maken met clienttoepassingen. 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 kan onderscheiden op basis van unieke URL-paden met behulp van de onderliggende functie voor het delen van poorten HTTP.sys , wordt die functionaliteit niet gebruikt door de HTTP.sys-implementatie ICommunicationListener . Dat komt doordat dit resulteert in HTTP 503- en HTTP 404-foutcodes in het scenario dat eerder is beschreven. Dat 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.

Daarom standaardiseren zowel Kestrel- als HTTP.sys-implementaties ICommunicationListener op middleware die wordt geleverd door de UseServiceFabricIntegration extensiemethode. Clients hoeven daarom alleen een actie voor het opnieuw oplossen 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. HttpSysCommunicationListener hiermee kunt u een ASP.NET Core WebHost binnen een betrouwbare service maken met behulp van HTTP.sys als webserver.

HTTP.sys is gebouwd op de Windows HTTP Server-API. Deze API maakt gebruik van het HTTP.sys kernelstuurprogramma voor het verwerken van HTTP-aanvragen en omleiden naar processen die webtoepassingen uitvoeren. Hierdoor kunnen meerdere processen op dezelfde fysieke of virtuele machine webtoepassingen hosten op dezelfde poort, zonder onderscheid te maken door een uniek URL-pad of 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 staatloze service

Als u een staatloze service wilt gebruiken HttpSys , 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 poorten HTTP.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 reserveren met HTTP.sys (dit wordt normaal gesproken bereikt met het netsh-hulpprogramma ).

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

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

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

</ServiceManifest>

En de eindpuntnaam 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 door een Endpoint configuratie wordt toegewezen, 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 functie voor het delen van poorten HTTP.sys . Maar het wordt niet ondersteund door HttpSysCommunicationListener de complicaties die worden geïntroduceerd 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. KestrelCommunicationListener hiermee kunt u een ASP.NET Core WebHost binnen een betrouwbare service maken met behulp van Kestrel als webserver.

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. Elke instantie van Kestrel moet een unieke poort gebruiken. Zie de implementatiedetails voor meer informatie over Kestrel.

Kestreldiagram

Kestrel in een staatloze service

Als u een staatloze service wilt gebruiken Kestrel , 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 een stateful service wilt gebruiken Kestrel , 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 de container voor afhankelijkheidsinjectie van WebHost opgegeven. Dit is niet strikt noodzakelijk, maar hiermee kunt u betrouwbare verzamelingen gebruiken IReliableStateManager in de actiemethoden van uw MVC-controller.

Er Endpoint wordt geen configuratienaam opgegeven KestrelCommunicationListener in een stateful service. Dit wordt in de volgende sectie uitgebreid beschreven.

Kestrel configureren voor gebruik van HTTPS

Wanneer u HTTPS inschakelt met Kestrel in uw service, moet u verschillende luisteropties instellen. Werk het ServiceInstanceListener bij om een EndpointHttps-eindpunt te gebruiken en luister 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 voor het gebruik van Kestrel.

Kestrel is een eenvoudige zelfstandige webserver. In tegenstelling tot HTTP.sys (of HttpListener) heeft deze geen configuratie in ServiceManifest.xml nodig Endpoint omdat er geen URL-registratie nodig is 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 mogelijke voordelen:

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

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

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

Als ServiceManifest.xml geen configuratie gebruikt Endpoint , laat u de naam in de KestrelCommunicationListener constructor weg. 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 niet gebruiken vanuit de Endpoint configuratie in ServiceManifest.xml. Dat komt doordat automatische poorttoewijzing vanuit een Endpoint configuratie een unieke poort per hostproces toewijst en één hostproces meerdere Kestrel-exemplaren kan bevatten. Dit werkt niet met Kestrel omdat dit geen ondersteuning biedt voor het delen van poorten. Daarom moet elke Kestrel-instantie worden geopend op een unieke poort.

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

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

In deze configuratie KestrelCommunicationListener selecteert u 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 de eindpuntnaam door te geven aan de KestrelCommunicationListener-constructor.

Integratie van IHost en Minimale hosting

Naast IWebHost/IWebHostBuilder KestrelCommunicationListener en HttpSysCommunicationListener 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 en Microsoft.ServiceFabric.AspNetCore.HttpSys pakketten.

// 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

Omdat KestrelCommunicationListener en HttpSysCommunicationListener bedoeld zijn voor webservices, is het vereist om een webserver (met behulp van de methode ConfigureWebHostDefaults of ConfigureWebHost ) te registreren/configureren 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 Service Fabric-configuratie-instellingen, net als andere toepassingsinstellingen. U kunt bijvoorbeeld het optiespatroon 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

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

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

Als u bijvoorbeeld een configuratiepakket hebt met de volgende MyConfigPackage inhoud, is de configuratiewaarde beschikbaar op ASP.NET Core IConfiguration via MyConfigPackage: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 Core IConfiguration . 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 wordt 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 voor het invullen van gegevens van de Service Fabric-configuratie wijzigen in ASP.NET Core-configuratie met behulp van ConfigAction.

In de volgende voorbeelden ziet u hoe ConfigAction u de 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 te 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

In deze sectie vindt u een combinatie van webserver-, poortconfiguratie-, Service Fabric-integratieopties en diverse instellingen die u kunt aanbevelen om problemen met de volgende scenario's op te lossen:

  • Extern weergegeven ASP.NET Stateless Core-services
  • Interne ASP.NET Core stateless services
  • Stateful services met interne ASP.NET Core

Een extern blootgestelde 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 zich niet bewust zijn van Service Fabric-serviceomzetting, zoals Azure Load Balancer, kunnen stateful services niet beschikbaar maken. Dat komt doordat de load balancer geen verkeer kan vinden en routeren naar de juiste stateful servicereplica.

Extern weergegeven ASP.NET Stateless Core-services

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

Wanneer deze beschikbaar wordt gesteld aan internet, moet een stateless service een bekend en stabiel eindpunt gebruiken dat bereikbaar is via een load balancer. U geeft deze URL op voor de gebruikers van uw toepassing. We raden de volgende configuratie aan:

Type Aanbeveling Opmerkingen
Webserver Kestrel 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 geen binnenkomende aanvragen voor een unieke id probeert te valideren. Externe gebruikers van uw toepassing kennen niet de unieke identificatiegegevens die door de middleware worden gebruikt.
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 ontvangen van een load balancer.

Als meerdere extern blootgestelde 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();
})

Interne staatloze ASP.NET Core-service

Staatloze 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 Opmerkingen
Webserver Kestrel Hoewel u HTTP.sys kunt gebruiken voor interne staatloze 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 kunnen een hostproces of hostbesturingssysteem delen en dus unieke poorten nodig hebben.
ServiceFabricIntegrationOptions UseUniqueServiceUrl Met dynamische poorttoewijzing voorkomt deze instelling het foute identiteitsprobleem dat eerder is beschreven.
InstanceCount willekeurige De instelling voor het aantal exemplaren kan worden ingesteld op elke waarde die nodig is om de service te bedienen.

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 Opmerkingen
Webserver Kestrel Het 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 kunnen een hostproces of hostbesturingssysteem delen en dus unieke poorten nodig hebben.
ServiceFabricIntegrationOptions UseUniqueServiceUrl Met dynamische poorttoewijzing voorkomt deze instelling het foute identiteitsprobleem dat eerder is beschreven.

Volgende stappen

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