Orleans 2.0 官方文档 ——Grains定时器和提醒器(Reminder)

定时器和提醒器(Reminder)

Orleans运行时提供了两种机制,称为定时器和提醒器,使开发人员能够指定grain的周期性行为。

定时器说明

定时器用于创建不需要跨越多个激活(grain的实例化)的周期性的grain的行为。它基本上等同于标准的.NET System.Threading.Timer类。此外,在它运行的grain激活中,它还受单线程执行保证的约束。

每个激活都可以具有与其相关联的零个或多个计时器。在与定时器关联激活的运行时上下文中,运行时执行每个定时器的例程。

定时器使用

要启动定时器,请使用Grain.RegisterTimer方法,该方法返回 IDisposable引用:

public IDisposable RegisterTimer(
       Func<object, Task> asyncCallback, // function invoked when the timer ticks
       object state,                     // object tp pass to asyncCallback
       TimeSpan dueTime,                 // time to wait before the first timer tick
       TimeSpan period)                  // the period of the timer

通过disposing可以取消计时器。

如果激活被禁用,或者发生故障且其silo崩溃,则定时器将停止触发。

重要的考量因素

启用激活收集后,执行定时器回调,不会将激活状态从Idle状态更改为In Use状态。这意味着计时器不能用于延迟停用其他空闲的激活体。
传递给Grain.RegisterTimer的时间段是,从完成asyncCallback返回的Task起,到下一次调用asyncCallback时所经过的时间。这不仅使得对asyncCallback的连续调用不可能重叠,而且还使得asyncCallback完成所需的时长,影响了调用asyncCallback的频率。这是与System.Threading.Timer的语义的重要偏离。
每次调用asyncCallback,都会在单独的一个回合上传递给一个激活,并且永远不会与同一激活的其他回合同时运行。但请注意,asyncCallback的调用不是作为消息传递的,因此不受消息交错语义的影响。这意味着应该认为asyncCallback的调用行为,就像在相对于该粒度的其他消息的可重入的grain上运行一样。

提醒器说明

提醒与定时器类似,但有一些重要区别:

除非明确取消,否则提醒器是持久性的,并且将在几乎所有情况下(包括部分或全部的群集重新启动)继续触发。
提醒器的“定义”被写入存储。然而,每一个特定的事件,及其特定的时间,却不是如此。这具有副作用,即如果集群刚好在提醒器到点时完全关闭,则将错过此次到点,仅在提醒器的下一个到点时发生。
提醒器与一个grain关联,而不与任何特定的激活关联。
如果grain没有与之关联的激活,并且提醒器到点,则将创建一个grain。例如:如果激活变为空闲且被停用,则与相同grain相关联的提醒器,将在下一个到点时重新激活grain。
提醒器通过消息传递,并且与所有其他grain方法具有相同的交错语义。
提醒器不应用于高频计时器 - 它们的周期应以分钟,小时或天来衡量。

配置

提醒器是持久化的,依赖于存储来发挥作用。您必须在提醒器的子系统运行之前,指定要使用的存储后备。这是通过扩展方法UseXReminderService,来配置其中提醒器的提供程序之一而完成的,其中X是提供程序的名称,例如UseAzureTableReminderService。

Azure表配置:

// TODO replace with your connection string
const string connectionString = "YOUR_CONNECTION_STRING_HERE";
var silo = new SiloHostBuilder()
    [...]
    .UseAzureTableReminderService(options => options.ConnectionString = connectionString)
    [...]

SQL:

// TODO replace with your connection string
const string connectionString = "YOUR_CONNECTION_STRING_HERE";
const string invariant = "YOUR_INVARIANT";
var silo = new SiloHostBuilder()
    [...]
    .UseAdoNetReminderService(options => 
    {
        options.ConnectionString = connectionString;
        options.Invariant = invariant;
    })
    [...]

如果您只是想要一个实现提醒器的占位符,而不需设置Azure帐户或SQL数据库,那么这将为您提供一个仅限开发的提醒器系统实现:

var silo = new SiloHostBuilder()
    [...]
    .UseInMemoryReminderService()
    [...]

提醒器用法

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

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

要启动提醒器,请使用Grain.RegisterOrUpdateReminder方法,该方法返回IOrleansReminder对象:

protected Task<IOrleansReminder> RegisterOrUpdateReminder(string reminderName, TimeSpan dueTime, TimeSpan period)

reminderName是一个字符串,必须唯一地标识上下文的grain作用域内的提醒器。
dueTime指定在发出第一个定时器到点之前等待的时间量。
period指定定时器的周期。
由于提醒器在任何单次激活的生命周期中都存在,因此必须显式地取消它们(而不是被dispose)。您通过调用Grain.UnregisterReminder取消提醒器:

protected Task UnregisterReminder(IOrleansReminder reminder)

提醒器是Grain.RegisterOrUpdateReminder返回的句柄对象。

IOrleansReminder的实例不能保证在激活的生命周期之外是有效的。如果要以持续的方式标识提醒,请使用包含提醒器名称的字符串。

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

protected Task<IOrleansReminder> GetReminder(string reminderName)

我应该使用哪种?

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

如果激活被停用或发生故障,定时器停止工作,这种情况并不要紧(或者是预期内的)。
定时器的分辨率很小(例如,合理地表示成几秒或几分钟)。
定时器回调可以从Grain.OnActivateAsync启动,也可以在调用一个grain方法时启动。
我们建议您在以下情况下使用提醒器:

当周期性行为需要在激活和任何失败时均能执行。
执行不频繁的任务(例如,在几分钟,几小时或几天内合理表达)。

结合计时器和提醒

您可以考虑使用提醒器和计时器的组合来实现目的。例如,如果您需要一个在激活过程中存活下来且分辨率很小的定时器,可以使用每五分钟运行一次的提醒器,其目的是唤醒一个grain重新启动一个本地的定时器,而该定时器可能由于已停用而发生丢失。

转载:https://blog.csdn.net/uddiqpl/article/details/86238115

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值