Orleans - это структура модели акторов, которая используется для простого создания распределенных систем в кластере машин. В этом посте мы рассмотрим функцию «Напоминания» Орлеана.

Во-первых, документы:



Напоминания можно использовать в Орлеане для выполнения задач более или менее «по расписанию». Мне сложно придумать простой пример, который действительно имеет смысл, поэтому мы собираемся использовать сигнализацию «все в порядке»:

Чтобы установить сигнализацию «все в порядке», нам нужно сделать несколько вещей:

  • Включите службу напоминаний в ISiloHostBuilder - мы будем использовать службу в памяти только для простоты, и чтобы не приходилось полагаться на дополнительную инфраструктуру.
  • Новое зерно напоминания
  • Что-то, что нужно сделать для зерна напоминания.

Я подумал, что мы могли бы использовать FakeEmailSender, представленные в:



чтобы отправлять «поддельные электронные письма», все в порядке.

Включите службу напоминаний

Начиная с https://github.com/Kritner-Blogs/OrleansGettingStarted/releases/tag/v0.40, мы включим службу напоминаний в памяти, добавив следующую строку в наш ISiloHostBuilder.

.UseInMemoryReminderService()

Полный метод:

private static async Task<ISiloHost> StartSilo()
{
 // define the cluster configuration
 var builder = new SiloHostBuilder()
  .UseLocalhostClustering()
  .Configure<ClusterOptions>(options =>
  {
   options.ClusterId = "dev";
   options.ServiceId = "HelloWorldApp";
  })
  .Configure<EndpointOptions>(options => options.AdvertisedIPAddress = IPAddress.Loopback)
  .AddMemoryGrainStorage(Constants.OrleansMemoryProvider)
  .ConfigureApplicationParts(parts =>
  {
    parts.AddApplicationPart(typeof(IGrainMarker).Assembly).WithReferences();
  })
  .ConfigureServices(DependencyInjectionHelper.IocContainerRegistration)
  .UseDashboard(options => { })
  .UseInMemoryReminderService()
  .ConfigureLogging(logging => logging.AddConsole());
 var host = builder.Build();
 await host.StartAsync();
 return host;
}

Некоторые другие возможные службы напоминания, которые можно использовать, включают AzureTableReminderService и AdoNetReminderService.

Напоминание зерна

Давайте создадим тревожное зерно, в котором все в порядке! В письменной форме я обнаружил, что существует минимум 1 минута времени между «напоминаниями», поэтому, к сожалению, мы не соберем первоначально запланированные 3 секунды :(

В любом случае ... наш интерфейс зерна:

public interface IEverythingIsOkGrain : IGrainWithStringKey, IRemindable
{
 Task Start();
 Task Stop();
}

В приведенном выше примере мы делаем довольно стандартный интерфейс зерна с дополнительным (будет) реализованным IRemindable. К интерфейсу прикреплены два метода: один для запуска напоминания, другой для его остановки. Обратите внимание, что интерфейс IRemindable требует, чтобы реализующий класс реализовал:

Task ReceiveReminder(string reminderName, TickStatus status);

Зерновая реализация - также Grainception!

Как я уже упоминал ранее, мы будем использовать FakeEmailSender, созданный из предыдущего поста, а также использовать другие зерна в нашем создаваемом зерне (grainception)!

Это могло выглядеть так:

[StorageProvider(ProviderName = Constants.OrleansMemoryProvider)]
public class EverythingIsOkGrain : Grain, IEverythingIsOkGrain
{
 IGrainReminder _reminder = null;
 public async Task ReceiveReminder(string reminderName, TickStatus status)
 {
  // Grain-ception!
  var emailSenderGrain = GrainFactory
   .GetGrain<IEmailSenderGrain>(Guid.Empty);
  await emailSenderGrain.SendEmail(
   "[email protected]",
   new[] 
   {
    "[email protected]",
    "[email protected]",
    "[email protected]",
    "[email protected]"
   },
   "Everything's ok!",
   "This alarm will sound every 1 minute, as long as everything is ok!"
  );
 }
 public async Task Start()
 {
  if (_reminder != null)
  {
   return;
  }
  _reminder = await RegisterOrUpdateReminder(
   this.GetPrimaryKeyString(),
   TimeSpan.FromSeconds(3),
   TimeSpan.FromMinutes(1) // apparently the minimum
  );
 }
public async Task Stop()
 {
  if (_reminder == null)
  {
   return;
  }
  await UnregisterReminder(_reminder);
  _reminder = null;
 }
}

Несколько замечаний из вышеизложенного:

  • [StorageProvider(ProviderName = Constants.OrleansMemoryProvider)] - мы делаем зернистость с учетом состояния, поэтому (теоретически) напоминание будет сохраняться при завершении работы. Обратите внимание, что в нашем случае этого не произойдет из-за использования памяти, я * думаю * иначе было бы.
  • IGrainReminder _reminder = null; - содержит ссылку на наше начатое напоминание, используемое для остановки напоминания.
  • Task ReceiveReminder(string reminderName, TickStatus status) - это метод, с помощью которого мы фактически определяем, что происходит при появлении напоминания.
  • var emailSenderGrain = GrainFactory.GetGrain<IEmailSenderGrain>(Guid.Empty); - здесь мы используем несколько другие способы получения зерна, поскольку на самом деле мы делаем это из SiloHost, а не из Client. Обратите внимание, что это вытягиваемое зерно также использует внедрение зависимостей, но его зависимость вводится только в зерно, которое действительно в нем нуждается, а не в это зерно напоминания.

Новая опция меню зерна

как обычно, мы собираемся создать новую IOrleansFunction конкрецию для использования в нашей системе меню; это новое зерно также будет добавлено для возврата из нашего IOrleansFunctionProvider.

public class EverythingIsOkReminder : IOrleansFunction
{
 public string Description => "Demonstrates a reminder service, notifying the user that everything is ok... every three seconds...";
 public async Task PerformFunction(IClusterClient clusterClient)
 {
  var grain = clusterClient.GetGrain<IEverythingIsOkGrain>(
   $"{nameof(IEverythingIsOkGrain)}-{Guid.NewGuid()}"
  );
  Console.WriteLine("Starting everything's ok alerm after key press.");
  Console.ReadKey();
  Console.WriteLine("Starting everything's ok reminder...");
  await grain.Start();
  Console.WriteLine("Reminder started.  Press any key to stop reminder.");
  Console.ReadKey();
  await grain.Stop();
  ConsoleHelpers.ReturnToMenu();
 }
}

Пробовать это

Согласно нормам, мы будем запускать SiloHost, Client и пробовать новое зерно.

В приведенном выше примере вы можете видеть, что наше «FakeEmail» попало в журнал Orleans, заявив, что все в порядке.

Еще одна интересная вещь, которую мы можем увидеть, добавив в предыдущий пост Дашборд Орлеана:

Аккуратный!

В этом посте мы узнали немного об еще одной особенности Орлеана - напоминаниях! Вы можете найти код этого сообщения по адресу:



Связанный: