ASP.NET Core ve službě Azure Service Fabric Reliable Services

ASP.NET Core je opensourcová a multiplatformní architektura. Tato architektura je navržená pro vytváření cloudových aplikací připojených k internetu, jako jsou webové aplikace, aplikace IoT a mobilní back-endy.

Tento článek je podrobný průvodce hostováním služeb ASP.NET Core v Service Fabric Reliable Services pomocí sady balíčků NuGet microsoft.ServiceFabric.AspNetCore.

Úvodní kurz o ASP.NET Core ve službě Service Fabric a pokyny k nastavení vývojového prostředí najdete v tématu Kurz: Vytvoření a nasazení aplikace s front-endovou službou ASP.NET Core Web API a stavovou back-endovou službou.

Zbytek tohoto článku předpokládá, že už znáte ASP.NET Core. Pokud ne, přečtěte si základní základy ASP.NET.

ASP.NET Core v prostředí Service Fabric

Aplikace ASP.NET Core i Service Fabric se můžou spouštět v .NET Core nebo v plném rozhraní .NET Framework. V Service Fabric můžete použít ASP.NET Core dvěma různými způsoby:

  • Hostovaný jako spustitelný soubor hosta. Tímto způsobem se primárně používá ke spouštění existujících aplikací ASP.NET Core ve službě Service Fabric beze změn kódu.
  • Spusťte ve spolehlivé službě. Díky tomu umožňuje lepší integraci s modulem runtime Service Fabric a umožňuje stavové služby ASP.NET Core.

Zbytek tohoto článku vysvětluje, jak používat ASP.NET Core uvnitř spolehlivé služby prostřednictvím komponent integrace ASP.NET Core, které se dodávají se sadou Service Fabric SDK.

Hostování služby Service Fabric

V Service Fabric se jedna nebo více instancí a/nebo replik vaší služby spouští v hostitelském procesu služby: spustitelný soubor, který spouští kód služby. Jako autor služby vlastníte proces hostitele služby a Service Fabric ho aktivujete a monitorujete za vás.

Tradiční ASP.NET (až MVC 5) je úzce svázané se službou IIS prostřednictvím System.Web.dll. ASP.NET Core poskytuje oddělení mezi webovým serverem a vaší webovou aplikací. Toto oddělení umožňuje přenos webových aplikací mezi různými webovými servery. Umožňuje také místním hostování webových serverů. To znamená, že můžete spustit webový server ve vlastním procesu, a ne proces, který vlastní vyhrazený software webového serveru, jako je služba IIS.

Pokud chcete zkombinovat službu Service Fabric a ASP.NET jako spustitelný soubor hosta nebo ve spolehlivé službě, musíte být schopni spustit ASP.NET uvnitř procesu hostitele služby. ASP.NET core samoobslužné hostování vám to umožní.

Hostování ASP.NET Core ve spolehlivé službě

Obvykle místní aplikace ASP.NET Core vytvářejí webhost v vstupním bodu aplikace, například static void Main() metodu v Program.cs. V tomto případě je životní cyklus webového hostitele vázán na životní cyklus procesu.

Hosting ASP.NET Core in a process

Vstupní bod aplikace ale není správným místem pro vytvoření webového hostitele ve spolehlivé službě. Důvodem je to, že vstupní bod aplikace se používá pouze k registraci typu služby v modulu runtime Service Fabric, aby mohl vytvořit instance tohoto typu služby. WebHost by se měl vytvořit ve spolehlivé službě samotné. V rámci procesu hostitele služby můžou instance služby nebo repliky procházet více životních cyklů.

Instance Reliable Service je reprezentována vaší třídou služby odvozenou z StatelessService nebo StatefulService. Zásobník komunikace pro službu je obsažen v ICommunicationListener implementaci ve vaší třídě služby. Balíčky Microsoft.ServiceFabric.AspNetCore.* NuGet obsahují implementace ICommunicationListener spuštění a správy ASP.NET Core WebHost pro Kestrel nebo HTTP.sys ve spolehlivé službě.

Diagram for hosting ASP.NET Core in a reliable service

ASP.NET Core ICommunicationListeners

Implementace ICommunicationListener pro Kestrel a HTTP.sys v Microsoft.ServiceFabric.AspNetCore.* balíčcích NuGet mají podobné vzory použití. Ale provádějí mírně odlišné akce specifické pro každý webový server.

Oba naslouchací procesy komunikace poskytují konstruktor, který přijímá následující argumenty:

  • ServiceContext serviceContext: Toto je ServiceContext objekt, který obsahuje informace o spuštěné službě.
  • string endpointName: Toto je název Endpoint konfigurace v ServiceManifest.xml. Primárně se tyto dva naslouchací procesy komunikace liší. HTTP.sys vyžadujeEndpoint konfiguraci, zatímco Kestrel ne.
  • Func<string, AspNetCoreCommunicationListener, IWebHost> build: Toto je lambda, kterou implementujete, ve které vytvoříte a vrátíte IWebHost. Umožňuje nakonfigurovat IWebHost způsob, jakým byste normálně v aplikaci ASP.NET Core. Lambda poskytuje adresu URL, která je pro vás vygenerovaná, v závislosti na možnostech integrace Service Fabric, které používáte, a Endpoint konfiguraci, kterou zadáte. Pak můžete tuto adresu URL upravit nebo použít ke spuštění webového serveru.

Middleware integrace Service Fabric

Balíček Microsoft.ServiceFabric.AspNetCore NuGet obsahuje metodu UseServiceFabricIntegrationIWebHostBuilder rozšíření, která přidává middleware podporující Service Fabric. Tento middleware nakonfiguruje Kestrel nebo HTTP.sys ICommunicationListener tak, aby registrovali jedinečnou adresu URL služby ve službě Pojmenování Service Fabric. Pak ověří požadavky klientů, aby se zajistilo, že se klienti připojují ke správné službě.

Tento krok je nezbytný k tomu, aby se klienti omylem připojili k nesprávné službě. Důvodem je to, že v prostředí sdíleného hostitele, jako je Service Fabric, může několik webových aplikací běžet na stejném fyzickém nebo virtuálním počítači, ale nepoužívají jedinečné názvy hostitelů. Tento scénář je podrobněji popsán v další části.

Případ chybné identity

Repliky služeb bez ohledu na protokol naslouchají jedinečné kombinaci IP:port. Jakmile replika služby začne naslouchat na koncovém bodu IP:port, hlásí adresu koncového bodu službě Service Fabric Pojmenování. Klienti nebo jiné služby ho mohou zjistit. Pokud služby používají dynamicky přiřazené aplikační porty, replika služby může shodou okolností použít stejný koncový bod IP:port jiné služby dříve na stejném fyzickém nebo virtuálním počítači. To může způsobit, že se klient omylem připojí k nesprávné službě. Tento scénář může mít za následek následující posloupnost událostí:

  1. Služba A naslouchá 10.0.0.1:30000 přes HTTP.
  2. Klient vyřeší službu A a získá adresu 10.0.0.1:30000.
  3. Služba A se přesune na jiný uzel.
  4. Služba B je umístěna na 10.0.0.1 a shodně používá stejný port 30000.
  5. Klient se pokusí připojit ke službě A s adresou uloženou v mezipaměti 10.0.0.1:30000.
  6. Klient je teď úspěšně připojený ke službě B, a nerealizační, že je připojený k nesprávné službě.

To může způsobit chyby v náhodných časech, které mohou být obtížné diagnostikovat.

Použití jedinečných adres URL služby

Aby se těmto chybám zabránilo, můžou služby publikovat koncový bod do služby pojmenování s jedinečným identifikátorem a pak ověřit jedinečný identifikátor během požadavků klientů. Jedná se o akci spolupráce mezi službami v důvěryhodném prostředí nehostinném tenantovi. Neposkytuje zabezpečené ověřování služeb v nepřátelském prostředí tenanta.

V důvěryhodném prostředí middleware přidaný UseServiceFabricIntegration metodou automaticky připojí jedinečný identifikátor k adrese publikované do služby pojmenování. Ověří identifikátor každého požadavku. Pokud se identifikátor neshoduje, middleware okamžitě vrátí odpověď HTTP 410 Gone.

Služby, které používají dynamicky přiřazený port, by měly používat tento middleware.

Služby, které používají opravený jedinečný port, tento problém nemají v kooperativním prostředí. Pevný jedinečný port se obvykle používá pro externě přístupné služby, které potřebují dobře známý port pro klientské aplikace pro připojení. Například většina internetových webových aplikací bude používat port 80 nebo 443 pro připojení webového prohlížeče. V takovém případě by se jedinečný identifikátor neměl povolit.

Následující diagram znázorňuje tok požadavku s povoleným middlewarem:

Service Fabric ASP.NET Core integration

Implementace Kestrel i HTTP.sys ICommunicationListener tento mechanismus používají stejným způsobem. I když HTTP.sys může interně rozlišovat požadavky na základě jedinečných cest URL pomocí základní funkce sdílení portůHTTP.sys , tato funkce není používána implementací HTTP.sys ICommunicationListener . Důvodem je to, že výsledkem jsou kódy chyb HTTP 503 a HTTP 404 ve scénáři popsaném výše. To zase znesnadňuje klientům určit záměr chyby, protože HTTP 503 a HTTP 404 se běžně používají k označení jiných chyb.

Proto implementace Kestrel i HTTP.sys ICommunicationListener standardizují middleware poskytované metodou UseServiceFabricIntegration rozšíření. Klienti proto potřebují provést akci opětovného překladu koncového bodu služby u odpovědí HTTP 410.

HTTP.sys ve službě Reliable Services

HTTP.sys ve službě Reliable Services můžete použít importem balíčku NuGet Microsoft.ServiceFabric.AspNetCore.HttpSys . Tento balíček obsahuje HttpSysCommunicationListenerimplementaci ICommunicationListener. HttpSysCommunicationListener umožňuje vytvořit ASP.NET Core WebHost uvnitř spolehlivé služby pomocí HTTP.sys jako webového serveru.

HTTP.sys je postaven na rozhraní API systému Windows HTTP Server. Toto rozhraní API používá ovladač jádraHTTP.sys ke zpracování požadavků HTTP a jejich směrování do procesů, které spouští webové aplikace. To umožňuje více procesů na stejném fyzickém nebo virtuálním počítači hostovat webové aplikace na stejném portu, které není nejednoznačné podle jedinečné cesty url nebo názvu hostitele. Tyto funkce jsou užitečné v Service Fabric pro hostování více webů ve stejném clusteru.

Poznámka

HTTP.sys implementace funguje jenom na platformě Windows.

Následující diagram znázorňuje, jak HTTP.sys používá ovladač jádra HTTP.sys ve Windows ke sdílení portů:

HTTP.sys diagram

HTTP.sys ve bezstavové službě

Pokud chcete použít HttpSys v bezstavové službě, přepište metodu CreateServiceInstanceListeners a vraťte HttpSysCommunicationListener instanci:

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 ve stavové službě

HttpSysCommunicationListener není v současné době navržená pro použití ve stavových službách kvůli komplikacím se základní funkcí sdílení portů HTTP.sys . Další informace najdete v následující části věnované dynamickému přidělování portů s HTTP.sys. Pro stavové služby je Kestrel navrhovaný webový server.

Konfigurace koncového bodu

Pro Endpoint webové servery, které používají rozhraní API windows HTTP Serveru, včetně HTTP.sys, se vyžaduje konfigurace. Webové servery, které používají rozhraní API systému Windows HTTP Server, musí nejprve rezervovat adresu URL s HTTP.sys (to se obvykle provádí pomocí nástroje netsh ).

Tato akce vyžaduje zvýšená oprávnění, která vaše služby ve výchozím nastavení nemají. Možnosti "http" nebo "https" pro Protocol vlastnost Endpoint konfigurace v ServiceManifest.xml se používají speciálně k tomu, aby modul runtime Service Fabric zaregistroval adresu URL za HTTP.sys vaším jménem. To provede pomocí silné předpony adresy URL se zástupnými čísly .

Pokud chcete například rezervovat http://+:80 službu, použijte v ServiceManifest.xml následující konfiguraci:

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

</ServiceManifest>

Název koncového bodu musí být předán konstruktoru HttpSysCommunicationListener :

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

Použití HTTP.sys se statickým portem

Pokud chcete použít statický port s HTTP.sys, zadejte číslo portu v Endpoint konfiguraci:

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

Použití HTTP.sys s dynamickým portem

Pokud chcete použít dynamicky přiřazený port s HTTP.sys, v konfiguraci tuto vlastnost Endpoint vynechátePort:

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

Dynamický port přidělený Endpoint konfigurací poskytuje pouze jeden port pro každý hostitelský proces. Aktuální model hostování Service Fabric umožňuje hostování více instancí služby nebo replik ve stejném procesu. To znamená, že každý z nich bude sdílet stejný port při přidělení prostřednictvím Endpoint konfigurace. Několik HTTP.sys instancí může sdílet port pomocí základní funkce sdílení portůHTTP.sys . Není ale podporována HttpSysCommunicationListener kvůli komplikacím, které zavádí pro požadavky klientů. Pro použití dynamického portu je Kestrel navrhovaný webový server.

Kestrel ve službě Reliable Services

Kestrel v Reliable Services můžete použít importem balíčku NuGet Microsoft.ServiceFabric.AspNetCore.Kestrel . Tento balíček obsahuje KestrelCommunicationListenerimplementaci ICommunicationListener. KestrelCommunicationListener umožňuje vytvořit ASP.NET Core WebHost uvnitř spolehlivé služby pomocí Kestrel jako webového serveru.

Kestrel je multiplatformní webový server pro ASP.NET Core. Na rozdíl od HTTP.sys Kestrel nepoužívá centralizovaný správce koncových bodů. Na rozdíl od HTTP.sys také Kestrel nepodporuje sdílení portů mezi více procesy. Každá instance Kestrel musí používat jedinečný port. Další informace o Kestrel naleznete v podrobnostech implementace.

Kestrel diagram

Kestrel ve bezstavové službě

Pokud chcete použít Kestrel v bezstavové službě, přepište metodu CreateServiceInstanceListeners a vraťte KestrelCommunicationListener instanci:

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 ve stavové službě

Pokud chcete použít Kestrel ve stavové službě, přepište metodu CreateServiceReplicaListeners a vraťte KestrelCommunicationListener instanci:

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

V tomto příkladu je k dispozici jedna instance kontejneru IReliableStateManager injektáže závislostí WebHost. To není nezbytně nutné, ale umožňuje používat IReliableStateManager a Spolehlivé kolekce v metodách akcí kontroleru MVC.

Název Endpoint konfigurace není k KestrelCommunicationListener dispozici ve stavové službě. To je podrobněji vysvětleno v následující části.

Nakonfigurovat Kestrel k používání HTTPS

Když ve službě povolíte PROTOKOL HTTPS s Kestrelem, budete muset nastavit několik možností naslouchání. ServiceInstanceListener Aktualizujte koncový bod EndpointHttps a naslouchejte na konkrétním portu (například na portu 443). Při konfiguraci webového hostitele tak, aby používal webový server Kestrel, musíte nakonfigurovat Kestrel, aby naslouchal adresám IPv6 ve všech síťových rozhraních:

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

Úplný příklad v kurzu najdete v tématu Konfigurace Kestrel pro použití PROTOKOLU HTTPS.

Konfigurace koncového bodu

Konfigurace Endpoint není nutná k použití Kestrelu.

Kestrel je jednoduchý samostatný webový server. Na rozdíl od HTTP.sys (nebo HttpListener) nepotřebuje Endpoint konfiguraci v ServiceManifest.xml, protože před spuštěním nevyžaduje registraci adresy URL.

Použití Kestrel se statickým portem

Statický port můžete nakonfigurovat v Endpoint konfiguraci ServiceManifest.xml pro použití s Kestrelem. I když to není nezbytně nutné, nabízí dvě potenciální výhody:

  • Pokud port nespadne do rozsahu portů aplikace, otevře se přes bránu firewall operačního systému service Fabric.
  • Adresa URL zadaná prostřednictvím KestrelCommunicationListener tohoto portu bude používat.
  <Resources>
    <Endpoints>
      <Endpoint Protocol="http" Name="ServiceEndpoint" Port="80" />
    </Endpoints>
  </Resources>

Endpoint Pokud je nakonfigurovaný, musí být jeho název předán do konstruktoruKestrelCommunicationListener:

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

Pokud ServiceManifest.xml nepoužívá Endpoint konfiguraci, vynecháte název v konstruktoru KestrelCommunicationListener . V tomto případě použije dynamický port. Další informace o tom najdete v další části.

Použití Kestrelu s dynamickým portem

Kestrel nemůže použít automatické přiřazení portu z Endpoint konfigurace v ServiceManifest.xml. Je to proto, že automatické přiřazení portů z Endpoint konfigurace přiřadí jedinečný port na proces hostitele a jeden hostitelský proces může obsahovat více instancí Kestrel. To nefunguje s Kestrelem, protože nepodporuje sdílení portů. Proto musí být každá instance Kestrel otevřena na jedinečném portu.

Pokud chcete použít dynamické přiřazení portu s Kestrel, vymiřte Endpoint konfiguraci v ServiceManifest.xml zcela a nepředávejte do konstruktoru název koncového KestrelCommunicationListener bodu následujícím způsobem:

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

V této konfiguraci KestrelCommunicationListener automaticky vybere nevyužitý port z rozsahu portů aplikace.

U protokolu HTTPS by měl mít koncový bod nakonfigurovaný s protokolem HTTPS bez portu zadaného v ServiceManifest.xml a předat název koncového bodu konstruktoru KestrelCommunicationListener.

Integrace hostitele IHost a minimálního hostování

Kromě IWebHost/IWebHostBuilder KestrelCommunicationListener a HttpSysCommunicationListener podpora vytváření služeb ASP.NET Core pomocí IHost/IHostBuilder. To je k dispozici od verze 5.2.1363 Microsoft.ServiceFabric.AspNetCore.Kestrel a Microsoft.ServiceFabric.AspNetCore.HttpSys balíčků.

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

Poznámka

Vzhledem k tomu, že KestrelCommunicationListener a HttpSysCommunicationListener jsou určené pro webové služby, je nutné zaregistrovat nebo nakonfigurovat webový server (pomocí metody ConfigureWebHostDefaults nebo ConfigureWebHost ) přes IHost.

ASP.NET 6 zavedl model minimálního hostování, což je jednodušší a jednodušší způsob vytváření webových aplikací. Minimální model hostování lze také použít s KestrelCommunicationListener a 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;
            }))
    };
}

Poskytovatel konfigurace Service Fabric

Konfigurace aplikace v ASP.NET Core je založená na párech klíč-hodnota vytvořených poskytovatelem konfigurace. Další informace o obecné podpoře konfigurace ASP.NET Core najdete v ASP.NET Core .

Tato část popisuje, jak se poskytovatel konfigurace Service Fabric integruje s konfigurací ASP.NET Core importem Microsoft.ServiceFabric.AspNetCore.Configuration balíčku NuGet.

Rozšíření spuštění AddServiceFabricConfiguration

Po importu Microsoft.ServiceFabric.AspNetCore.Configuration balíčku NuGet je potřeba zaregistrovat zdroj konfigurace Service Fabric v rozhraní API konfigurace ASP.NET Core. Provedete to tak, že zkontrolujete rozšíření AddServiceFabricConfiguration v Microsoft.ServiceFabric.AspNetCore.Configuration oboru názvů proti 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; }

Teď má služba ASP.NET Core přístup k nastavení konfigurace Service Fabric stejně jako jakákoli jiná nastavení aplikace. Pomocí vzoru možností můžete například načíst nastavení do objektů se silnými typy.

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

Výchozí mapování klíčů

Ve výchozím nastavení poskytovatel konfigurace Service Fabric obsahuje název balíčku, název oddílu a název vlastnosti. Společně tvoří konfigurační klíč ASP.NET Core následujícím způsobem:

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

Pokud máte například konfigurační balíček s názvem MyConfigPackage s následujícím obsahem, bude hodnota konfigurace k dispozici na ASP.NET Core IConfiguration prostřednictvím 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>

Možnosti konfigurace Service Fabric

Poskytovatel konfigurace Service Fabric podporuje ServiceFabricConfigurationOptions také změnu výchozího chování mapování klíčů.

Šifrovaná nastavení

Service Fabric podporuje šifrovaná nastavení, stejně jako poskytovatel konfigurace Service Fabric. Šifrovaná nastavení se ve výchozím nastavení nešifrují do ASP.NET Core IConfiguration . Šifrované hodnoty jsou místo toho uloženy. Pokud ale chcete dešifrovat hodnotu pro uložení v ASP.NET Core IConfiguration, můžete v rozšíření nastavit příznak DecryptValue na false AddServiceFabricConfiguration , následujícím způsobem:

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

Několik konfiguračních balíčků

Service Fabric podporuje více konfiguračních balíčků. Ve výchozím nastavení je název balíčku součástí konfiguračního klíče. Příznak ale můžete nastavit IncludePackageName na false následujícím způsobem:

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

Mapování vlastních klíčů, extrakce hodnot a základní soubor dat

Poskytovatel konfigurace Service Fabric také podporuje pokročilejší scénáře pro přizpůsobení mapování ExtractKeyFunc klíčů a vlastní extrakci hodnot pomocí ExtractValueFunc. Můžete dokonce změnit celý proces naplnění dat z konfigurace Service Fabric na ASP.NET Core konfigurace pomocí ConfigAction.

Následující příklady ukazují použití ConfigAction k přizpůsobení základního souboru dat:

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

Aktualizace konfigurace

Poskytovatel konfigurace Service Fabric také podporuje aktualizace konfigurace. Pomocí ASP.NET Core IOptionsMonitor můžete přijímat oznámení o změnách a pak je znovu IOptionsSnapshot načíst. Další informace najdete v tématu ASP.NET Možnosti jádra.

Tyto možnosti jsou ve výchozím nastavení podporovány. K povolení aktualizací konfigurace není potřeba žádné další kódování.

Scénáře a konfigurace

Tato část obsahuje kombinaci webových serverů, konfigurace portů, možností integrace Service Fabric a různých nastavení, která doporučujeme řešit potíže s následujícími scénáři:

  • Externě vystavené ASP.NET bezstavové služby Core
  • Interní ASP.NET bezstavové služby Core
  • Stavové služby jen pro interní ASP.NET Core

Externě vystavená služba je služba, která zveřejňuje koncový bod, který je volán mimo cluster, obvykle prostřednictvím nástroje pro vyrovnávání zatížení.

Interní služba je jedna, jejíž koncový bod se volá pouze z clusteru.

Poznámka

Koncové body stavové služby by obecně neměly být vystaveny internetu. Clustery za nástroji pro vyrovnávání zatížení, které neví o překladu služeb Service Fabric, jako je Azure Load Balancer, nebudou moct zveřejnit stavové služby. Důvodem je to, že nástroj pro vyrovnávání zatížení nebude moct najít a směrovat provoz do příslušné stavové repliky služby.

Externě vystavené ASP.NET bezstavové služby Core

Kestrel je navrhovaný webový server pro front-endové služby, které zpřístupňují externí internetové koncové body HTTP. Ve Windows může HTTP.sys poskytovat možnosti sdílení portů, které umožňují hostovat více webových služeb na stejné sadě uzlů pomocí stejného portu. V tomto scénáři se webové služby rozlišují podle názvu hostitele nebo cesty, aniž by se museli spoléhat na front-endový proxy server nebo bránu k poskytování směrování HTTP.

Když je služba vystavená internetu, měla by bezstavová služba používat dobře známý a stabilní koncový bod, který je dostupný prostřednictvím nástroje pro vyrovnávání zatížení. Tuto adresu URL zadáte uživatelům aplikace. Doporučujeme následující konfiguraci:

Typ Doporučení Poznámky
Webový server Kestrel Kestrel je upřednostňovaným webovým serverem, protože je podporovaný v systémech Windows a Linux.
Konfigurace portů static Dobře známý statický port by měl být nakonfigurován v Endpoints konfiguraci ServiceManifest.xml, například 80 pro HTTP nebo 443 pro HTTPS.
ServiceFabricIntegrationOptions Žádné Tuto možnost použijte při konfiguraci middlewaru ServiceFabricIntegrationOptions.None integrace Service Fabric, aby se služba nepokoušla ověřit příchozí požadavky pro jedinečný identifikátor. Externí uživatelé vaší aplikace nebudou znát jedinečné identifikační informace, které middleware používá.
Počet instancí -1 V typických případech použití by mělo být nastavení počtu instancí nastaveno na -1. To se provádí tak, aby byla instance dostupná na všech uzlech, které přijímají provoz z nástroje pro vyrovnávání zatížení.

Pokud více externě vystavených služeb sdílí stejnou sadu uzlů, můžete použít HTTP.sys s jedinečnou, ale stabilní cestou url. Můžete to provést úpravou adresy URL, kterou jste zadali při konfiguraci IWebHost. Upozorňujeme, že se to týká jenom HTTP.sys.

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

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

Bezstavová služba ASP.NET Core jen pro interní počítače

Bezstavové služby, které se volají jenom z clusteru, by měly používat jedinečné adresy URL a dynamicky přiřazené porty k zajištění spolupráce mezi více službami. Doporučujeme následující konfiguraci:

Typ Doporučení Poznámky
Webový server Kestrel I když můžete použít HTTP.sys pro interní bezstavové služby, je Kestrel nejlepším serverem, který umožňuje více instancím služby sdílet hostitele.
Konfigurace portů dynamicky přiřazené Více replik stavové služby může sdílet hostitelský proces nebo hostitelský operační systém, a proto bude potřebovat jedinečné porty.
ServiceFabricIntegrationOptions UseUniqueServiceUrl Při přiřazení dynamického portu toto nastavení brání problému s chybnou identitou popsanou výše.
InstanceCount Libovolný Nastavení počtu instancí lze nastavit na libovolnou hodnotu potřebnou pro provoz služby.

Stavová služba jen pro interní ASP.NET Core

Stavové služby, které se volají jenom z clusteru, by měly používat dynamicky přiřazené porty k zajištění spolupráce mezi více službami. Doporučujeme následující konfiguraci:

Typ Doporučení Poznámky
Webový server Kestrel Není HttpSysCommunicationListener určena pro použití stavovými službami, ve kterých repliky sdílejí proces hostitele.
Konfigurace portů dynamicky přiřazené Více replik stavové služby může sdílet hostitelský proces nebo hostitelský operační systém, a proto bude potřebovat jedinečné porty.
ServiceFabricIntegrationOptions UseUniqueServiceUrl Při přiřazení dynamického portu toto nastavení brání problému s chybnou identitou popsanou výše.

Další kroky

Ladění aplikace Service Fabric pomocí Visual Studia