Timers and Reminder 定時器和提醒器
Orleans runtime 允許開發人員通過一種叫做timer和另一種叫做reminder的機制為grain添加周期性行為。接下來我分別為大家介紹Timer和Reminder
Timers 定時器
Timer用於創建grain的定時任務,但這個定時任務並非跨實例的(StateLessWorker允許多個實例)周期性任務,類似於System.Threading.Timer,但不同的是,它需要它依賴的grain實例來保證單線程執行模式
使用方式
RegisterTimer會返回一個IDisposable引用,你可以通過調用dispose來取消這個timer
protected IDisposable RegisterTimer(Func<object, Task> asyncCallback, object state, TimeSpan dueTime, TimeSpan period)
幾個注意事項
- Timer定時調用不會改變當前grain實例的狀態(grain實例狀態:空閑 idle、使用中use),如果你通過Timer來延遲grian因為空閑太久而被回收 (從idle到use狀態裝換),是行不通的。也就是說即使有timer,如果這個grain一直沒有被調用過,這個grain可能會因為空閑太久而被轉為非激活狀態,timer就不在繼續運行
- Timer的周期,指的是從上一次的調用成功后,到下次調用開始前的一段時間,Orleans的Timer不僅不會發生類似於System.Theading.Timer的重疊調用,而且延長調用周期為【固定的周期+上一次調用的時間】
- Timer的調用,不會和這個grain上的其它調用並行執行。而且asyncCallback不會想其它調用一樣做為消息傳遞
Reminders 提醒器
Reminder和Timer有幾個不同之處:
- Reminder會持久化存儲自身,也就是重啟Orleans,不會導致Reminder失效,它會持續運行
- Reminder是針對Grain,而不是Grain的特定實例
- 如果在Reminder到期提醒時,沒有任何這個Grain的激活實例,它會創建一個新的激活實例
- Reminder的調用時通過消息,在調用方式上,和grain的其它方法調用相同
- Reminder不要使用在高頻率的調用上,調用周期應該是分鍾、小時、或者日級別的,高頻率、短周期的調用,應優先考慮Timer
Reminder的配置
Reminder是一個持久化的提醒,需要后端的存儲支持,這個存儲支持,是Orleans 服務器端的配置文件中的SystemStore配置節點中配置決定的,目前支持AzureTable和SQl SERVER。Orleans官方博客介紹說,會在2015年初開源,等開源了,我想各種第三方的SystemStoreProvider也就不是什么問題了,只要你原因,你可以寫出任何Provider。
如果在開發環境使用,只需要暫時的保留在內存中,可以配置
<ReminderService ReminderServiceType="ReminderTableGrain"/>
使用方式
要使用reminder,必須讓你的grain繼承IRemindable,並實現它的IRemindable.RecieveReminder 方法
Task IRemindable.ReceiveReminder(string reminderName, TickStatus status) { Console.WriteLine("Thanks for reminding me-- I almost forgot!"); return TaskDone.Done; }
然后在Grain內部 需要建立提醒(Reminder)的地方,使用調用grain父類的方法
protected Task<IOrleansReminder> RegisterOrUpdateReminder(string reminderName, TimeSpan dueTime, TimeSpan period)
參數說明:
reminderName reminder名稱,在這個grain內部,需要是唯一的
duetime 第一次調用提醒的時間間隔(從建立到第一次調用)
period 每次調用的周期
取消提醒 cancel reminder
你可以通過調用父類的UnregisterReminder方法來完成.那么在取消之前如何得到這個reminder呢?
①RegisterOrUpdateReminder會返回Reminder的引用 ②通過reminderName,通過父類的GetReminder方法
protected Task UnregisterReminder(IOrleansReminder reminder)
protected Task<IOrleansReminder> GetReminder(string reminderName)
PS:Reminder是一個非常不錯的東西,稍后我會在之后的博文中,介紹如何使用Reminder來保證非持久化消息分布式系統的可靠性
