Ciclo de vida do ator, libertação de lixo automática e eliminação manual

Um ator é ativado na primeira vez que é feita uma chamada para qualquer um dos seus métodos. Um ator é desativado (lixo recolhido pelo runtime Atores) se não for utilizado durante um período de tempo configurável. Um ator e o respetivo estado também podem ser eliminados manualmente em qualquer altura.

Ativação de ator

Quando um ator é ativado, ocorre o seguinte:

  • Quando uma chamada chega para um ator e uma ainda não está ativa, é criado um novo ator.
  • O estado do ator é carregado se estiver a manter o estado.
  • O OnActivateAsync método (C#) ou onActivateAsync (Java) (que pode ser substituído na implementação do ator) é chamado.
  • O ator é agora considerado ativo.

Desativação do ator

Quando um ator é desativado, ocorre o seguinte:

  • Quando um ator não é utilizado durante algum tempo, é removido da tabela Active Actors.
  • O OnDeactivateAsync método (C#) ou onDeactivateAsync (Java) (que pode ser substituído na implementação do ator) é chamado. Isto limpa todos os temporizadores do ator. As operações de ator, como alterações de estado, não devem ser chamadas a partir deste método.

Dica

O runtime dos Fabric Actors emite alguns eventos relacionados com a ativação e desativação de ator. São úteis nos diagnósticos e na monitorização do desempenho.

Libertação da memória do ator

Quando um ator é desativado, as referências ao objeto de ator são libertadas e podem ser recolhidas da memória normalmente pelo runtime de linguagem comum (CLR) ou pelo recoletor de lixo da máquina virtual Java (JVM). A libertação da memória só limpa o objeto de ator; não remove o estado armazenado no Gestor de Estado do ator. Da próxima vez que o ator for ativado, é criado um novo objeto de ator e o respetivo estado é restaurado.

O que conta como "a ser utilizado" para fins de desativação e libertação da memória?

  • Receber uma chamada
  • IRemindable.ReceiveReminderAsync método que está a ser invocado (aplicável apenas se o ator utilizar lembretes)

Nota

se o ator utilizar temporizadores e a chamada de retorno do temporizador for invocada, não conta como "a ser utilizado".

Antes de avançarmos para os detalhes da desativação, é importante definir os seguintes termos:

  • Intervalo de análise. Este é o intervalo em que o runtime actors analisa a respetiva tabela active actors para atores que podem ser desativados e libertação da memória. O valor predefinido para este valor é de 1 minuto.
  • Tempo limite de inatividade. Esta é a quantidade de tempo que um ator precisa para permanecer inutilizado (inativo) antes de poder ser desativado e libertação da memória. O valor predefinido para este valor é de 60 minutos.

Normalmente, não precisa de alterar estas predefinições. No entanto, se necessário, estes intervalos podem ser alterados ao ActorServiceSettings registar o Serviço de Ator:

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);
    }
}

Para cada ator ativo, o runtime do ator controla a quantidade de tempo durante o qual esteve inativo (ou seja, não foi utilizado). O runtime do ator verifica cada um dos atores ScanIntervalInSeconds para ver se pode ser lixo recolhido e marca-o se estiver inativo para IdleTimeoutInSeconds.

Sempre que um ator é utilizado, o tempo de inatividade é reposto para 0. Depois disso, o ator só pode ser libertado do lixo se permanecer novamente inativo para IdleTimeoutInSeconds. Lembre-se de que um ator é considerado como sendo utilizado se for executado um método de interface de ator ou uma chamada de retorno de lembretes de ator. Um ator não é considerado como sendo utilizado se a chamada de retorno do temporizador for executada.

O diagrama seguinte mostra o ciclo de vida de um único ator para ilustrar estes conceitos.

Exemplo de tempo de inatividade

O exemplo mostra o impacto das chamadas de método de ator, lembretes e temporizadores na duração deste ator. Vale a pena mencionar os seguintes pontos sobre o exemplo:

  • ScanInterval e IdleTimeout estão definidos como 5 e 10, respetivamente. (As unidades não são importantes aqui, uma vez que o nosso objetivo é apenas ilustrar o conceito.)
  • A análise para que os atores sejam recolhidos da memória ocorre em T=0,5,10,15,20,25, conforme definido pelo intervalo de análise de 5.
  • Um temporizador periódico é acionado em T=4,8,12,16,20,24 e a chamada de retorno é executada. Não afeta o tempo de inatividade do ator.
  • Uma chamada de método de ator em T=7 repõe o tempo de inatividade para 0 e atrasa a libertação da memória do ator.
  • Uma chamada de retorno de lembrete de ator é executada em T=14 e atrasa ainda mais a libertação da memória do ator.
  • Durante a análise da libertação da memória em T=25, o tempo de inatividade do ator excede finalmente o tempo limite de inatividade de 10 e o ator é libertado da memória.

Um ator nunca será libertado do lixo enquanto executa um dos seus métodos, independentemente do tempo gasto na execução desse método. Conforme mencionado anteriormente, a execução de métodos de interface de ator e chamadas de retorno de lembretes impede a libertação da memória ao repor o tempo de inatividade do ator para 0. A execução de chamadas de retorno de temporizador não repõe o tempo de inatividade para 0. No entanto, a libertação da memória do ator é adiada até que a chamada de retorno do temporizador tenha concluído a execução.

Eliminar manualmente os atores e o respetivo estado

A libertação da memória de atores desativados só limpa o objeto de ator, mas não remove os dados armazenados no State Manager de um ator. Quando um ator é reativado, os respetivos dados são novamente disponibilizados através do Gestor de Estado. Nos casos em que os atores armazenam dados no State Manager e são desativados, mas nunca são reativados, poderá ser necessário limpar os respetivos dados. Para obter exemplos de como eliminar atores, leia eliminar atores e o respetivo estado.

Passos seguintes