ASP.NET Core i Azure Service Fabric Reliable Services
ASP.NET Core är ett ramverk med öppen källkod och plattformsoberoende. Det här ramverket är utformat för att skapa molnbaserade, Internetanslutna program, till exempel webbappar, IoT-appar och mobila serverdelar.
Den här artikeln är en djupgående guide för att vara värd för ASP.NET Core-tjänster i Service Fabric Reliable Services med hjälp av uppsättningen Microsoft.ServiceFabric.AspNetCore. med NuGet-paket.
En introduktionskurs om ASP.NET Core i Service Fabric och instruktioner för hur du konfigurerar utvecklingsmiljön finns i Självstudie: Skapa och distribuera ett program med en klientdelstjänst för ASP.NET Core Web API och en tillståndskänslig serverdelstjänst.
Resten av den här artikeln förutsätter att du redan är bekant med ASP.NET Core. Om inte kan du läsa igenom grunderna i ASP.NET Core.
ASP.NET Core i Service Fabric-miljön
Både ASP.NET Core- och Service Fabric-appar kan köras på .NET Core eller fullständigt .NET Framework. Du kan använda ASP.NET Core på två olika sätt i Service Fabric:
- Körs som körbar gäst. Det här sättet används främst för att köra befintliga ASP.NET Core-program på Service Fabric utan kodändringar.
- Kör i en tillförlitlig tjänst. På så sätt kan du bättre integrera med Service Fabric-körningen och tillåta tillståndskänsliga ASP.NET Core-tjänster.
Resten av den här artikeln förklarar hur du använder ASP.NET Core i en tillförlitlig tjänst, via ASP.NET Core-integreringskomponenter som levereras med Service Fabric SDK.
Service Fabric-tjänstvärd
I Service Fabric körs en eller flera instanser och/eller repliker av tjänsten i en tjänstvärdprocess: en körbar fil som kör tjänstkoden. Som tjänstförfattare äger du tjänstvärdprocessen och Service Fabric aktiverar och övervakar den åt dig.
Traditionella ASP.NET (upp till MVC 5) är tätt kopplade till IIS genom System.Web.dll. ASP.NET Core ger en separation mellan webbservern och webbappen. Den här separationen gör att webbprogram kan vara portabla mellan olika webbservrar. Det gör också att webbservrar kan vara lokalt installerade. Det innebär att du kan starta en webbserver i din egen process, till skillnad från en process som ägs av dedikerad webbserverprogramvara, till exempel IIS.
Om du vill kombinera en Service Fabric-tjänst och ASP.NET, antingen som körbar gäst eller i en tillförlitlig tjänst, måste du kunna starta ASP.NET i tjänstvärdprocessen. ASP.NET Core självvärd kan du göra detta.
Värd för ASP.NET Core i en tillförlitlig tjänst
Vanligtvis skapar lokalt installerade ASP.NET Core-program en WebHost i ett programs startpunkt, till exempel static void Main()
metoden i Program.cs
. I det här fallet är livscykeln för WebHost bunden till processens livscykel.
Men programmets startpunkt är inte rätt plats för att skapa en WebHost i en tillförlitlig tjänst. Det beror på att programmets startpunkt endast används för att registrera en tjänsttyp med Service Fabric-körningen, så att den kan skapa instanser av den tjänsttypen. WebHost ska skapas i en tillförlitlig tjänst. I tjänstvärdprocessen kan tjänstinstanser och/eller repliker genomgå flera livscykelr.
En Reliable Service-instans representeras av din tjänstklass som härleds från StatelessService
eller StatefulService
. Kommunikationsstacken för en tjänst finns i en ICommunicationListener
implementering i din tjänstklass. NuGet-paketen Microsoft.ServiceFabric.AspNetCore.*
innehåller implementeringar av ICommunicationListener
som startar och hanterar ASP.NET Core WebHost för antingen Kestrel eller HTTP.sys i en tillförlitlig tjänst.
ASP.NET Core ICommunicationListeners
Implementeringarna ICommunicationListener
för Kestrel och HTTP.sys i NuGet-paketen Microsoft.ServiceFabric.AspNetCore.*
har liknande användningsmönster. Men de utför lite olika åtgärder som är specifika för varje webbserver.
Båda kommunikationslyssnare tillhandahåller en konstruktor som använder följande argument:
ServiceContext serviceContext
: Det här är objektetServiceContext
som innehåller information om den tjänst som körs.string endpointName
: Det här är namnet på enEndpoint
konfiguration i ServiceManifest.xml. Det är främst där de två kommunikationslyssnarna skiljer sig åt. HTTP.sys kräver enEndpoint
konfiguration, medan Kestrel inte gör det.Func<string, AspNetCoreCommunicationListener, IWebHost> build
: Det här är en lambda som du implementerar, där du skapar och returnerar enIWebHost
. Det gör att du kan konfigureraIWebHost
det sätt som du normalt skulle göra i ett ASP.NET Core-program. Lambda innehåller en URL som genereras åt dig, beroende på vilka Service Fabric-integreringsalternativ du använder och denEndpoint
konfiguration du anger. Du kan sedan ändra eller använda webbadressen för att starta webbservern.
Mellanprogram för Service Fabric-integrering
Microsoft.ServiceFabric.AspNetCore
NuGet-paketet innehåller UseServiceFabricIntegration
tilläggsmetoden på IWebHostBuilder
som lägger till Service Fabric-medvetna mellanprogram. Det här mellanprogrammet konfigurerar Kestrel eller HTTP.sys ICommunicationListener
för att registrera en unik tjänst-URL med Service Fabric Naming Service. Sedan valideras klientbegäranden för att säkerställa att klienter ansluter till rätt tjänst.
Det här steget är nödvändigt för att förhindra att klienter felaktigt ansluter till fel tjänst. Det beror på att i en miljö med delad värd, till exempel Service Fabric, kan flera webbprogram köras på samma fysiska eller virtuella dator men inte använda unika värdnamn. Det här scenariot beskrivs mer detaljerat i nästa avsnitt.
Ett fall av felaktig identitet
Tjänstrepliker, oavsett protokoll, lyssnar på en unik IP:portkombination. När en tjänstreplik har börjat lyssna på en IP:portslutpunkt rapporterar den slutpunktsadressen till Service Fabric Naming Service. Där kan klienter eller andra tjänster identifiera det. Om tjänster använder dynamiskt tilldelade programportar kan en tjänstreplik av en tillfällighet använda samma IP:portslutpunkt för en annan tjänst tidigare på samma fysiska eller virtuella dator. Detta kan leda till att en klient felaktigt ansluter till fel tjänst. Det här scenariot kan uppstå om följande sekvens av händelser inträffar:
- Service A lyssnar på 10.0.0.1:30000 via HTTP.
- Klienten löser service A och hämtar adressen 10.0.0.1:30000.
- Tjänst A flyttas till en annan nod.
- Service B är placerad på 10.0.0.1 och använder av en tillfällighet samma port 30000.
- Klienten försöker ansluta till tjänst A med cachelagrad adress 10.0.0.1:30000.
- Klienten är nu ansluten till tjänst B, utan att inse att den är ansluten till fel tjänst.
Detta kan orsaka buggar vid slumpmässiga tidpunkter som kan vara svåra att diagnostisera.
Använda unika tjänst-URL:er
För att förhindra dessa buggar kan tjänster publicera en slutpunkt till namngivningstjänsten med en unik identifierare och sedan verifiera den unika identifieraren under klientbegäranden. Det här är en samarbetsåtgärd mellan tjänster i en icke-fientlig klientorganisations betrodd miljö. Den tillhandahåller inte säker tjänstautentisering i en miljö med fientlig klientorganisation.
I en betrodd miljö lägger mellanprogrammet som läggs till av UseServiceFabricIntegration
metoden automatiskt till en unik identifierare till den adress som publiceras i namngivningstjänsten. Den verifierar identifieraren för varje begäran. Om identifieraren inte matchar returnerar mellanprogrammet omedelbart ett HTTP 410 Gone-svar.
Tjänster som använder en dynamiskt tilldelad port bör använda det här mellanprogrammet.
Tjänster som använder en fast unik port har inte det här problemet i en samarbetsmiljö. En fast unik port används vanligtvis för externt riktade tjänster som behöver en välkänd port för klientprogram att ansluta till. De flesta internetuppkopplade webbprogram använder till exempel port 80 eller 443 för webbläsaranslutningar. I det här fallet ska den unika identifieraren inte vara aktiverad.
Följande diagram visar begärandeflödet med mellanprogrammet aktiverat:
Både Kestrel och HTTP.sys ICommunicationListener
implementeringar använder den här mekanismen på exakt samma sätt. Även om HTTP.sys internt kan skilja begäranden baserat på unika URL-sökvägar med hjälp av den underliggande HTTP.sys portdelningsfunktionen, används inte den funktionen av HTTP.sys ICommunicationListener
implementeringen. Det beror på att det resulterar i HTTP 503- och HTTP 404-felstatuskoder i scenariot som beskrevs tidigare. Det gör det i sin tur svårt för klienter att fastställa avsikten med felet, eftersom HTTP 503 och HTTP 404 ofta används för att indikera andra fel.
Därför standardiseras både Kestrel- och HTTP.sys-implementeringar ICommunicationListener
på mellanprogram som tillhandahålls av UseServiceFabricIntegration
tilläggsmetoden. Därför behöver klienter bara utföra en åtgärd för att matcha om en tjänstslutpunkt på HTTP 410-svar.
HTTP.sys i Reliable Services
Du kan använda HTTP.sys i Reliable Services genom att importera NuGet-paketet Microsoft.ServiceFabric.AspNetCore.HttpSys . Det här paketet innehåller HttpSysCommunicationListener
, en implementering av ICommunicationListener
. HttpSysCommunicationListener
gör att du kan skapa en ASP.NET Core WebHost i en tillförlitlig tjänst med hjälp av HTTP.sys som webbserver.
HTTP.sys bygger på Windows HTTP Server API. Det här API:et använder HTTP.sys kerneldrivrutin för att bearbeta HTTP-begäranden och dirigera dem till processer som kör webbprogram. Detta gör att flera processer på samma fysiska eller virtuella dator kan vara värdar för webbprogram på samma port, vilket är tvetydigt med antingen en unik URL-sökväg eller ett värdnamn. Dessa funktioner är användbara i Service Fabric för att vara värd för flera webbplatser i samma kluster.
Kommentar
HTTP.sys-implementeringen fungerar bara på Windows-plattformen.
Följande diagram visar hur HTTP.sys använder HTTP.sys kerneldrivrutin i Windows för portdelning:
HTTP.sys i en tillståndslös tjänst
Om du vill använda HttpSys
i en tillståndslös tjänst åsidosätter du CreateServiceInstanceListeners
metoden och returnerar en HttpSysCommunicationListener
instans:
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new ServiceInstanceListener[]
{
new ServiceInstanceListener(serviceContext =>
new HttpSysCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
new WebHostBuilder()
.UseHttpSys()
.ConfigureServices(
services => services
.AddSingleton<StatelessServiceContext>(serviceContext))
.UseContentRoot(Directory.GetCurrentDirectory())
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
.UseStartup<Startup>()
.UseUrls(url)
.Build()))
};
}
HTTP.sys i en tillståndskänslig tjänst
HttpSysCommunicationListener
är för närvarande inte utformat för användning i tillståndskänsliga tjänster på grund av komplikationer med den underliggande HTTP.sys portdelningsfunktionen. Mer information finns i följande avsnitt om dynamisk portallokering med HTTP.sys. För tillståndskänsliga tjänster är Kestrel den föreslagna webbservern.
Slutpunktskonfiguration
En Endpoint
konfiguration krävs för webbservrar som använder Windows HTTP Server API, inklusive HTTP.sys. Webbservrar som använder Windows HTTP Server API måste först reservera sin URL med HTTP.sys (detta utförs normalt med netsh-verktyget ).
Den här åtgärden kräver utökade privilegier som dina tjänster inte har som standard. Alternativen "http" eller "https" för egenskapen för Protocol
konfigurationen Endpoint
i ServiceManifest.xml används specifikt för att instruera Service Fabric-körningen att registrera en URL med HTTP.sys åt dig. Det gör den med hjälp av det starka url-prefixet för jokertecken .
Om du till exempel vill reservera http://+:80
för en tjänst använder du följande konfiguration i ServiceManifest.xml:
<ServiceManifest ... >
...
<Resources>
<Endpoints>
<Endpoint Name="ServiceEndpoint" Protocol="http" Port="80" />
</Endpoints>
</Resources>
</ServiceManifest>
Och slutpunktsnamnet måste skickas till HttpSysCommunicationListener
konstruktorn:
new HttpSysCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
{
return new WebHostBuilder()
.UseHttpSys()
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
.UseUrls(url)
.Build();
})
Använda HTTP.sys med en statisk port
Om du vill använda en statisk port med HTTP.sys anger du portnumret i konfigurationen Endpoint
:
<Resources>
<Endpoints>
<Endpoint Protocol="http" Name="ServiceEndpoint" Port="80" />
</Endpoints>
</Resources>
Använda HTTP.sys med en dynamisk port
Om du vill använda en dynamiskt tilldelad port med HTTP.sys utelämnar Port
du egenskapen i konfigurationen Endpoint
:
<Resources>
<Endpoints>
<Endpoint Protocol="http" Name="ServiceEndpoint" />
</Endpoints>
</Resources>
En dynamisk port som allokeras av en Endpoint
konfiguration ger endast en port per värdprocess. Den aktuella Service Fabric-värdmodellen gör att flera tjänstinstanser och/eller repliker kan hanteras i samma process. Det innebär att var och en delar samma port när den allokeras via konfigurationen Endpoint
. Flera HTTP.sys instanser kan dela en port med hjälp av den underliggande HTTP.sys portdelningsfunktionen. Men det stöds inte av på grund av HttpSysCommunicationListener
de komplikationer som den introducerar för klientbegäranden. För dynamisk portanvändning är Kestrel den föreslagna webbservern.
Kestrel i Reliable Services
Du kan använda Kestrel i Reliable Services genom att importera NuGet-paketet Microsoft.ServiceFabric.AspNetCore.Kestrel . Det här paketet innehåller KestrelCommunicationListener
, en implementering av ICommunicationListener
. KestrelCommunicationListener
gör att du kan skapa en ASP.NET Core WebHost i en tillförlitlig tjänst med hjälp av Kestrel som webbserver.
Kestrel är en plattformsoberoende webbserver för ASP.NET Core. Till skillnad från HTTP.sys använder Kestrel inte en centraliserad slutpunktshanterare. Till skillnad från HTTP.sys stöder Kestrel inte portdelning mellan flera processer. Varje instans av Kestrel måste använda en unik port. Mer information om Kestrel finns i Implementeringsinformation.
Kestrel i en tillståndslös tjänst
Om du vill använda Kestrel
i en tillståndslös tjänst åsidosätter du CreateServiceInstanceListeners
metoden och returnerar en KestrelCommunicationListener
instans:
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new ServiceInstanceListener[]
{
new ServiceInstanceListener(serviceContext =>
new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
new WebHostBuilder()
.UseKestrel()
.ConfigureServices(
services => services
.AddSingleton<StatelessServiceContext>(serviceContext))
.UseContentRoot(Directory.GetCurrentDirectory())
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.UseUniqueServiceUrl)
.UseStartup<Startup>()
.UseUrls(url)
.Build();
))
};
}
Kestrel i en tillståndskänslig tjänst
Om du vill använda Kestrel
i en tillståndskänslig tjänst åsidosätter du CreateServiceReplicaListeners
metoden och returnerar en KestrelCommunicationListener
instans:
protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
{
return new ServiceReplicaListener[]
{
new ServiceReplicaListener(serviceContext =>
new KestrelCommunicationListener(serviceContext, (url, listener) =>
new WebHostBuilder()
.UseKestrel()
.ConfigureServices(
services => services
.AddSingleton<StatefulServiceContext>(serviceContext)
.AddSingleton<IReliableStateManager>(this.StateManager))
.UseContentRoot(Directory.GetCurrentDirectory())
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.UseUniqueServiceUrl)
.UseStartup<Startup>()
.UseUrls(url)
.Build();
))
};
}
I det här exemplet tillhandahålls en singleton-instans av IReliableStateManager
till containern webhost-beroendeinmatning. Detta är inte absolut nödvändigt, men det gör att du kan använda IReliableStateManager
och tillförlitliga samlingar i dina MVC-kontrollantåtgärder.
Ett Endpoint
konfigurationsnamn anges inte i KestrelCommunicationListener
en tillståndskänslig tjänst. Detta förklaras mer detaljerat i följande avsnitt.
Konfigurera Kestrel för användning av HTTPS
När du aktiverar HTTPS med Kestrel i din tjänst måste du ange flera lyssningsalternativ. ServiceInstanceListener
Uppdatera för att använda en EndpointHttps-slutpunkt och lyssna på en specifik port (till exempel port 443). När du konfigurerar webbvärden för att använda Kestrel-webbservern måste du konfigurera Kestrel att lyssna efter IPv6-adresser i alla nätverksgränssnitt:
new ServiceInstanceListener(
serviceContext =>
new KestrelCommunicationListener(
serviceContext,
"EndpointHttps",
(url, listener) =>
{
ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting Kestrel on {url}");
return new WebHostBuilder()
.UseKestrel(opt =>
{
int port = serviceContext.CodePackageActivationContext.GetEndpoint("EndpointHttps").Port;
opt.Listen(IPAddress.IPv6Any, port, listenOptions =>
{
listenOptions.UseHttps(GetCertificateFromStore());
listenOptions.NoDelay = true;
});
})
.ConfigureAppConfiguration((builderContext, config) =>
{
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
})
.ConfigureServices(
services => services
.AddSingleton<HttpClient>(new HttpClient())
.AddSingleton<FabricClient>(new FabricClient())
.AddSingleton<StatelessServiceContext>(serviceContext))
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>()
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
.UseUrls(url)
.Build();
}))
Ett fullständigt exempel i en självstudiekurs finns i Konfigurera Kestrel att använda HTTPS.
Slutpunktskonfiguration
En Endpoint
konfiguration krävs inte för att använda Kestrel.
Kestrel är en enkel fristående webbserver. Till skillnad från HTTP.sys (eller HttpListener) behöver den inte någon Endpoint
konfiguration i ServiceManifest.xml eftersom den inte kräver URL-registrering innan du startar.
Använda Kestrel med en statisk port
Du kan konfigurera en statisk port i konfigurationen Endpoint
av ServiceManifest.xml för användning med Kestrel. Även om detta inte är absolut nödvändigt erbjuder det två potentiella fördelar:
- Om porten inte hamnar i programmets portintervall öppnas den via operativsystemets brandvägg av Service Fabric.
- Den URL som du får via
KestrelCommunicationListener
använder den här porten.
<Resources>
<Endpoints>
<Endpoint Protocol="http" Name="ServiceEndpoint" Port="80" />
</Endpoints>
</Resources>
Om en Endpoint
har konfigurerats måste dess namn skickas till KestrelCommunicationListener
konstruktorn:
new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) => ...
Om ServiceManifest.xml inte använder någon Endpoint
konfiguration utelämnar du namnet i KestrelCommunicationListener
konstruktorn. I det här fallet använder den en dynamisk port. Mer information om detta finns i nästa avsnitt.
Använda Kestrel med en dynamisk port
Kestrel kan inte använda den automatiska porttilldelningen från konfigurationen Endpoint
i ServiceManifest.xml. Det beror på att automatisk porttilldelning från en Endpoint
konfiguration tilldelar en unik port per värdprocess, och en enda värdprocess kan innehålla flera Kestrel-instanser. Detta fungerar inte med Kestrel eftersom det inte stöder portdelning. Därför måste varje Kestrel-instans öppnas på en unik port.
Om du vill använda dynamisk porttilldelning med Kestrel utelämnar du konfigurationen Endpoint
i ServiceManifest.xml helt och skickar inte ett slutpunktsnamn till KestrelCommunicationListener
konstruktorn på följande sätt:
new KestrelCommunicationListener(serviceContext, (url, listener) => ...
I den här konfigurationen KestrelCommunicationListener
väljer du automatiskt en port som inte används från programmets portintervall.
För HTTPS bör slutpunkten konfigureras med HTTPS-protokollet utan en port som anges i ServiceManifest.xml och skicka slutpunktsnamnet till konstruktorn KestrelCommunicationListener.
IHost och minimal värdintegrering
Förutom IWebHost/IWebHostBuilder KestrelCommunicationListener
och HttpSysCommunicationListener
stöd för att skapa ASP.NET Core-tjänster med hjälp av IHost/IHostBuilder.
Detta är tillgängligt från och med v5.2.1363 av Microsoft.ServiceFabric.AspNetCore.Kestrel
och Microsoft.ServiceFabric.AspNetCore.HttpSys
paket.
// Stateless Service
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new ServiceInstanceListener[]
{
new ServiceInstanceListener(serviceContext =>
new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
{
return Host.CreateDefaultBuilder()
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseKestrel()
.UseStartup<Startup>()
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
.UseContentRoot(Directory.GetCurrentDirectory())
.UseUrls(url);
})
.ConfigureServices(services => services.AddSingleton<StatelessServiceContext>(serviceContext))
.Build();
}))
};
}
// Stateful Service
protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
{
return new ServiceReplicaListener[]
{
new ServiceReplicaListener(serviceContext =>
new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
{
return Host.CreateDefaultBuilder()
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseKestrel()
.UseStartup<Startup>()
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.UseUniqueServiceUrl)
.UseContentRoot(Directory.GetCurrentDirectory())
.UseUrls(url);
})
.ConfigureServices(services =>
{
services.AddSingleton<StatefulServiceContext>(serviceContext);
services.AddSingleton<IReliableStateManager>(this.StateManager);
})
.Build();
}))
};
}
Kommentar
Eftersom KestrelCommunicationListener och HttpSysCommunicationListener är avsedda för webbtjänster måste du registrera/konfigurera en webbserver (med metoden ConfigureWebHostDefaults eller ConfigureWebHost ) via IHost
ASP.NET 6 introducerade modellen Minimal Hosting som är ett mer förenklat och effektiviserat sätt att skapa webbprogram. Minimal värdmodell kan också användas med KestrelCommunicationListener och HttpSysCommunicationListener.
// Stateless Service
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new ServiceInstanceListener[]
{
new ServiceInstanceListener(serviceContext =>
new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
{
var builder = WebApplication.CreateBuilder();
builder.Services.AddSingleton<StatelessServiceContext>(serviceContext);
builder.WebHost
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
.UseUrls(url);
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
return app;
}))
};
}
// Stateful Service
protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
{
return new ServiceReplicaListener[]
{
new ServiceReplicaListener(serviceContext =>
new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
{
var builder = WebApplication.CreateBuilder();
builder.Services
.AddSingleton<StatefulServiceContext>(serviceContext)
.AddSingleton<IReliableStateManager>(this.StateManager);
builder.WebHost
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.UseUniqueServiceUrl)
.UseUrls(url);
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
return app;
}))
};
}
Service Fabric-konfigurationsprovider
Appkonfigurationen i ASP.NET Core baseras på nyckel/värde-par som upprättats av konfigurationsprovidern. Läs Konfiguration i ASP.NET Core om du vill veta mer om allmän ASP.NET Core-konfigurationsstöd.
I det här avsnittet beskrivs hur Service Fabric-konfigurationsprovidern integreras med ASP.NET Core-konfiguration genom att importera NuGet-paketet Microsoft.ServiceFabric.AspNetCore.Configuration
.
Starttillägg för AddServiceFabricConfiguration
När du har importerat Microsoft.ServiceFabric.AspNetCore.Configuration
NuGet-paketet måste du registrera Service Fabric-konfigurationskällan med ASP.NET Core-konfigurations-API. Det gör du genom att kontrollera Tillägg för Microsoft.ServiceFabric.AspNetCore.Configuration
AddServiceFabricConfiguration i namnområdet mot IConfigurationBuilder
.
using Microsoft.ServiceFabric.AspNetCore.Configuration;
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddServiceFabricConfiguration() // Add Service Fabric configuration settings.
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; }
Nu kan ASP.NET Core-tjänsten komma åt Service Fabric-konfigurationsinställningarna, precis som andra programinställningar. Du kan till exempel använda alternativmönstret för att läsa in inställningar i starkt skrivna objekt.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<MyOptions>(Configuration); // Strongly typed configuration object.
services.AddMvc();
}
Standardnyckelmappning
Som standard innehåller Service Fabric-konfigurationsprovidern paketnamnet, avsnittsnamnet och egenskapsnamnet. Tillsammans utgör dessa konfigurationsnyckeln ASP.NET Core enligt följande:
$"{this.PackageName}{ConfigurationPath.KeyDelimiter}{section.Name}{ConfigurationPath.KeyDelimiter}{property.Name}"
Om du till exempel har ett konfigurationspaket med namnet MyConfigPackage
med följande innehåll blir konfigurationsvärdet tillgängligt på ASP.NET Core IConfiguration
via MyConfigPackage:MyConfigSection:MyParameter.
<?xml version="1.0" encoding="utf-8" ?>
<Settings xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/2011/01/fabric">
<Section Name="MyConfigSection">
<Parameter Name="MyParameter" Value="Value1" />
</Section>
</Settings>
Konfigurationsalternativ för Service Fabric
Service Fabric-konfigurationsprovidern har också stöd ServiceFabricConfigurationOptions
för att ändra standardbeteendet för nyckelmappning.
Krypterade inställningar
Service Fabric stöder krypterade inställningar, liksom Service Fabric-konfigurationsprovidern. De krypterade inställningarna dekrypteras inte till ASP.NET Core IConfiguration
som standard. De krypterade värdena lagras där i stället. Men om du vill dekryptera värdet som ska lagras i ASP.NET Core IConfiguration kan du ange flaggan DecryptValue till false i AddServiceFabricConfiguration
tillägget enligt följande:
public Startup()
{
ICodePackageActivationContext activationContext = FabricRuntime.GetActivationContext();
var builder = new ConfigurationBuilder()
.AddServiceFabricConfiguration(activationContext, (options) => options.DecryptValue = false); // set flag to decrypt the value
Configuration = builder.Build();
}
Flera konfigurationspaket
Service Fabric stöder flera konfigurationspaket. Som standard ingår paketnamnet i konfigurationsnyckeln. Men du kan ställa in flaggan på IncludePackageName
false enligt följande:
public Startup()
{
ICodePackageActivationContext activationContext = FabricRuntime.GetActivationContext();
var builder = new ConfigurationBuilder()
// exclude package name from key.
.AddServiceFabricConfiguration(activationContext, (options) => options.IncludePackageName = false);
Configuration = builder.Build();
}
Anpassad nyckelmappning, värdeextrahering och datapopulation
Service Fabric-konfigurationsprovidern har också stöd för mer avancerade scenarier för att anpassa nyckelmappningen med ExtractKeyFunc
och extrahera värdena med ExtractValueFunc
. Du kan till och med ändra hela processen för att fylla i data från Service Fabric-konfigurationen till ASP.NET Core-konfiguration med hjälp ConfigAction
av .
Följande exempel visar hur du använder ConfigAction
för att anpassa datapopulationen:
public Startup()
{
ICodePackageActivationContext activationContext = FabricRuntime.GetActivationContext();
this.valueCount = 0;
this.sectionCount = 0;
var builder = new ConfigurationBuilder();
builder.AddServiceFabricConfiguration(activationContext, (options) =>
{
options.ConfigAction = (package, configData) =>
{
ILogger logger = new ConsoleLogger("Test", null, false);
logger.LogInformation($"Config Update for package {package.Path} started");
foreach (var section in package.Settings.Sections)
{
this.sectionCount++;
foreach (var param in section.Parameters)
{
configData[options.ExtractKeyFunc(section, param)] = options.ExtractValueFunc(section, param);
this.valueCount++;
}
}
logger.LogInformation($"Config Update for package {package.Path} finished");
};
});
Configuration = builder.Build();
}
Konfigurationsuppdateringar
Service Fabric-konfigurationsprovidern stöder även konfigurationsuppdateringar. Du kan använda ASP.NET Core IOptionsMonitor
för att ta emot ändringsmeddelanden och sedan använda IOptionsSnapshot
för att läsa in konfigurationsdata igen. Mer information finns i ASP.NET Core-alternativ.
De här alternativen stöds som standard. Ingen ytterligare kodning krävs för att aktivera konfigurationsuppdateringar.
Scenarier och konfigurationer
Det här avsnittet innehåller kombinationen av webbserver, portkonfiguration, Service Fabric-integreringsalternativ och diverse inställningar som vi rekommenderar för att felsöka följande scenarier:
- Externt exponerade ASP.NET Tillståndslösa kärntjänster
- Tillståndslösa tjänster med endast internt ASP.NET Core
- Tillståndskänsliga tjänster med endast intern ASP.NET Core
En externt exponerad tjänst är en tjänst som exponerar en slutpunkt som anropas utanför klustret, vanligtvis via en lastbalanserare.
En intern tjänst är en vars slutpunkt bara anropas inifrån klustret.
Kommentar
Tillståndskänsliga tjänstslutpunkter bör vanligtvis inte exponeras för Internet. Kluster bakom lastbalanserare som inte känner till Service Fabric-tjänstmatchning, till exempel Azure Load Balancer, kommer inte att kunna exponera tillståndskänsliga tjänster. Det beror på att lastbalanseraren inte kan hitta och dirigera trafik till lämplig tillståndskänslig tjänstreplik.
Externt exponerade ASP.NET Tillståndslösa kärntjänster
Kestrel är den föreslagna webbservern för klientdelstjänster som exponerar externa, Internetuppkopplade HTTP-slutpunkter. I Windows kan HTTP.sys tillhandahålla portdelningsfunktioner, vilket gör att du kan vara värd för flera webbtjänster på samma uppsättning noder med samma port. I det här scenariot särskiljs webbtjänsterna efter värdnamn eller sökväg, utan att förlita sig på en klientdelsproxy eller gateway för att tillhandahålla HTTP-routning.
När den exponeras för Internet bör en tillståndslös tjänst använda en välkänd och stabil slutpunkt som kan nås via en lastbalanserare. Du anger den här URL:en till programmets användare. Vi rekommenderar följande konfiguration:
Typ | Rekommendation | Kommentar |
---|---|---|
Webbserver | Kestrel | Kestrel är den föredragna webbservern eftersom den stöds i Windows och Linux. |
Portkonfiguration | static | En välkänd statisk port bör konfigureras i konfigurationen Endpoints av ServiceManifest.xml, till exempel 80 för HTTP eller 443 för HTTPS. |
ServiceFabricIntegrationOptions | Ingen | Använd alternativet ServiceFabricIntegrationOptions.None när du konfigurerar Service Fabric-integreringsmellanprogram, så att tjänsten inte försöker verifiera inkommande begäranden för en unik identifierare. Externa användare av ditt program känner inte till den unika identifieringsinformation som mellanprogrammet använder. |
Antal instanser | -1 | I vanliga användningsfall bör inställningen för antal instanser anges till -1. Detta görs så att en instans är tillgänglig på alla noder som tar emot trafik från en lastbalanserare. |
Om flera externt exponerade tjänster delar samma uppsättning noder kan du använda HTTP.sys med en unik men stabil URL-sökväg. Du kan göra detta genom att ändra url:en som angavs när du konfigurerade IWebHost. Observera att detta endast gäller för HTTP.sys.
new HttpSysCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
{
url += "/MyUniqueServicePath";
return new WebHostBuilder()
.UseHttpSys()
...
.UseUrls(url)
.Build();
})
Tillståndslös ASP.NET Core-tjänst endast internt
Tillståndslösa tjänster som endast anropas inifrån klustret bör använda unika URL:er och dynamiskt tilldelade portar för att säkerställa samarbete mellan flera tjänster. Vi rekommenderar följande konfiguration:
Typ | Rekommendation | Kommentar |
---|---|---|
Webbserver | Kestrel | Även om du kan använda HTTP.sys för interna tillståndslösa tjänster är Kestrel den bästa servern för att tillåta flera tjänstinstanser att dela en värd. |
Portkonfiguration | dynamiskt tilldelad | Flera repliker av en tillståndskänslig tjänst kan dela en värdprocess eller värdoperativsystem och behöver därför unika portar. |
ServiceFabricIntegrationOptions | UseUniqueServiceUrl | Med dynamisk porttilldelning förhindrar den här inställningen det felaktiga identitetsproblem som beskrevs tidigare. |
InstanceCount | någon | Instansantalsinställningen kan ställas in på valfritt värde som krävs för att använda tjänsten. |
Tillståndskänslig ASP.NET Core-tjänst endast internt
Tillståndskänsliga tjänster som endast anropas inifrån klustret bör använda dynamiskt tilldelade portar för att säkerställa samarbete mellan flera tjänster. Vi rekommenderar följande konfiguration:
Typ | Rekommendation | Kommentar |
---|---|---|
Webbserver | Kestrel | HttpSysCommunicationListener Är inte utformad för användning av tillståndskänsliga tjänster där repliker delar en värdprocess. |
Portkonfiguration | dynamiskt tilldelad | Flera repliker av en tillståndskänslig tjänst kan dela en värdprocess eller värdoperativsystem och behöver därför unika portar. |
ServiceFabricIntegrationOptions | UseUniqueServiceUrl | Med dynamisk porttilldelning förhindrar den här inställningen det felaktiga identitetsproblem som beskrevs tidigare. |