Orleans:构建高性能分布式Actor服务
上QQ阅读APP看书,第一时间看更新

2.4.2 显式控制Grain状态

Grain对象的激活是Orleans运行时根据外部服务请求自动创建Grain类的过程,而Grain实例的休眠实际上是Orleans运行时对空闲Grain实例的垃圾回收(Garbage Collection,GC),这与.NET/Java等高级语言运行时中的GC过程非常相似,两者的区别在于:.NET/Java等高级语言运行时是基于系统内存的使用情况触发GC过程的,而Orleans运行时是通过计算Grain实例的空闲时间来进行休眠状态的判定与标记的。

然而,在某些业务场景下,开发人员可能需要在Grain实例运行阶段对Grain实例的活跃周期进行延长。例如,在对可预测的流量高峰到达前,通过内部API对集群进行预热,以减少系统冷启动所造成的性能损失。在这种情况下,开发人员可以在Grain实例逻辑内部调用DelayDeactivation()方法延缓该Grain实例被运行时回收的时间(实际是延后该实例被标记为空闲的时间):

在调用DelayDeactivation函数后,Orleans运行时将确保该Grain实例所占有的系统资源在指定的时间段内不被回收,对DelayDeactivation函数的调用会覆盖开发人员在Orleans服务端所配置的全局GC策略,但并不会禁用Orleans运行时对该Grain实例的回收监测过程。若开发人员需要在下一次GC过程中回收Grain实例,则可以调用Grain类的DeactivateOnIdle( )方法,该方法会提示Orleans运行时在下一次Grain实例闲置时回收该Grain实例的资源:

Grain实例将在其处理完所有消息任务时,被Orleans运行时标识为空闲实例,若在响应外部业务逻辑调用时执行DeactivateOnIdle方法,则该Grain实例会在处理完此次请求后被立即回收,其他任何待处理请求都将被Orleans运行时调度转发至该Grain的下一个激活实例对象中响应。

例如,以下Sentinel Grain类型可以按照外部服务请求控制其自身的GC策略。

若在DelayDeactivation函数中传入一个大于零的timeSpan值,意味着“在该时间段内不对此Grain实例执行垃圾回收”,而一个小于零的timeSpan值则表明“取消之前对于该Grain实例的生命周期配置,使该Grain实例按照全局运行时垃圾回收配置进行生命周期管理”。例如:

1)运行时全局垃圾回收策略配置为Grain闲置时间大于10分钟,某一Grain实例在最后一次业务请求时调用了DelayDeactivation(TimeSpan.FromMinutes(20)),该Grain实例将不会在20分钟之内被垃圾回收。

2)运行时全局垃圾回收策略配置为Grain闲置时间大于10分钟,某一Grain实例在最后一次业务请求时调用了DelayDeactivation(TimeSpan.FromMinutes(5)),则该Grain实例将在空闲后的10分钟后被Orleans运行时回收。

3)运行时全局垃圾回收策略配置为Grain闲置时间大于10分钟,某一Grain实例在0时刻调用了DelayDeactivation(TimeSpan.FromMinutes(5)),而在第7分钟时该Grain实例又接收到了一个新的业务请求,在此之后该Grain实例闲置,则该实例将在0时刻后的第17分钟后被Orleans运行时回收。

4)运行时全局垃圾回收策略配置为Grain闲置时间大于10分钟,某一Grain实例在0时刻调用了DelayDeactivation(TimeSpan.FromMinutes(20)),而在第7分钟时该Grain实例又接收到了一个新的业务请求,在此之后该Grain实例闲置,则该实例将在0时刻后的第20分钟后被Orleans运行时回收。

在此需要开发人员注意的是,通过DelayDeactivation及DeactivateOnIdle对Grain实例生命周期的显式配置都只是针对该Grain实例对象,而不影响其他Grain实例;通过调用Deactiva-teOnIdle所设置的垃圾回收配置优先级不仅比Orleans运行时的全局配置高,也高于通过Delay-Deactivation方法配置的延缓回收的配置。因此,若在同一Grain实例内先后调用DelayDeactivation及DeactivateOnIdle方法,则该Grain实例状态将被标识为需要立即回收。