ASP.NET Core in Azure Service Fabric Reliable Services
ASP.NET Core is een opensource- en platformoverschrijdend framework. Dit framework is ontworpen voor het bouwen van cloudtoepassingen die zijn verbonden met internet, zoals web-apps, IoT-apps en mobiele back-ends.
Dit artikel is een uitgebreide handleiding voor het hosten van ASP.NET Core services in Service Fabric Reliable Services met behulp van de Microsoft.ServiceFabric.AspNetCore. set NuGet-pakketten.
Zie Zelfstudie: Een toepassing maken en implementeren met een ASP.NET Core web-API-front-endservice en een stateful back-endservice voor een inleidende zelfstudie over ASP.NET Core in Service Fabric en instructies voor het instellen van uw ontwikkelomgeving.
In de rest van dit artikel wordt ervan uitgegaan dat u al bekend bent met ASP.NET Core. Zo niet, lees dan de basisprincipes van de ASP.NET Core door.
ASP.NET Core in de Service Fabric-omgeving
Zowel ASP.NET Core- als Service Fabric-apps kunnen worden uitgevoerd op .NET Core of volledige .NET Framework. U kunt ASP.NET Core op twee verschillende manieren gebruiken in Service Fabric:
- Gehost als een uitvoerbare gast. Deze manier wordt voornamelijk gebruikt voor het uitvoeren van bestaande ASP.NET Core toepassingen op Service Fabric zonder codewijzigingen.
- Voer uit binnen een betrouwbare service. Op deze manier is een betere integratie met de Service Fabric-runtime mogelijk en staat stateful ASP.NET Core-services toe.
In de rest van dit artikel wordt uitgelegd hoe u ASP.NET Core in een betrouwbare service kunt gebruiken via de ASP.NET Core integratieonderdelen die worden geleverd met de Service Fabric SDK.
Service Fabric-servicehosting
In Service Fabric worden een of meer exemplaren en/of replica's van uw service uitgevoerd in een servicehostproces: een uitvoerbaar bestand waarmee uw servicecode wordt uitgevoerd. U, als serviceauteur, bent de eigenaar van het servicehostproces en Service Fabric activeert en bewaakt dit voor u.
Traditionele ASP.NET (tot MVC 5) is nauw gekoppeld aan IIS via System.Web.dll. ASP.NET Core biedt een scheiding tussen de webserver en uw webtoepassing. Door deze scheiding kunnen webtoepassingen overdraagbaar zijn tussen verschillende webservers. Hiermee kunnen webservers ook zelf-hosten. Dit betekent dat u een webserver in uw eigen proces kunt starten, in plaats van een proces dat eigendom is van toegewezen webserversoftware, zoals IIS.
Als u een Service Fabric-service en ASP.NET wilt combineren, als uitvoerbare gast of in een betrouwbare service, moet u ASP.NET kunnen starten binnen het proces van de servicehost. ASP.NET Core self-hosting stelt u in staat om dit te doen.
Hosting ASP.NET Core in een betrouwbare service
Normaal gesproken maken zelf-hostende ASP.NET Core toepassingen een webhost in het toegangspunt van een toepassing, zoals de static void Main()
methode in Program.cs
. In dit geval is de levenscyclus van de WebHost gebonden aan de levenscyclus van het proces.
Maar het ingangspunt van de toepassing is niet de juiste plek om een webhost te maken in een betrouwbare service. Dat komt omdat het toegangspunt van de toepassing alleen wordt gebruikt om een servicetype te registreren bij de Service Fabric-runtime, zodat er exemplaren van dat servicetype kunnen worden gemaakt. De webhost moet worden gemaakt in een betrouwbare service zelf. Binnen het servicehostproces kunnen service-exemplaren en/of replica's meerdere levenscycluscycli doorlopen.
Een Reliable Service-exemplaar wordt vertegenwoordigd door uw serviceklasse die is afgeleid van StatelessService
of StatefulService
. De communicatiestack voor een service is opgenomen in een ICommunicationListener
implementatie in uw serviceklasse. De Microsoft.ServiceFabric.AspNetCore.*
NuGet-pakketten bevatten implementaties van ICommunicationListener
die de ASP.NET Core WebHost starten en beheren voor Kestrel of HTTP.sys in een betrouwbare service.
ASP.NET Core ICommunicationListeners
De ICommunicationListener
implementaties voor Kestrel en HTTP.sys in de Microsoft.ServiceFabric.AspNetCore.*
NuGet-pakketten hebben vergelijkbare gebruikspatronen. Maar ze voeren iets verschillende acties uit die specifiek zijn voor elke webserver.
Beide communicatielisteners bieden een constructor met de volgende argumenten:
ServiceContext serviceContext
: dit is hetServiceContext
object dat informatie bevat over de actieve service.string endpointName
: dit is de naam van eenEndpoint
configuratie in ServiceManifest.xml. Dit is voornamelijk waar de twee communicatielisteners verschillen. HTTP.sys vereist eenEndpoint
configuratie, maar Kestrel niet.Func<string, AspNetCoreCommunicationListener, IWebHost> build
: dit is een lambda die u implementeert, waarin u een maakt en retourneertIWebHost
. Hiermee kunt u configurerenIWebHost
zoals u dat normaal zou doen in een ASP.NET Core-toepassing. De lambda biedt een URL die voor u wordt gegenereerd, afhankelijk van de Service Fabric-integratieopties die u gebruikt en deEndpoint
configuratie die u opgeeft. Vervolgens kunt u die URL wijzigen of gebruiken om de webserver te starten.
Service Fabric-integratie-middleware
Het Microsoft.ServiceFabric.AspNetCore
NuGet-pakket bevat de UseServiceFabricIntegration
extensiemethode op IWebHostBuilder
waarmee Service Fabric-compatibele middleware wordt toegevoegd. Deze middleware configureert de Kestrel of HTTP.sys ICommunicationListener
om een unieke service-URL te registreren bij de Service Fabric-naamgevingsservice. Vervolgens worden clientaanvragen gevalideerd om ervoor te zorgen dat clients verbinding maken met de juiste service.
Deze stap is nodig om te voorkomen dat clients per ongeluk verbinding maken met de verkeerde service. Dat komt doordat in een omgeving met gedeelde host, zoals Service Fabric, meerdere webtoepassingen kunnen worden uitgevoerd op dezelfde fysieke of virtuele machine, maar geen unieke hostnamen gebruiken. Dit scenario wordt uitgebreid beschreven in de volgende sectie.
Een geval van verkeerde identiteit
Servicereplica's, ongeacht het protocol, luisteren op een unieke combinatie van IP:poort. Zodra een servicereplica is begonnen met luisteren op een IP:poort-eindpunt, rapporteert het dat eindpuntadres aan de Service Fabric-naamgevingsservice. Daar kunnen klanten of andere services het detecteren. Als services dynamisch toegewezen toepassingspoorten gebruiken, kan een servicereplica per ongeluk hetzelfde IP:poorteindpunt van een andere service gebruiken op dezelfde fysieke of virtuele machine. Dit kan ertoe leiden dat een client per ongeluk verbinding maakt met de verkeerde service. Dit scenario kan het gevolg zijn als de volgende reeks gebeurtenissen zich voordoet:
- Service A luistert op 10.0.0.1:30000 via HTTP.
- Client zet Service A om en krijgt adres 10.0.0.1:30000.
- Service A wordt verplaatst naar een ander knooppunt.
- Service B wordt op 10.0.0.1 geplaatst en gebruikt toevallig dezelfde poort 30000.
- Client probeert verbinding te maken met service A met in de cache opgeslagen adres 10.0.0.1:30000.
- De client is nu verbonden met service B en realiseert zich niet dat deze is verbonden met de verkeerde service.
Dit kan op willekeurige momenten fouten veroorzaken die moeilijk te diagnosticeren zijn.
Unieke service-URL's gebruiken
Om deze fouten te voorkomen, kunnen services een eindpunt naar de naamgevingsservice posten met een unieke id en deze unieke id vervolgens valideren tijdens clientaanvragen. Dit is een samenwerkingsactie tussen services in een niet-vijandige tenant vertrouwde omgeving. Het biedt geen veilige serviceverificatie in een omgeving met vijandige tenants.
In een vertrouwde omgeving voegt de middleware die door de UseServiceFabricIntegration
methode wordt toegevoegd, automatisch een unieke id toe aan het adres dat is gepost in de naamgevingsservice. Deze id wordt voor elke aanvraag gevalideerd. Als de id niet overeenkomt, retourneert de middleware onmiddellijk een HTTP 410 Gone-antwoord.
Services die gebruikmaken van een dynamisch toegewezen poort, moeten gebruikmaken van deze middleware.
Services die gebruikmaken van een vaste unieke poort hebben dit probleem niet in een samenwerkingsomgeving. Een vaste unieke poort wordt doorgaans gebruikt voor extern gerichte services die een bekende poort nodig hebben voor clienttoepassingen om verbinding mee te maken. De meeste internetgerichte webtoepassingen gebruiken bijvoorbeeld poort 80 of 443 voor webbrowserverbindingen. In dit geval mag de unieke id niet worden ingeschakeld.
In het volgende diagram ziet u de aanvraagstroom met de middleware ingeschakeld:
Zowel Kestrel als HTTP.sys ICommunicationListener
implementaties gebruiken dit mechanisme op precies dezelfde manier. Hoewel HTTP.sys aanvragen intern kunt onderscheiden op basis van unieke URL-paden met behulp van de onderliggende functie voor het delen van poortenHTTP.sys , wordt deze functionaliteit niet gebruikt door de HTTP.sys-implementatie ICommunicationListener
. Dat komt omdat dit resulteert in HTTP 503- en HTTP 404-foutcodes in het eerder beschreven scenario. Dit maakt het op zijn beurt moeilijk voor clients om de intentie van de fout te bepalen, omdat HTTP 503 en HTTP 404 vaak worden gebruikt om andere fouten aan te geven.
Zowel Kestrel- als HTTP.sys-implementaties ICommunicationListener
standaardiseren dus op middleware die wordt geleverd door de UseServiceFabricIntegration
extensiemethode. Daarom hoeven clients alleen een actie voor het opnieuw omzetten van een service-eindpunt uit te voeren op HTTP 410-antwoorden.
HTTP.sys in Reliable Services
U kunt HTTP.sys in Reliable Services gebruiken door het NuGet-pakket Microsoft.ServiceFabric.AspNetCore.HttpSys te importeren. Dit pakket bevat HttpSysCommunicationListener
, een implementatie van ICommunicationListener
. HttpSysCommunicationListener
hiermee kunt u een ASP.NET Core WebHost binnen een betrouwbare service maken door HTTP.sys als webserver te gebruiken.
HTTP.sys is gebaseerd op de Windows HTTP Server-API. Deze API maakt gebruik van het HTTP.sys kernelstuurprogramma om HTTP-aanvragen te verwerken en deze te routeren naar processen die webtoepassingen uitvoeren. Hierdoor kunnen meerdere processen op dezelfde fysieke of virtuele machine webtoepassingen hosten op dezelfde poort, ondubbelzinnig door een uniek URL-pad of een hostnaam. Deze functies zijn handig in Service Fabric voor het hosten van meerdere websites in hetzelfde cluster.
Notitie
HTTP.sys implementatie werkt alleen op het Windows-platform.
In het volgende diagram ziet u hoe HTTP.sys het HTTP.sys kernelstuurprogramma in Windows gebruikt voor het delen van poorten:
HTTP.sys in een stateless service
Als u wilt gebruiken HttpSys
in een staatloze service, overschrijft u de CreateServiceInstanceListeners
methode en retourneert u een HttpSysCommunicationListener
exemplaar:
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new ServiceInstanceListener[]
{
new ServiceInstanceListener(serviceContext =>
new HttpSysCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
new WebHostBuilder()
.UseHttpSys()
.ConfigureServices(
services => services
.AddSingleton<StatelessServiceContext>(serviceContext))
.UseContentRoot(Directory.GetCurrentDirectory())
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
.UseStartup<Startup>()
.UseUrls(url)
.Build()))
};
}
HTTP.sys in een stateful service
HttpSysCommunicationListener
is momenteel niet ontworpen voor gebruik in stateful services vanwege complicaties met de onderliggende functie voor het delen van poortenHTTP.sys . Zie de volgende sectie over dynamische poorttoewijzing met HTTP.sys voor meer informatie. Voor stateful services is Kestrel de voorgestelde webserver.
Eindpuntconfiguratie
Er is een Endpoint
configuratie vereist voor webservers die gebruikmaken van de Windows HTTP Server-API, inclusief HTTP.sys. Webservers die gebruikmaken van de Windows HTTP Server-API moeten eerst hun URL bij HTTP.sys reserveren (dit wordt normaal gesproken gedaan met het hulpprogramma netsh ).
Voor deze actie zijn verhoogde bevoegdheden vereist die uw services niet standaard hebben. De opties 'http' of 'https' voor de Protocol
eigenschap van de Endpoint
configuratie in ServiceManifest.xml worden specifiek gebruikt om de Service Fabric-runtime te instrueren om namens u een URL met HTTP.sys te registreren. Dit doet u met behulp van het sterke URL-voorvoegsel met jokertekens .
Als u bijvoorbeeld wilt reserveren http://+:80
voor een service, gebruikt u de volgende configuratie in ServiceManifest.xml:
<ServiceManifest ... >
...
<Resources>
<Endpoints>
<Endpoint Name="ServiceEndpoint" Protocol="http" Port="80" />
</Endpoints>
</Resources>
</ServiceManifest>
En de naam van het eindpunt moet worden doorgegeven aan de HttpSysCommunicationListener
constructor:
new HttpSysCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
{
return new WebHostBuilder()
.UseHttpSys()
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
.UseUrls(url)
.Build();
})
Gebruik HTTP.sys met een statische poort
Als u een statische poort wilt gebruiken met HTTP.sys, geeft u het poortnummer op in de Endpoint
configuratie:
<Resources>
<Endpoints>
<Endpoint Protocol="http" Name="ServiceEndpoint" Port="80" />
</Endpoints>
</Resources>
Gebruik HTTP.sys met een dynamische poort
Als u een dynamisch toegewezen poort met HTTP.sys wilt gebruiken, laat u de Port
eigenschap weg in de Endpoint
configuratie:
<Resources>
<Endpoints>
<Endpoint Protocol="http" Name="ServiceEndpoint" />
</Endpoints>
</Resources>
Een dynamische poort die is toegewezen door een Endpoint
configuratie, biedt slechts één poort per hostproces. Met het huidige Service Fabric-hostingmodel kunnen meerdere service-exemplaren en/of replica's in hetzelfde proces worden gehost. Dit betekent dat elke poort dezelfde poort deelt wanneer deze wordt toegewezen via de Endpoint
configuratie. Meerdere HTTP.sys-exemplaren kunnen een poort delen met behulp van de onderliggende functieHTTP.sys poort delen. Maar het wordt niet ondersteund door HttpSysCommunicationListener
vanwege de complicaties die het introduceert voor clientaanvragen. Voor dynamisch poortgebruik is Kestrel de voorgestelde webserver.
Kestrel in Reliable Services
U kunt Kestrel in Reliable Services gebruiken door het NuGet-pakket Microsoft.ServiceFabric.AspNetCore.Kestrel te importeren. Dit pakket bevat KestrelCommunicationListener
, een implementatie van ICommunicationListener
. KestrelCommunicationListener
hiermee kunt u een ASP.NET Core WebHost binnen een betrouwbare service maken door Kestrel als webserver te gebruiken.
Kestrel is een platformoverschrijdende webserver voor ASP.NET Core. In tegenstelling tot HTTP.sys gebruikt Kestrel geen gecentraliseerd eindpuntbeheer. In tegenstelling tot HTTP.sys biedt Kestrel geen ondersteuning voor het delen van poorten tussen meerdere processen. Elk exemplaar van Kestrel moet een unieke poort gebruiken. Zie implementatiedetails voor meer informatie over Kestrel.
Kestrel in een staatloze service
Als u wilt gebruiken Kestrel
in een staatloze service, overschrijft u de CreateServiceInstanceListeners
methode en retourneert u een KestrelCommunicationListener
exemplaar:
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new ServiceInstanceListener[]
{
new ServiceInstanceListener(serviceContext =>
new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
new WebHostBuilder()
.UseKestrel()
.ConfigureServices(
services => services
.AddSingleton<StatelessServiceContext>(serviceContext))
.UseContentRoot(Directory.GetCurrentDirectory())
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.UseUniqueServiceUrl)
.UseStartup<Startup>()
.UseUrls(url)
.Build();
))
};
}
Kestrel in een stateful service
Als u wilt gebruiken Kestrel
in een stateful service, overschrijft u de CreateServiceReplicaListeners
methode en retourneert u een KestrelCommunicationListener
exemplaar:
protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
{
return new ServiceReplicaListener[]
{
new ServiceReplicaListener(serviceContext =>
new KestrelCommunicationListener(serviceContext, (url, listener) =>
new WebHostBuilder()
.UseKestrel()
.ConfigureServices(
services => services
.AddSingleton<StatefulServiceContext>(serviceContext)
.AddSingleton<IReliableStateManager>(this.StateManager))
.UseContentRoot(Directory.GetCurrentDirectory())
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.UseUniqueServiceUrl)
.UseStartup<Startup>()
.UseUrls(url)
.Build();
))
};
}
In dit voorbeeld wordt een singleton-exemplaar van IReliableStateManager
opgegeven voor de webhost-afhankelijkheidsinjectiecontainer. Dit is niet strikt noodzakelijk, maar hiermee kunt u betrouwbare verzamelingen gebruiken IReliableStateManager
in de actiemethoden van uw MVC-controller.
Er Endpoint
is geen configuratienaam opgegeven voor KestrelCommunicationListener
in een stateful service. Dit wordt gedetailleerder uitgelegd in de volgende sectie.
Kestrel configureren voor gebruik van HTTPS
Wanneer u HTTPS inschakelt met Kestrel in uw service, moet u verschillende luisteropties instellen. Werk de ServiceInstanceListener
bij om een EndpointHttps-eindpunt te gebruiken en te luisteren op een specifieke poort (zoals poort 443). Wanneer u de webhost configureert voor het gebruik van de Kestrel-webserver, moet u Kestrel configureren om te luisteren naar IPv6-adressen op alle netwerkinterfaces:
new ServiceInstanceListener(
serviceContext =>
new KestrelCommunicationListener(
serviceContext,
"EndpointHttps",
(url, listener) =>
{
ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting Kestrel on {url}");
return new WebHostBuilder()
.UseKestrel(opt =>
{
int port = serviceContext.CodePackageActivationContext.GetEndpoint("EndpointHttps").Port;
opt.Listen(IPAddress.IPv6Any, port, listenOptions =>
{
listenOptions.UseHttps(GetCertificateFromStore());
listenOptions.NoDelay = true;
});
})
.ConfigureAppConfiguration((builderContext, config) =>
{
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
})
.ConfigureServices(
services => services
.AddSingleton<HttpClient>(new HttpClient())
.AddSingleton<FabricClient>(new FabricClient())
.AddSingleton<StatelessServiceContext>(serviceContext))
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>()
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
.UseUrls(url)
.Build();
}))
Zie Kestrel configureren voor het gebruik van HTTPS voor een volledig voorbeeld in een zelfstudie.
Eindpuntconfiguratie
Er Endpoint
is geen configuratie vereist om Kestrel te gebruiken.
Kestrel is een eenvoudige zelfstandige webserver. In tegenstelling tot HTTP.sys (of HttpListener) is er geen configuratie nodig Endpoint
in ServiceManifest.xml omdat hiervoor geen URL-registratie is vereist voordat u begint.
Kestrel gebruiken met een statische poort
U kunt een statische poort configureren in de Endpoint
configuratie van ServiceManifest.xml voor gebruik met Kestrel. Hoewel dit niet strikt noodzakelijk is, biedt het twee potentiële voordelen:
- Als de poort niet binnen het bereik van de toepassingspoort valt, wordt deze geopend via de firewall van het besturingssysteem door Service Fabric.
- De URL die u via
KestrelCommunicationListener
krijgt, gebruikt deze poort.
<Resources>
<Endpoints>
<Endpoint Protocol="http" Name="ServiceEndpoint" Port="80" />
</Endpoints>
</Resources>
Als een Endpoint
is geconfigureerd, moet de naam ervan worden doorgegeven aan de KestrelCommunicationListener
constructor:
new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) => ...
Als ServiceManifest.xml geen configuratie gebruikt Endpoint
, laat u de naam weg in de KestrelCommunicationListener
constructor. In dit geval wordt een dynamische poort gebruikt. Zie de volgende sectie voor meer informatie hierover.
Kestrel gebruiken met een dynamische poort
Kestrel kan de automatische poorttoewijzing uit de Endpoint
configuratie in ServiceManifest.xml niet gebruiken. Dat komt doordat automatische poorttoewijzing vanuit een Endpoint
configuratie een uniek poortproces per host toewijst en één hostproces meerdere Kestrel-exemplaren kan bevatten. Dit werkt niet met Kestrel omdat het delen van poorten niet ondersteunt. Daarom moet elk exemplaar van Kestrel worden geopend op een unieke poort.
Als u dynamische poorttoewijzing wilt gebruiken met Kestrel, laat u de Endpoint
configuratie als volgt weg in ServiceManifest.xml en geeft u geen eindpuntnaam door aan de KestrelCommunicationListener
constructor:
new KestrelCommunicationListener(serviceContext, (url, listener) => ...
In deze configuratie KestrelCommunicationListener
selecteert automatisch een ongebruikte poort in het bereik van de toepassingspoort.
Voor HTTPS moet het eindpunt zijn geconfigureerd met het HTTPS-protocol zonder een poort die is opgegeven in ServiceManifest.xml en moet de naam van het eindpunt worden doorgegeven aan de constructor KestrelCommunicationListener.
Integratie van IHost en minimale hosting
Naast IWebHost/IWebHostBuilder en KestrelCommunicationListener
HttpSysCommunicationListener
ondersteuning voor het bouwen van ASP.NET Core services met behulp van IHost/IHostBuilder.
Dit is beschikbaar vanaf v5.2.1363 van Microsoft.ServiceFabric.AspNetCore.Kestrel
pakketten en Microsoft.ServiceFabric.AspNetCore.HttpSys
.
// Stateless Service
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new ServiceInstanceListener[]
{
new ServiceInstanceListener(serviceContext =>
new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
{
return Host.CreateDefaultBuilder()
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseKestrel()
.UseStartup<Startup>()
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
.UseContentRoot(Directory.GetCurrentDirectory())
.UseUrls(url);
})
.ConfigureServices(services => services.AddSingleton<StatelessServiceContext>(serviceContext))
.Build();
}))
};
}
// Stateful Service
protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
{
return new ServiceReplicaListener[]
{
new ServiceReplicaListener(serviceContext =>
new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
{
return Host.CreateDefaultBuilder()
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseKestrel()
.UseStartup<Startup>()
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.UseUniqueServiceUrl)
.UseContentRoot(Directory.GetCurrentDirectory())
.UseUrls(url);
})
.ConfigureServices(services =>
{
services.AddSingleton<StatefulServiceContext>(serviceContext);
services.AddSingleton<IReliableStateManager>(this.StateManager);
})
.Build();
}))
};
}
Notitie
Aangezien KestrelCommunicationListener en HttpSysCommunicationListener zijn bedoeld voor webservices, moet u een webserver registreren/configureren (met behulp van de methode ConfigureWebHostDefaults of ConfigureWebHost ) via de IHost
ASP.NET 6 heeft het model Minimale hosting geïntroduceerd. Dit is een eenvoudigere en gestroomlijnde manier om webtoepassingen te maken. Minimaal hostingmodel kan ook worden gebruikt met KestrelCommunicationListener en HttpSysCommunicationListener.
// Stateless Service
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new ServiceInstanceListener[]
{
new ServiceInstanceListener(serviceContext =>
new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
{
var builder = WebApplication.CreateBuilder();
builder.Services.AddSingleton<StatelessServiceContext>(serviceContext);
builder.WebHost
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
.UseUrls(url);
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
return app;
}))
};
}
// Stateful Service
protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
{
return new ServiceReplicaListener[]
{
new ServiceReplicaListener(serviceContext =>
new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
{
var builder = WebApplication.CreateBuilder();
builder.Services
.AddSingleton<StatefulServiceContext>(serviceContext)
.AddSingleton<IReliableStateManager>(this.StateManager);
builder.WebHost
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.UseUniqueServiceUrl)
.UseUrls(url);
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
return app;
}))
};
}
Service Fabric-configuratieprovider
App-configuratie in ASP.NET Core is gebaseerd op sleutel-waardeparen die zijn ingesteld door de configuratieprovider. Lees Configuratie in ASP.NET Core voor meer informatie over algemene ondersteuning voor ASP.NET Core configuratie.
In deze sectie wordt beschreven hoe de Service Fabric-configuratieprovider kan worden geïntegreerd met ASP.NET Core configuratie door het Microsoft.ServiceFabric.AspNetCore.Configuration
NuGet-pakket te importeren.
AddServiceFabricConfiguration-opstartextensies
Nadat u het Microsoft.ServiceFabric.AspNetCore.Configuration
NuGet-pakket hebt geïmporteerd, moet u de Service Fabric-configuratiebron registreren bij ASP.NET Core configuratie-API. U doet dit door AddServiceFabricConfiguration-extensies in de Microsoft.ServiceFabric.AspNetCore.Configuration
naamruimte te controleren op IConfigurationBuilder
.
using Microsoft.ServiceFabric.AspNetCore.Configuration;
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddServiceFabricConfiguration() // Add Service Fabric configuration settings.
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; }
De ASP.NET Core-service heeft nu toegang tot de configuratie-instellingen van Service Fabric, net als alle andere toepassingsinstellingen. U kunt bijvoorbeeld het optiepatroon gebruiken om instellingen te laden in sterk getypte objecten.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<MyOptions>(Configuration); // Strongly typed configuration object.
services.AddMvc();
}
Standaardsleuteltoewijzing
Standaard bevat de Service Fabric-configuratieprovider de pakketnaam, sectienaam en eigenschapsnaam. Samen vormen deze als volgt de ASP.NET Core configuratiesleutel:
$"{this.PackageName}{ConfigurationPath.KeyDelimiter}{section.Name}{ConfigurationPath.KeyDelimiter}{property.Name}"
Als u bijvoorbeeld een configuratiepakket met de naam MyConfigPackage
met de volgende inhoud hebt, is de configuratiewaarde beschikbaar op ASP.NET Core IConfiguration
via MyConfigPackage:MyConfigSection:MyParameter.
<?xml version="1.0" encoding="utf-8" ?>
<Settings xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/2011/01/fabric">
<Section Name="MyConfigSection">
<Parameter Name="MyParameter" Value="Value1" />
</Section>
</Settings>
Service Fabric-configuratieopties
De Service Fabric-configuratieprovider ondersteunt ServiceFabricConfigurationOptions
ook het wijzigen van het standaardgedrag van sleuteltoewijzing.
Versleutelde instellingen
Service Fabric ondersteunt versleutelde instellingen, net als de Service Fabric-configuratieprovider. De versleutelde instellingen worden niet standaard ontsleuteld naar ASP.NET CoreIConfiguration
. De versleutelde waarden worden daar opgeslagen. Maar als u de waarde wilt ontsleutelen die moet worden opgeslagen in ASP.NET Core IConfiguration, kunt u de vlag DecryptValue als volgt instellen op false in de AddServiceFabricConfiguration
extensie:
public Startup()
{
ICodePackageActivationContext activationContext = FabricRuntime.GetActivationContext();
var builder = new ConfigurationBuilder()
.AddServiceFabricConfiguration(activationContext, (options) => options.DecryptValue = false); // set flag to decrypt the value
Configuration = builder.Build();
}
Meerdere configuratiepakketten
Service Fabric ondersteunt meerdere configuratiepakketten. Standaard is de pakketnaam opgenomen in de configuratiesleutel. Maar u kunt de IncludePackageName
vlag als volgt instellen op onwaar:
public Startup()
{
ICodePackageActivationContext activationContext = FabricRuntime.GetActivationContext();
var builder = new ConfigurationBuilder()
// exclude package name from key.
.AddServiceFabricConfiguration(activationContext, (options) => options.IncludePackageName = false);
Configuration = builder.Build();
}
Aangepaste sleuteltoewijzing, waardeextractie en gegevenspopulatie
De Service Fabric-configuratieprovider ondersteunt ook geavanceerdere scenario's voor het aanpassen van de sleuteltoewijzing met ExtractKeyFunc
en het extraheren van de waarden met ExtractValueFunc
. U kunt zelfs het hele proces van het invullen van gegevens van Service Fabric-configuratie wijzigen in ASP.NET Core-configuratie met behulp van ConfigAction
.
In de volgende voorbeelden ziet u hoe u ConfigAction
gegevenspopulatie kunt aanpassen:
public Startup()
{
ICodePackageActivationContext activationContext = FabricRuntime.GetActivationContext();
this.valueCount = 0;
this.sectionCount = 0;
var builder = new ConfigurationBuilder();
builder.AddServiceFabricConfiguration(activationContext, (options) =>
{
options.ConfigAction = (package, configData) =>
{
ILogger logger = new ConsoleLogger("Test", null, false);
logger.LogInformation($"Config Update for package {package.Path} started");
foreach (var section in package.Settings.Sections)
{
this.sectionCount++;
foreach (var param in section.Parameters)
{
configData[options.ExtractKeyFunc(section, param)] = options.ExtractValueFunc(section, param);
this.valueCount++;
}
}
logger.LogInformation($"Config Update for package {package.Path} finished");
};
});
Configuration = builder.Build();
}
Configuratie-updates
De Service Fabric-configuratieprovider ondersteunt ook configuratie-updates. U kunt ASP.NET Core IOptionsMonitor
gebruiken om wijzigingsmeldingen te ontvangen en vervolgens gebruiken IOptionsSnapshot
om configuratiegegevens opnieuw te laden. Zie ASP.NET Core opties voor meer informatie.
Deze opties worden standaard ondersteund. Er is geen verdere codering nodig om configuratie-updates in te schakelen.
Scenario's en configuraties
Deze sectie bevat de combinatie van webserver, poortconfiguratie, Service Fabric-integratieopties en diverse instellingen die we aanraden om de volgende scenario's op te lossen:
- Extern beschikbaar ASP.NET Core stateless services
- Alleen interne ASP.NET Core staatloze services
- Alleen interne ASP.NET Core stateful services
Een extern beschikbaar gemaakte service is een service die een eindpunt beschikbaar maakt dat van buiten het cluster wordt aangeroepen, meestal via een load balancer.
Een interne service is een service waarvan het eindpunt alleen vanuit het cluster wordt aangeroepen.
Notitie
Stateful service-eindpunten mogen over het algemeen niet worden blootgesteld aan internet. Clusters achter load balancers die niet op de hoogte zijn van Service Fabric-serviceomzetting, zoals Azure Load Balancer, kunnen stateful services niet beschikbaar maken. Dat komt omdat de load balancer geen verkeer kan vinden en routeren naar de juiste stateful servicereplica.
Extern beschikbaar ASP.NET Core stateless services
Kestrel is de voorgestelde webserver voor front-endservices die externe, internetgerichte HTTP-eindpunten beschikbaar maken. In Windows kunt HTTP.sys de mogelijkheid voor het delen van poorten bieden, zodat u meerdere webservices op dezelfde set knooppunten kunt hosten met dezelfde poort. In dit scenario worden de webservices onderscheiden op hostnaam of -pad, zonder dat ze afhankelijk zijn van een front-endproxy of gateway om HTTP-routering te bieden.
Wanneer een staatloze service wordt blootgesteld aan internet, moet een bekend en stabiel eindpunt worden gebruikt dat bereikbaar is via een load balancer. U geeft deze URL op aan de gebruikers van uw toepassing. We raden de volgende configuratie aan:
Type | Aanbeveling | Notities |
---|---|---|
Webserver | Torenvalk | Kestrel is de voorkeurswebserver, omdat deze wordt ondersteund in Windows en Linux. |
Poortconfiguratie | statisch | Een bekende statische poort moet worden geconfigureerd in de Endpoints configuratie van ServiceManifest.xml, zoals 80 voor HTTP of 443 voor HTTPS. |
ServiceFabricIntegrationOptions | Geen | Gebruik de optie bij het ServiceFabricIntegrationOptions.None configureren van Service Fabric-integratie-middleware, zodat de service niet probeert binnenkomende aanvragen te valideren voor een unieke id. Externe gebruikers van uw toepassing kennen de unieke identificatiegegevens die de middleware gebruikt niet. |
Aantal instanties | -1 | In typische gebruiksvoorbeelden moet de instelling voor het aantal exemplaren worden ingesteld op -1. Dit wordt gedaan zodat een exemplaar beschikbaar is op alle knooppunten die verkeer van een load balancer ontvangen. |
Als meerdere extern beschikbaar gestelde services dezelfde set knooppunten delen, kunt u HTTP.sys gebruiken met een uniek, maar stabiel URL-pad. U kunt dit doen door de URL te wijzigen die is opgegeven bij het configureren van IWebHost. Houd er rekening mee dat dit alleen van toepassing is op HTTP.sys.
new HttpSysCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
{
url += "/MyUniqueServicePath";
return new WebHostBuilder()
.UseHttpSys()
...
.UseUrls(url)
.Build();
})
Alleen interne staatloze ASP.NET Core-service
Stateless services die alleen vanuit het cluster worden aangeroepen, moeten gebruikmaken van unieke URL's en dynamisch toegewezen poorten om samenwerking tussen meerdere services te garanderen. We raden de volgende configuratie aan:
Type | Aanbeveling | Notities |
---|---|---|
Webserver | Torenvalk | Hoewel u HTTP.sys kunt gebruiken voor interne stateless services, is Kestrel de beste server om meerdere service-exemplaren toe te staan een host te delen. |
Poortconfiguratie | dynamisch toegewezen | Meerdere replica's van een stateful service delen mogelijk een hostproces of hostbesturingssysteem en hebben daarom unieke poorten nodig. |
ServiceFabricIntegrationOptions | UseUniqueServiceUrl | Met dynamische poorttoewijzing voorkomt deze instelling het eerder beschreven verkeerde identiteitsprobleem. |
InstanceCount | alle | De instelling voor het aantal exemplaren kan worden ingesteld op elke waarde die nodig is om de service uit te voeren. |
Alleen interne stateful ASP.NET Core-service
Stateful services die alleen vanuit het cluster worden aangeroepen, moeten dynamisch toegewezen poorten gebruiken om samenwerking tussen meerdere services te garanderen. We raden de volgende configuratie aan:
Type | Aanbeveling | Notities |
---|---|---|
Webserver | Torenvalk | De HttpSysCommunicationListener is niet ontworpen voor gebruik door stateful services waarin replica's een hostproces delen. |
Poortconfiguratie | dynamisch toegewezen | Meerdere replica's van een stateful service delen mogelijk een hostproces of hostbesturingssysteem en hebben daarom unieke poorten nodig. |
ServiceFabricIntegrationOptions | UseUniqueServiceUrl | Met dynamische poorttoewijzing voorkomt deze instelling het eerder beschreven verkeerde identiteitsprobleem. |
Volgende stappen
Foutopsporing uitvoeren in uw Service Fabric-toepassing met behulp van Visual Studio