执行组件生命周期、自动垃圾回收和手动删除Actor lifecycle, automatic garbage collection, and manual delete

当第一次调用执行组件的任何方法时即可激活该执行组件。An actor is activated the first time a call is made to any of its methods. 如果在可配置的一段时间内未使用执行组件,则此执行组件将停用(执行组件运行时对其进行垃圾回收)。An actor is deactivated (garbage collected by the Actors runtime) if it is not used for a configurable period of time. 还可以在任何时候手动删除执行组件及其状态。An actor and its state can also be deleted manually at any time.

执行组件激活Actor activation

当激活了某个执行组件,将出现以下情况:When an actor is activated, the following occurs:

  • 当调用执行组件时,如果执行组件尚未处于活动状态,则将创建新的执行组件。When a call comes for an actor and one is not already active, a new actor is created.
  • 如果执行组件为维护状态,则加载此执行组件的状态。The actor's state is loaded if it's maintaining state.
  • 将调用 OnActivateAsync (C#) 或 onActivateAsync (Java) 方法(该方法可以在执行组件实现中被覆盖)。The OnActivateAsync (C#) or onActivateAsync (Java) method (which can be overridden in the actor implementation) is called.
  • 现在该执行组件被视为处于活动状态。The actor is now considered active.

执行组件停用Actor deactivation

当停用了某个执行组件,将出现以下情况:When an actor is deactivated, the following occurs:

  • 如果在一段时间内未使用执行组件,则会从“活动执行组件”表中将其删除。When an actor is not used for some period of time, it is removed from the Active Actors table.
  • 将调用 OnDeactivateAsync (C#) 或 onDeactivateAsync (Java) 方法(该方法可以在执行组件实现中被覆盖)。The OnDeactivateAsync (C#) or onDeactivateAsync (Java) method (which can be overridden in the actor implementation) is called. 这会清除此执行组件的所有计时器。This clears all the timers for the actor. 不可从该方法中调用诸如状态更改的执行组件操作。Actor operations like state changes should not be called from this method.

提示

Fabric 执行组件运行时发出一些与执行组件激活和停用相关的事件The Fabric Actors runtime emits some events related to actor activation and deactivation. 它们可用于进行诊断和性能监视。They are useful in diagnostics and performance monitoring.

执行组件垃圾回收Actor garbage collection

停用某个执行组件后,将释放对此执行组件对象的引用,并且通常使用公共语言运行时 (CLR) 或 Java 虚拟机 (JVM) 垃圾回收器对其进行回收。When an actor is deactivated, references to the actor object are released and it can be garbage collected normally by the common language runtime (CLR) or java virtual machine (JVM) garbage collector. 垃圾回收只清除执行组件对象;它不会删除存储在执行组件的状态管理器中的状态。Garbage collection only cleans up the actor object; it does not remove state stored in the actor's State Manager. 当下次激活此执行组件时,将创建一个新的执行组件对象,并还原其状态。The next time the actor is activated, a new actor object is created and its state is restored.

就停用和垃圾回收而言,什么样的执行组件可视为“正在使用”?What counts as "being used" for the purpose of deactivation and garbage collection?

  • 正在接收调用Receiving a call
  • 正在调用的 IRemindable.ReceiveReminderAsync 方法(仅当执行组件使用提醒时该方法才可用)IRemindable.ReceiveReminderAsync method being invoked (applicable only if the actor uses reminders)

备注

如果执行组件使用计时器,且计时器回调得到调用,则不 计为“正在使用”。if the actor uses timers and its timer callback is invoked, it does not count as "being used".

在了解停用的详细信息之前,定义以下术语非常重要:Before we go into the details of deactivation, it is important to define the following terms:

  • 扫描时间间隔Scan interval. 这是执行组件运行时为可以停用和进行垃圾回收的执行组件扫描其活动执行组件表的时间间隔。This is the interval at which the Actors runtime scans its Active Actors table for actors that can be deactivated and garbage collected. 此状态的默认值为 1 分钟。The default value for this is 1 minute.
  • 空闲超时Idle timeout. 这是在停用执行组件并对其进行垃圾回收之前,该执行组件需要保持未使用(空闲)状态的时间。This is the amount of time that an actor needs to remain unused (idle) before it can be deactivated and garbage collected. 此状态的默认值为 60 分钟。The default value for this is 60 minutes.

通常不需要更改这些默认值。Typically, you do not need to change these defaults. 但是,如有必要,可在注册执行组件服务时通过 ActorServiceSettings 更改这些时间间隔:However, if necessary, these intervals can be changed through ActorServiceSettings when registering your Actor Service:

public class Program
{
    public static void Main(string[] args)
    {
        ActorRuntime.RegisterActorAsync<MyActor>((context, actorType) =>
                new ActorService(context, actorType,
                    settings:
                        new ActorServiceSettings()
                        {
                            ActorGarbageCollectionSettings =
                                new ActorGarbageCollectionSettings(10, 2)
                        }))
            .GetAwaiter()
            .GetResult();
    }
}
public class Program
{
    public static void main(String[] args)
    {
        ActorRuntime.registerActorAsync(
                MyActor.class,
                (context, actorTypeInfo) -> new FabricActorService(context, actorTypeInfo),
                timeout);
    }
}

对于每个活动的执行组件,执行组件运行时会持续跟踪其处于空闲状态(即未使用)的时间。For each active actor, the actor runtime keeps track of the amount of time that it has been idle (i.e. not used). 执行组件运行时每隔 ScanIntervalInSeconds 检查每个执行组件,以查看是否可以对它进行垃圾回收,并且如果它已空闲 IdleTimeoutInSeconds,则对其进行标记。The actor runtime checks each of the actors every ScanIntervalInSeconds to see if it can be garbage collected and marks it if it has been idle for IdleTimeoutInSeconds.

任何时候只要使用了执行组件,其空闲时间都会重置为 0。Anytime an actor is used, its idle time is reset to 0. 此后,仅在此执行组件再次空闲 IdleTimeoutInSeconds,才会对其执行垃圾回收。After this, the actor can be garbage collected only if it again remains idle for IdleTimeoutInSeconds. 如果执行执行组件接口方法或执行组件提醒回调,则想到执行组件被视为已使用。Recall that an actor is considered to have been used if either an actor interface method or an actor reminder callback is executed. 如果执行其计时器回调,则执行组件被视为已使用。An actor is not considered to have been used if its timer callback is executed.

下图通过单个执行组件的生命周期来说明这些概念。The following diagram shows the lifecycle of a single actor to illustrate these concepts.

空闲时间示例

此示例显示了执行组件方法调用、提醒和计时器对此执行组件的生存期的影响。The example shows the impact of actor method calls, reminders, and timers on the lifetime of this actor. 值得一提的是有关示例的以下几点:The following points about the example are worth mentioning:

  • ScanInterval 和 IdleTimeout 分别设置为 5 和 10。ScanInterval and IdleTimeout are set to 5 and 10 respectively. (此处的单位无关紧要,因为我们的目的只是为了说明这一概念。)(Units do not matter here, since our purpose is only to illustrate the concept.)
  • 按照扫描间隔时间为 5 的定义,对要执行垃圾回收的执行组件进行的扫描发生在 T = 0、5、10、15、20、25。The scan for actors to be garbage collected happens at T=0,5,10,15,20,25, as defined by the scan interval of 5.
  • T = 4、8、12、16、20、24 时启动定期计时器,并执行其回调。A periodic timer fires at T=4,8,12,16,20,24, and its callback executes. 它不会影响执行组件的空闲时间。It does not impact the idle time of the actor.
  • 在 T = 7 时调用的执行组件方法将空闲时间重置为 0,并延迟此执行组件的垃圾回收。An actor method call at T=7 resets the idle time to 0 and delays the garbage collection of the actor.
  • 执行组件提醒回调在 T = 14 时执行,并进一步延迟执行组件的垃圾回收。An actor reminder callback executes at T=14 and further delays the garbage collection of the actor.
  • 在 T = 25 时的垃圾回收扫描期间,执行组件的空闲时间最终超过空闲超时时间 10,将对此执行组件进行垃圾回收。During the garbage collection scan at T=25, the actor's idle time finally exceeds the idle timeout of 10, and the actor is garbage collected.

当执行组件正在执行它的一个方法时,无论执行该方法用了多少时间,始终不会对此执行组件进行垃圾回收。An actor will never be garbage collected while it is executing one of its methods, no matter how much time is spent in executing that method. 前面曾提到,执行执行组件接口方法和提醒回调可以防止通过将执行组件的空闲时间重置为 0 进行垃圾回收。As mentioned earlier, the execution of actor interface methods and reminder callbacks prevents garbage collection by resetting the actor's idle time to 0. 执行计时器回调不会将空闲时间重置为 0。The execution of timer callbacks does not reset the idle time to 0. 但是,执行组件的垃圾回收会推迟到计时器回调执行完毕。However, the garbage collection of the actor is deferred until the timer callback has completed execution.

手动删除执行组件及其状态Manually deleting actors and their state

对已停用的执行组件进行垃圾回收只会清除该执行组件对象,但是存储在执行组件的状态管理器中的数据不会被删除。Garbage collection of deactivated actors only cleans up the actor object, but it does not remove data that is stored in an actor's State Manager. 重新激活执行组件后,可通过状态管理器再次使用其数据。When an actor is re-activated, its data is again made available to it through the State Manager. 如果执行组件将数据存储在状态管理器,并且已停用且始终不激活该执行组件,那么可能需要清理其数据。In cases where actors store data in State Manager and are deactivated but never re-activated, it may be necessary to clean up their data. 有关如何删除执行组件的示例,请阅读删除执行组件及其状态For examples of how to delete actors, read delete actors and their state.

后续步骤Next steps