Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Los servicios de grano son servicios particionados a los que se puede acceder de forma remota para respaldar la funcionalidad de grano. Cada instancia de un servicio de grano es responsable de algunos conjuntos de granos. Esos granos pueden obtener una referencia al servicio de granos actualmente responsable de servirlos mediante un GrainServiceClient
.
Existen servicios para apoyar casos donde la responsabilidad de servicio debe ser distribuida alrededor del clúster Orleans. Por ejemplo, Orleans los recordatorios se implementan mediante servicios de grano: cada silo controla las operaciones de recordatorio para un subconjunto de granos y notifica esos granos cuando se activan sus recordatorios.
Configuras servicios de granos en silos. Se inicializan cuando se inicia el silo, antes de que el silo complete la inicialización. No se recolectan cuando están inactivos; en su lugar, sus tiempos de vida se extienden por la duración del silo mismo.
Crear un servicio de granos
Un GrainService es un grano especial: no tiene ninguna identidad estable y se ejecuta en cada silo desde el inicio hasta el apagado. La implementación de una IGrainService interfaz implica varios pasos.
Defina la interfaz de comunicación de servicio específica. Cree la interfaz de un
GrainService
utilizando los mismos principios que se usan para construir una interfaz de grano.public interface IDataService : IGrainService { Task MyMethod(); }
Cree el
DataService
servicio de grano. Resulta útil saber que también puede insertar un IGrainFactory para que pueda realizar llamadas de grano desde suGrainService
.[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; } }
Cree una interfaz para el GrainServiceClient<TGrainService>
GrainServiceClient
que otros granos usarán para conectarse alGrainService
.public interface IDataServiceClient : IGrainServiceClient<IDataService>, IDataService { }
Cree el cliente de servicio de grano. Los clientes suelen actuar como servidores proxy para los servicios específicos que tienen como destino, por lo que normalmente se agrega un método para cada método en el servicio de destino. Estos métodos deben obtener una referencia al servicio de grano de destino para que puedan llamar a él. La clase base
GrainServiceClient<T>
proporciona varias sobrecargas del métodoGetGrainService
que pueden devolver una referencia de grano correspondiente a unGrainId
, un hash numérico (uint
), o unSiloAddress
. Las últimas dos sobrecargas son para los casos avanzados en los que desea usar un mecanismo diferente para asignar la responsabilidad a los hosts o direccionar directamente a un host. En el siguiente código de ejemplo, definimos una propiedad,GrainService
, que devuelve elIDataService
del grano que llama aDataServiceClient
. Para ello, usamos laGetGrainService(GrainId)
sobrecarga junto con laCurrentGrainReference
propiedad .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(); }
Inserta el cliente de servicio de intervalo de agregación en los otros intervalos que lo necesitan. No se garantiza que
GrainServiceClient
tenga acceso aGrainService
en el silo local. Tu comando podría enviarse aGrainService
en cualquier silo del clúster.public class MyNormalGrain: Grain<NormalGrainState>, INormalGrain { readonly IDataServiceClient _dataServiceClient; public MyNormalGrain( IGrainActivationContext grainActivationContext, IDataServiceClient dataServiceClient) => _dataServiceClient = dataServiceClient; }
Configure el servicio de grano y el cliente del servicio de grano en el silo. Debe hacerlo para que el silo comience
GrainService
.(ISiloHostBuilder builder) => builder.ConfigureServices( services => services.AddGrainService<DataService>() .AddSingleton<IDataServiceClient, DataServiceClient>());
Notas adicionales
Hay un método de extensión, GrainServicesSiloBuilderExtensions.AddGrainService, que se usa para registrar servicios de granos.
services.AddSingleton<IGrainService>(
serviceProvider => GrainServiceFactory(grainServiceType, serviceProvider));
El silo obtiene los IGrainService
tipos del proveedor de servicios al iniciar (consulte orleans/src/Orleans.Runtime/Silo/Silo.cs):
var grainServices = this.Services.GetServices<IGrainService>();
Se debe hacer referencia al paquete NuGet Microsoft.Orleans.Runtime en el proyecto GrainService
.
Para que esto funcione, debe registrar tanto el servicio como su cliente. La salida tendrá un aspecto similar a este:
var builder = new HostBuilder()
.UseOrleans(c =>
{
c.AddGrainService<DataService>() // Register GrainService
.ConfigureServices(services =>
{
// Register Client of GrainService
services.AddSingleton<IDataServiceClient, DataServiceClient>();
});
})