Grain Services
Grain Services zijn extern toegankelijke, gepartitioneerde services voor het ondersteunen van de functionaliteitskorrels. Elk exemplaar van een graanservice is verantwoordelijk voor een aantal korrels en deze korrels kunnen een verwijzing krijgen naar de graanservice die momenteel verantwoordelijk is voor het onderhouden ervan met behulp van een GrainServiceClient
.
Grain Services bestaan ter ondersteuning van gevallen waarin verantwoordelijkheid voor onderhoudskorrels moet worden gedistribueerd over het Orleans cluster. Herinneringen worden bijvoorbeeld Orleans geïmplementeerd met behulp van graanservices: elke silo is verantwoordelijk voor het verwerken van herinneringsbewerkingen voor een subset van korrels en het melden van deze korrels wanneer hun herinneringen worden geactiveerd.
Grain Services worden geconfigureerd op silo's en worden geïnitialiseerd wanneer de silo wordt gestart, voordat de silo wordt geïnitialiseerd. Ze worden niet verzameld wanneer ze niet actief zijn en in plaats daarvan levensduur hebben die de levensduur van de silo zelf verlengen.
Een GrainService maken
Een GrainService is een speciaal graan; een die geen stabiele identiteit heeft en in elke silo wordt uitgevoerd van opstarten tot afsluiten. Er zijn verschillende stappen betrokken bij het implementeren van een IGrainService interface.
Definieer de communicatie-interface van de grain-service. De interface van een
GrainService
is gebouwd met dezelfde principes die u zou gebruiken voor het bouwen van de interface van een graan.public interface IDataService : IGrainService { Task MyMethod(); }
Maak de
DataService
grain-service. Het is goed om te weten dat je ook een IGrainFactory kunt injecteren zodat je graanaanroepen van jeGrainService
.[Reentrant] public class DataService : GrainService, IDataService { readonly IGrainFactory _grainFactory; public DataService( IServiceProvider services, GrainId id, Silo silo, ILoggerFactory loggerFactory, IGrainFactory grainFactory) : base(id, silo, loggerFactory) { _grainFactory = grainFactory; } public override Task Init(IServiceProvider serviceProvider) => base.Init(serviceProvider); public override Task Start() => base.Start(); public override Task Stop() => base.Stop(); public Task MyMethod() { // TODO: custom logic here. return Task.CompletedTask; } }
[Reentrant] public class DataService : GrainService, IDataService { readonly IGrainFactory _grainFactory; public DataService( IServiceProvider services, IGrainIdentity id, Silo silo, ILoggerFactory loggerFactory, IGrainFactory grainFactory) : base(id, silo, loggerFactory) { _grainFactory = grainFactory; } public override Task Init(IServiceProvider serviceProvider) => base.Init(serviceProvider); public override Task Start() => base.Start(); public override Task Stop() => base.Stop(); public Task MyMethod() { // TODO: custom logic here. return Task.CompletedTask; } }
Maak een interface voor het GrainServiceClient<TGrainService>
GrainServiceClient
te gebruiken door andere korrels om verbinding te maken met deGrainService
.public interface IDataServiceClient : IGrainServiceClient<IDataService>, IDataService { }
Maak de grain-serviceclient. Clients fungeren doorgaans als proxy's voor de graanservices waarop ze zijn gericht, zodat u meestal een methode toevoegt voor elke methode in de doelservice. Deze methoden moeten verwijzen naar de graanservice waarop ze zich richten, zodat ze deze kunnen aanroepen. De
GrainServiceClient<T>
basisklasse biedt verschillende overbelastingen van deGetGrainService
methode die een korrelreferentie kan retourneren die overeenkomt met eenGrainId
, een numerieke hash (uint
) of eenSiloAddress
. De laatste twee overbelastingen zijn voor geavanceerde gevallen waarbij een ontwikkelaar een ander mechanisme wil gebruiken om verantwoordelijkheid toe te wijzen aan hosts of een host rechtstreeks wil aanpakken. In onze onderstaande voorbeeldcode definiëren we een eigenschap,GrainService
die deIDataService
waarde retourneert voor het graan dat deDataServiceClient
aanroept. Hiervoor gebruiken we deGetGrainService(GrainId)
overbelasting in combinatie met deCurrentGrainReference
eigenschap.public class DataServiceClient : GrainServiceClient<IDataService>, IDataServiceClient { public DataServiceClient(IServiceProvider serviceProvider) : base(serviceProvider) { } // For convenience when implementing methods, you can define a property which gets the IDataService // corresponding to the grain which is calling the DataServiceClient. private IDataService GrainService => GetGrainService(CurrentGrainReference.GrainId); public Task MyMethod() => GrainService.MyMethod(); }
Maak de werkelijke grain-serviceclient. Het fungeert vrijwel alleen als een proxy voor de gegevensservice. Helaas moet u handmatig alle methodetoewijzingen typen. Dit zijn eenvoudige éénregelige toewijzingen.
public class DataServiceClient : GrainServiceClient<IDataService>, IDataServiceClient { public DataServiceClient(IServiceProvider serviceProvider) : base(serviceProvider) { } public Task MyMethod() => GrainService.MyMethod(); }
Injecteer de grain-serviceclient in de andere korrels die deze nodig hebben. De
GrainServiceClient
toegang tot deGrainService
lokale silo is niet gegarandeerd. Uw opdracht kan mogelijk naar deGrainService
silo in het cluster worden verzonden.public class MyNormalGrain: Grain<NormalGrainState>, INormalGrain { readonly IDataServiceClient _dataServiceClient; public MyNormalGrain( IGrainActivationContext grainActivationContext, IDataServiceClient dataServiceClient) => _dataServiceClient = dataServiceClient; }
Configureer de grain-service- en grainserviceclient in de silo. U moet dit doen zodat de silo de
GrainService
.(ISiloHostBuilder builder) => builder.ConfigureServices( services => services.AddGrainService<DataService>() .AddSingleton<IDataServiceClient, DataServiceClient>());
Aanvullende opmerkingen
Er is een uitbreidingsmethode GrainServicesSiloBuilderExtensions.AddGrainService waarop graanservices worden geregistreerd.
services.AddSingleton<IGrainService>(
serviceProvider => GrainServiceFactory(grainServiceType, serviceProvider));
De silo haalt IGrainService
typen van de serviceprovider op bij het starten: orleans/src/Orleans. Runtime/Silo/Silo.cs
var grainServices = this.Services.GetServices<IGrainService>();
De Microsoft.Orleans. Er moet naar het Runtime NuGet-pakket worden verwezen door het GrainService
project.
De Microsoft.Orleans. Naar het NuGet-pakket OrleansRuntime moet worden verwezen door het GrainService
project.
Om dit te laten werken, moet u zowel de service als de bijbehorende client registreren. De code ziet er ongeveer als volgt uit:
var builder = new HostBuilder()
.UseOrleans(c =>
{
c.AddGrainService<DataService>() // Register GrainService
.ConfigureServices(services =>
{
// Register Client of GrainService
services.AddSingleton<IDataServiceClient, DataServiceClient>();
});
})