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

ASP.NET Core je opensourcová architektura pro různé platformy. 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ým průvodcem hostováním ASP.NET Core služeb v Service Fabric Reliable Services pomocí sady balíčků NuGet Microsoft.ServiceFabric.AspNetCore.

Úvodní kurz ASP.NET Core v 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 webového rozhraní API a stavovou back-endovou službou.

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

ASP.NET Core v prostředí Service Fabric

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

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

Zbývající část tohoto článku vysvětluje, jak používat ASP.NET Core ve spolehlivé službě 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 několik instancí 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 hostitelský proces služby a Service Fabric ho aktivuje a monitoruje za vás.

Tradiční ASP.NET (až MVC 5) je úzce svázán 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é hostování webových serverů v místním prostředí. To znamená, že webový server můžete spustit ve vlastním procesu, na rozdíl od procesu, který vlastní vyhrazený software webového serveru, jako je služba IIS.

Pokud chcete kombinovat službu Service Fabric a ASP.NET jako spustitelný soubor hosta nebo spolehlivou službu, musíte být schopni spustit ASP.NET v rámci procesu hostitele služby. ASP.NET Core to umožňuje samoobslužné hostování.

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

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

Hostování ASP.NET Core v procesu

Vstupní bod aplikace ale není správným místem pro vytvoření webhostingu ve spolehlivé službě. Je to proto, že vstupní bod aplikace se používá pouze k registraci typu služby v modulu runtime Service Fabric, aby mohl vytvářet instance tohoto typu služby. WebHost by měl být vytvořen v samotné spolehlivé službě. V rámci procesu hostitele služby můžou instance nebo repliky služby procházet několika životními cykly.

Instance Reliable Service je reprezentována vaší třídou služby odvozenou z StatelessService nebo StatefulService. Komunikační zásobník pro službu je obsažen v implementaci ICommunicationListener ve vaší třídě služby. Balíčky Microsoft.ServiceFabric.AspNetCore.* NuGet obsahují implementaceICommunicationListener, které spouští a spravují webhost ASP.NET Core pro Kestrel nebo HTTP.sys ve spolehlivé službě.

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

ASP.NET Core ICommunicationListeners

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

Oba komunikační naslouchací procesy 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 liší dva naslouchací procesy komunikace. 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 konfigurovat IWebHost obvyklým způsobem v aplikaci ASP.NET Core. Lambda poskytuje adresu URL, která se vygeneruje pro vás v závislosti na možnostech integrace Service Fabric, které používáte, a Endpoint konfiguraci, kterou zadáte. Tuto adresu URL pak můžete upravit nebo použít ke spuštění webového serveru.

Middleware Service Fabric Integration

Balíček Microsoft.ServiceFabric.AspNetCore NuGet obsahuje rozšiřující metodu UseServiceFabricIntegration , IWebHostBuilder která přidává middleware podporující Service Fabric. Tento middleware nakonfiguruje Kestrel nebo HTTP.sys ICommunicationListener pro registraci jedinečné adresy URL služby ve službě Service Fabric Naming Service. Pak ověří požadavky klientů, aby se ujistil, že se klienti připojují ke správné službě.

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

Případ chybné identity

Repliky služeb, bez ohledu na protokol, naslouchají na jedinečné kombinaci IP:port. Jakmile replika služby začne naslouchat na koncovém bodu IP:port, nahlásí adresu daného koncového bodu službě pojmenování Service Fabric. Tam ho můžou zjistit klienti nebo jiné služby. Pokud služby používají dynamicky přiřazené aplikační porty, replika služby může shodou okolností používat 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ě. K tomuto scénáři může dojít, pokud dojde k následující posloupnosti událostí:

  1. Služba A naslouchá přes HTTP na adrese 10.0.0.1:30000.
  2. Klient přeloží službu A a získá adresu 10.0.0.1:30000.
  3. Služba A se přesune do jiného uzlu.
  4. Služba B je umístěna na 10.0.0.1 a shodou okolností používá stejný port 30000.
  5. Klient se pokusí připojit ke službě A s adresou 10.0.0.1:30000 v mezipaměti.
  6. Klient je teď úspěšně připojený ke službě B, ale neuvědomuje si, že je připojený k nesprávné službě.

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

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

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 tento jedinečný identifikátor ověřit během požadavků klientů. Jedná se o akci spolupráce mezi službami v nehostinném prostředí s důvěryhodnými tenanty. Neposkytuje zabezpečené ověřování služby v prostředí nehostinných tenantů.

V důvěryhodném prostředí middleware přidaný metodou UseServiceFabricIntegration automaticky připojí jedinečný identifikátor k adrese odeslané do služby Pojmenování. Ověří tento identifikátor u 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 tento middleware využívat.

U služeb, které používají pevný jedinečný port, k tomuto problému v prostředí spolupráce dochází. Pevný jedinečný port se obvykle používá pro externě přístupné služby, které potřebují dobře známý port pro připojení klientských aplikací. Například většina internetových webových aplikací bude pro připojení webového prohlížeče používat port 80 nebo 443. V takovém případě by jedinečný identifikátor neměl být povolený.

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

Integrace ASP.NET Core Service Fabric

Implementace Kestrel i HTTP.sys ICommunicationListener používají tento mechanismus úplně stejným způsobem. I když HTTP.sys můžou interně rozlišovat požadavky na základě jedinečných cest URL pomocí základní funkce sdílení portůHTTP.sys, implementace HTTP.sys ICommunicationListenertuto funkci nepoužívá. Je to proto, že výsledkem jsou stavové kódy chyb HTTP 503 a HTTP 404 ve scénáři popsaném výše. To pak ztěžuje klientům určení účelu chyby, protože HTTP 503 a HTTP 404 se běžně používají k označení jiných chyb.

To znamená, že implementace Kestrel i HTTP.sys ICommunicationListener standardizují na middlewaru poskytovaném UseServiceFabricIntegration rozšiřující metodou. Klienti proto stačí provést akci opětovného překladu koncového bodu služby u odpovědí HTTP 410.

HTTP.sys v Reliable Services

HTTP.sys v Reliable Services můžete použít importem balíčku NuGet Microsoft.ServiceFabric.AspNetCore.HttpSys . Tento balíček obsahuje HttpSysCommunicationListenerimplementaci .ICommunicationListener HttpSysCommunicationListenerumožň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ům na stejném fyzickém nebo virtuálním počítači hostovat webové aplikace na stejném portu, které jsou nejednoznačné podle jedinečné cesty URL nebo názvu hostitele. Tyto funkce jsou užitečné v Service Fabric k 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ádraHTTP.sys ve Windows ke sdílení portů:

HTTP.sys diagram

HTTP.sys v 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í momentálně navržený pro použití ve stavových službách kvůli komplikacím se základní funkcí HTTP.sys sdílení portů. 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 navrhovaným webovým serverem Kestrel.

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 pomocí HTTP.sys (k tomu obvykle slouží nástroj 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 slouží konkrétně k tomu, aby modul runtime Service Fabric zaregistroval adresu URL u HTTP.sys vaším jménem. Používá k tomu silnou předponu adresy URL se zástupným znakem .

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 se musí předat 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 vyněžte PortEndpoint vlastnost :

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

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

Kestrel v Reliable Services

Kestrel můžete použít v Reliable Services importováním balíčku NuGet Microsoft.ServiceFabric.AspNetCore.Kestrel . Tento balíček obsahuje KestrelCommunicationListenerimplementaci .ICommunicationListener KestrelCommunicationListenerumožň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ého správce koncových bodů. Kestrel také na rozdíl od HTTP.sys nepodporuje sdílení portů mezi několika procesy. Každá instance Kestrel musí používat jedinečný port. Další informace o nástroji Kestrel najdete v podrobnostech o implementaci.

Kestrel diagram

Kestrel v 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 do kontejneru IReliableStateManager injektáže závislostí WebHost poskytována jediná instance . Není to nezbytně nutné, ale umožňuje vám to v metodách akcí kontroleru MVC používat IReliableStateManager spolehlivé kolekce a .

Ve Endpoint stavové službě KestrelCommunicationListenernení k dispozici název konfigurace. Podrobnější vysvětlení najdete v následující části.

Nakonfigurovat Kestrel k používání HTTPS

Při povolování HTTPS s Kestrel ve vaší službě budete muset nastavit několik možností naslouchání. ServiceInstanceListener Aktualizujte tak, aby používal koncový bod EndpointHttps a naslouchal na konkrétním portu (například port 443). Při konfiguraci webového hostitele pro použití webového serveru Kestrel musíte nakonfigurovat Kestrel tak, 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 tomto kurzu najdete v tématu Konfigurace Kestrelu 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í Kestrelu se statickým portem

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

  • Pokud port nespadá do rozsahu portů aplikace, service Fabric ho otevře přes bránu firewall operačního systému.
  • Tento port bude používat adresa URL, kterou jste získali prostřednictvím KestrelCommunicationListener .
  <Resources>
    <Endpoints>
      <Endpoint Protocol="http" Name="ServiceEndpoint" Port="80" />
    </Endpoints>
  </Resources>

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

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

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

Použití Kestrelu s dynamickým portem

Kestrel nemůže použít automatické přiřazení portů 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 hostitelský proces a jeden hostitelský proces může obsahovat více instancí Kestrel. S Kestrelem to nefunguje, 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í portů s nástrojem Kestrel, zcela vynechejte Endpoint konfiguraci v ServiceManifest.xml a nepředávejte konstruktoru název KestrelCommunicationListener koncového bodu následujícím způsobem:

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

V této konfiguraci KestrelCommunicationListener nástroj automaticky vybere nepoužívaný port z rozsahu portů aplikace.

V případě 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.

IHost a minimální integrace hostingu

Kromě IWebHost/IWebHostBuilder KestrelCommunicationListener podporují HttpSysCommunicationListener vytváření ASP.NET Core služeb pomocí IHost/IHostBuilder. To je k dispozici od verze 5.2.1363 Microsoft.ServiceFabric.AspNetCore.Kestrel balíčků a 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();
            }))
    };
}

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 představil model Minimal Hosting, 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 tématu Konfigurace v ASP.NET Core.

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

AddServiceFabricConfiguration – spouštěcí rozšíření

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 zaškrtnutím addServiceFabricConfiguration extensions v oboru názvů proti Microsoft.ServiceFabric.AspNetCore.ConfigurationIConfigurationBuilder.

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

Služba ASP.NET Core teď má přístup k nastavení konfigurace Service Fabric stejně jako jakékoli jiné nastavení aplikace. Vzor možností můžete například použít k načtení nastavení do objektů silného typu.

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í zahrnuje zprostředkovatel konfigurace Service Fabric 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 pro 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

Zprostředkovatel konfigurace Service Fabric také podporuje ServiceFabricConfigurationOptions 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í tak, aby ASP.NET CoreIConfiguration. Místo toho jsou šifrované hodnoty uložené tam. Pokud ale chcete dešifrovat hodnotu, která se má uložit v ASP.NET Core IConfiguration, můžete v AddServiceFabricConfiguration rozšíření nastavit příznak DecryptValue na hodnotu false, a to 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();
}

Více 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 soubor dat

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

Následující příklady ukazují, jak použít ConfigAction k přizpůsobení datového souboru:

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

Zprostředkovatel konfigurace Service Fabric také podporuje aktualizace konfigurace. Pomocí ASP.NET Core IOptionsMonitor můžete dostávat oznámení o změnách a pak znovu načíst IOptionsSnapshot konfigurační data. Další informace najdete v tématu možnosti ASP.NET Core.

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

Scénáře a konfigurace

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

  • Externě vystavené ASP.NET Core bezstavové služby
  • Bezstavové služby pouze interní ASP.NET Core
  • Stavové služby pouze 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í.

Pouze interní služba je ta, jejíž koncový bod je volán pouze z clusteru.

Poznámka

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

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

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 funkci sdílení portů, která umožňuje hostovat více webových služeb na stejné sadě uzlů pomocí stejného portu. V tomto scénáři se webové služby odlišují podle názvu hostitele nebo cesty, aniž by se při poskytování směrování HTTP spoléhaly na front-end proxy server nebo bránu.

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ý přes nástroj pro vyrovnávání zatížení. Tuto adresu URL poskytnete uživatelům vaší aplikace. Doporučujeme následující konfiguraci:

Typ Doporučení Poznámky
Webový server Kestrel Upřednostňovaným webovým serverem je Kestrel, protože je podporovaný ve Windows a Linuxu.
Konfigurace portů static V konfiguraci ServiceManifest.xml by měl být nakonfigurovaný Endpoints dobře známý statický port, například 80 pro HTTP nebo 443 pro HTTPS.
ServiceFabricIntegrationOptions Žádné ServiceFabricIntegrationOptions.None Tuto možnost použijte při konfiguraci middlewaru integrace Service Fabric, aby se služba nepokoušla ověřit příchozí požadavky na 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 hodnotu -1. To se provádí tak, aby instance byla k dispozici 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. Toho můžete dosáhnout úpravou adresy URL zadané při konfiguraci IWebHost. Upozorňujeme, že to platí jenom pro HTTP.sys.

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

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

Pouze interní bezstavová služba ASP.NET Core

Bezstavové služby, které se volají jenom z clusteru, by měly používat jedinečné adresy URL a dynamicky přiřazené porty, aby se zajistila 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, Kestrel je nejlepším serverem, který umožňuje více instancím služby sdílet hostitele.
Konfigurace portů dynamicky přiřazeno Více replik stavové služby může sdílet hostitelský proces nebo hostitelský operační systém, a proto budou potřebovat jedinečné porty.
ServiceFabricIntegrationOptions UseUniqueServiceUrl U dynamického přiřazení portů toto nastavení zabraňuje problému s chybnou identitou, který byl popsán výše.
InstanceCount Libovolný Nastavení počtu instancí je možné nastavit na libovolnou hodnotu potřebnou k provozu služby.

Pouze interní stavová služba 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 Objekt HttpSysCommunicationListener není navržený pro použití stavovým službami, ve kterých repliky sdílejí hostitelský proces.
Konfigurace portů dynamicky přiřazeno Více replik stavové služby může sdílet hostitelský proces nebo hostitelský operační systém, a proto budou potřebovat jedinečné porty.
ServiceFabricIntegrationOptions UseUniqueServiceUrl U dynamického přiřazení portů toto nastavení zabraňuje problému s chybnou identitou, který byl popsán výše.

Další kroky

Ladění aplikace Service Fabric pomocí Visual Studia