Orleans Documentation

Timers and Reminders

Orleans运行时提供两种机制来让开发者可以指定grain的一些周期性行为,叫做定时器和提醒器。

定时器

描述

定时器 用来创建周期性的不需要跨越多个激活(grain的实例)的grain行为。它本质上是一种.NET标准。NET System.Threading.Timer类。此外,在grain激活中保证以单线程执行。

每一个激活可能有0个或者多与它有关的定时器。每个定时器例程在与它相关的运行时上下文中执行。

用法

使用Grain.RegisterTimer方法启动一个定时器,返回IDisposable引用:

protected IDisposable RegisterTimer(Func<object, Task> asyncCallback, object state, TimeSpan dueTime, TimeSpan period)
  • asyncCallback是定时器触发的时候调用的函数。
  • state是定时器触发时传递给asyncCallback的一个对象。
  • dueTime指定第一次触发之前的等待时间。
  • period指定触发的周期。

通过析构来取消一个定时器。

如果激活已经注销了或者当错误发生导致了它的silo崩溃,定时器将停止触发。

重要考量

当激活集合已经启用,一个定时器的回掉函数执行不会把激活的状态从闲置变为在使用。这意味着一个定时器不能用来阻止限制的激活注销。 传递给Grain.RegisterTimer的period是从asyncCallback返回的Task被求值得那一刻到下一个asyncCallback被调用经过的时间。这样不光使得对asyncCallback的成功调用不可能重叠并且完成asyncCallback花费的时间会影响asyncCallback调用的频率。 每一个asyncCallback的调用在单独的回合被传递给一个激活并且永远不会在同一个激活中与跟其他回合并发执行。然而请注意,asyncCallback调用不会被当作信息传递并且因此不受消息交错语义的影响。这表示在grain的消息消方面看,asyncCallback的调用应该被当作表现的像运行在一个可重入的grain。

提醒器

描述

提醒器类似定时器,但是有一些重要的不同:

  • 提醒器是持久化的并且在所有情况下(包括部分和全部的集群重启)将会持续触发除非主动取消。
  • 提醒器跟一个grain相关,而不是任何特定的激活。
  • 如果一个grain没有相关的激活并且一个提醒器出发了,一个激活将会被创建。例如:如果一个激活变成闲置的并且注销了,相同grain相关的一个额提醒器下一次触发的时候将会重新激活grain。

配置

提醒器的持久化依赖存储功能。你必须在提醒器子系统运转之前指定提醒器使用的后端存储。提醒器功能由服务端配置中的SystemStore元素控制。可以使用Azure Table和SQL server作为存储。

<SystemStore SystemStoreType="AzureTable" /> OR
<SystemStore SystemStoreType="SqlServer" />

如果你仅仅是想使用一个占位的提醒器实现来工作不需要设置Azure账户或者SQL数据库,通过添加这个元素到配置文件中(在’Globals’下),能让你得到一个提醒器系统的开发时使用的实现。

<ReminderService ReminderServiceType="ReminderTableGrain"/>

用法

一个使用提醒器的grain必须实现IRemindable.RecieveReminder方法。

Task IRemindable.ReceiveReminder(string reminderName, TickStatus status)
{
    Console.WriteLine("Thanks for reminding me-- I almost forgot!");
    return TaskDone.Done;
}

使用返回一个IOrleansReminder对象的Grain.RegisterOrUpdateReminder方法来启动一个提醒器。

protected Task<IOrleansReminder> RegisterOrUpdateReminder(string reminderName, TimeSpan dueTime, TimeSpan period)
  • reminderName是一个在grain上下文范围内唯一标识提醒器的字符串。
  • dueTime指定第一次触发之前等待的时间。
  • period指定定时器的周期。

因为提醒器独立于任何单个激活的生存时间,所以他们必须显式地取消(而不是被析构)。你可以通过调用Grain.UnregisterReminder取消一个提醒器。

protected Task UnregisterReminder(IOrleansReminder reminder)

reminder是Grain.RegisterOrUpdateReminder返回的处理对象。

IOrleansReminder的实例不保证在激活的寿命之前有效。如果你想有效识别一个提醒器,使用一个包含提醒器名字的字符串。

如果你只有提醒器的名字并且需要相应的IOrleansReminder实例,调用Grain.GetReminder方法:

protected Task<IOrleansReminder> GetReminder(string reminderName)

我应该使用什么?

我们建议你在以下情况下使用定时器:

  • 如果激活被注销或者错误发生后定时器不再工作不重要(或者可取的)。
  • 如果计时器周期很小(例如:几秒或者几分钟是合理的)。
  • 定时器的回掉函数可以在Grain.OnActivateAsync或者grain方法被调用的时候被启动。

我们建议你在以下情况使用提醒器:

  • 当周期性的行为需要不受激活的或者其他错误的影响。
  • 运行不常见的任务(例如:几分钟几小时或者几天是合理的)。

组合定时器和提醒器

你可能考虑组合使用定时器和提醒器来完成你的目的。例如:如果你需要一个小周期的并且不受激活影响的定时器,你可以使用一个每五分钟运行的提醒器,目的是唤醒一个grain来重启可能在注销时已经丢失的本地定时器。