Grain Services
Grain Services är fjärranslutna, partitionerade tjänster för stöd för funktionsintervall. Varje instans av en korntjänst ansvarar för vissa uppsättningar korn och dessa korn kan få en referens till korntjänsten som för närvarande ansvarar för att underhålla dem med hjälp av en GrainServiceClient
.
Grain Services finns för att stödja fall där ansvaret för att underhålla korn bör distribueras runt Orleans klustret. Påminnelser implementeras till exempel Orleans med hjälp av spannmålstjänster: varje silo ansvarar för att hantera påminnelseåtgärder för en delmängd korn och meddela dessa korn när deras påminnelser utlöses.
Grain Services konfigureras på silor och initieras när silon startar, innan silon slutför initieringen. De samlas inte in när de är inaktiva och har i stället livslängder som sträcker sig över silons livslängd.
Skapa en GrainService
A GrainService är ett särskilt korn, ett som inte har någon stabil identitet och körs i varje silo från start till avstängning. Det finns flera steg när du implementerar ett IGrainService gränssnitt.
Definiera kommunikationsgränssnittet för korntjänsten. Gränssnittet för en
GrainService
skapas med samma principer som du skulle använda för att skapa gränssnittet för ett korn.public interface IDataService : IGrainService { Task MyMethod(); }
DataService
Skapa korntjänsten. Det är bra att veta att du också kan mata in en IGrainFactory så att du kan göra korn samtal från dinGrainService
.[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; } }
Skapa ett gränssnitt som GrainServiceClient<TGrainService>
GrainServiceClient
ska användas av andra korn för att ansluta tillGrainService
.public interface IDataServiceClient : IGrainServiceClient<IDataService>, IDataService { }
Skapa korntjänstklienten. Klienter fungerar vanligtvis som proxyservrar för de korntjänster som de riktar in sig på, så du lägger vanligtvis till en metod för varje metod i måltjänsten. Dessa metoder måste hämta en referens till den korntjänst som de riktar in sig på så att de kan anropa den. Basklassen
GrainServiceClient<T>
innehåller flera överlagringar avGetGrainService
metoden som kan returnera en kornreferens som motsvarar enGrainId
, en numerisk hash (uint
) eller enSiloAddress
. De två senare överlagringarna gäller avancerade fall där en utvecklare vill använda en annan mekanism för att mappa ansvar till värdar eller vill adressera en värd direkt. I vår exempelkod nedan definierar vi en egenskap,GrainService
, som returnerarIDataService
för kornet som anroparDataServiceClient
. För att göra det använder vi överlagringenGetGrainService(GrainId)
tillsammans medCurrentGrainReference
egenskapen .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(); }
Skapa klienten för den faktiska korntjänsten. Det fungerar i stort sett bara som en proxy för datatjänsten. Tyvärr måste du manuellt skriva in alla metodmappningar, som bara är enkla one-liners.
public class DataServiceClient : GrainServiceClient<IDataService>, IDataServiceClient { public DataServiceClient(IServiceProvider serviceProvider) : base(serviceProvider) { } public Task MyMethod() => GrainService.MyMethod(); }
Mata in korntjänstklienten i de andra kornen som behöver den.
GrainServiceClient
Är inte garanterat att komma åt påGrainService
den lokala silo. Kommandot kan eventuellt skickas tillGrainService
på valfri silo i klustret.public class MyNormalGrain: Grain<NormalGrainState>, INormalGrain { readonly IDataServiceClient _dataServiceClient; public MyNormalGrain( IGrainActivationContext grainActivationContext, IDataServiceClient dataServiceClient) => _dataServiceClient = dataServiceClient; }
Konfigurera korntjänst- och korntjänstklienten i silon. Du måste göra detta så att silon startar
GrainService
.(ISiloHostBuilder builder) => builder.ConfigureServices( services => services.AddGrainService<DataService>() .AddSingleton<IDataServiceClient, DataServiceClient>());
Ytterligare kommentarer
Det finns en tilläggsmetod GrainServicesSiloBuilderExtensions.AddGrainService som används för att registrera spannmålstjänster.
services.AddSingleton<IGrainService>(
serviceProvider => GrainServiceFactory(grainServiceType, serviceProvider));
Silon hämtar typerna IGrainService
från tjänstleverantören vid start: orleans/src/Orleans.Runtime/Silo/Silo.cs
var grainServices = this.Services.GetServices<IGrainService>();
Microsoft .Orleans. NuGet-paketet Runtime ska refereras till GrainService
av projektet.
Microsoft .Orleans. OrleansRuntime NuGet-paketet ska refereras av GrainService
projektet.
För att detta ska fungera måste du registrera både tjänsten och dess klient. Koden ser ut ungefär så här:
var builder = new HostBuilder()
.UseOrleans(c =>
{
c.AddGrainService<DataService>() // Register GrainService
.ConfigureServices(services =>
{
// Register Client of GrainService
services.AddSingleton<IDataServiceClient, DataServiceClient>();
});
})