Partilhar via


Acesse, salve e remova o estado Reliable Actors

Atores confiáveis são objetos de thread único que podem encapsular lógica e estado e manter o estado de forma confiável. Cada instância de ator tem seu próprio gerenciador de estado: uma estrutura de dados semelhante a um dicionário que armazena de forma confiável pares chave/valor. O gestor estadual é um invólucro em torno de um provedor estatal. Você pode usá-lo para armazenar dados, independentemente de qual configuração de persistência é usada.

As chaves do gerenciador de estado devem ser strings. Os valores são genéricos e podem ser de qualquer tipo, incluindo tipos personalizados. Os valores armazenados no gerenciador de estado devem ser serializáveis por contrato de dados porque podem ser transmitidos pela rede para outros nós durante a replicação e podem ser gravados no disco, dependendo da configuração de persistência de estado de um ator.

O gestor de estado expõe métodos de dicionário comuns para gerir o estado, semelhantes aos encontrados no Reliable Dictionary.

Para obter informações, consulte as práticas recomendadas no gerenciamento do estado do ator.

Estado de acesso

O estado é acessado através do gestor estadual por chave. Os métodos do gerenciador de estado são todos assíncronos porque podem exigir E/S de disco quando os atores têm estado persistente. Após o primeiro acesso, os objetos de estado são armazenados em cache na memória. As operações de acesso repetidas acessam objetos diretamente da memória e retornam de forma síncrona sem incorrer em E/S de disco ou sobrecarga assíncrona de comutação de contexto. Um objeto de estado é removido do cache nos seguintes casos:

  • Um método ator lança uma exceção não tratada depois de recuperar um objeto do gestor de estado.
  • Um ator é reativado, seja depois de ser desativado ou após uma falha.
  • O estado das páginas do provedor de estado no disco. Esse comportamento depende da implementação do provedor de estado. O provedor de estado padrão para a Persisted configuração tem esse comportamento.

Você pode recuperar o estado usando uma operação Get padrão que lança KeyNotFoundException(C#) ou NoSuchElementException(Java) se não existir uma entrada para a chave:

[StatePersistence(StatePersistence.Persisted)]
class MyActor : Actor, IMyActor
{
    public MyActor(ActorService actorService, ActorId actorId)
        : base(actorService, actorId)
    {
    }

    public Task<int> GetCountAsync()
    {
        return this.StateManager.GetStateAsync<int>("MyState");
    }
}
@StatePersistenceAttribute(statePersistence = StatePersistence.Persisted)
class MyActorImpl extends FabricActor implements  MyActor
{
    public MyActorImpl(ActorService actorService, ActorId actorId)
    {
        super(actorService, actorId);
    }

    public CompletableFuture<Integer> getCountAsync()
    {
        return this.stateManager().getStateAsync("MyState");
    }
}

Você também pode recuperar o estado usando um método TryGet que não é lançado se uma entrada não existir para uma chave:

class MyActor : Actor, IMyActor
{
    public MyActor(ActorService actorService, ActorId actorId)
        : base(actorService, actorId)
    {
    }

    public async Task<int> GetCountAsync()
    {
        ConditionalValue<int> result = await this.StateManager.TryGetStateAsync<int>("MyState");
        if (result.HasValue)
        {
            return result.Value;
        }

        return 0;
    }
}
class MyActorImpl extends FabricActor implements  MyActor
{
    public MyActorImpl(ActorService actorService, ActorId actorId)
    {
        super(actorService, actorId);
    }

    public CompletableFuture<Integer> getCountAsync()
    {
        return this.stateManager().<Integer>tryGetStateAsync("MyState").thenApply(result -> {
            if (result.hasValue()) {
                return result.getValue();
            } else {
                return 0;
            });
    }
}

Salvar estado

Os métodos de recuperação do gerenciador de estado retornam uma referência a um objeto na memória local. Modificar esse objeto apenas na memória local não faz com que ele seja salvo de forma durável. Quando um objeto é recuperado do gerenciador de estado e modificado, ele deve ser reinserido no gerenciador de estado para ser salvo de forma durável.

Você pode inserir o estado usando um conjunto incondicional, que é o equivalente à dictionary["key"] = value sintaxe:

[StatePersistence(StatePersistence.Persisted)]
class MyActor : Actor, IMyActor
{
    public MyActor(ActorService actorService, ActorId actorId)
        : base(actorService, actorId)
    {
    }

    public Task SetCountAsync(int value)
    {
        return this.StateManager.SetStateAsync<int>("MyState", value);
    }
}
@StatePersistenceAttribute(statePersistence = StatePersistence.Persisted)
class MyActorImpl extends FabricActor implements  MyActor
{
    public MyActorImpl(ActorService actorService, ActorId actorId)
    {
        super(actorService, actorId);
    }

    public CompletableFuture setCountAsync(int value)
    {
        return this.stateManager().setStateAsync("MyState", value);
    }
}

Você pode adicionar estado usando um método Add . Este método lança InvalidOperationException(C#) ou IllegalStateException(Java) quando tenta adicionar uma chave que já existe.

[StatePersistence(StatePersistence.Persisted)]
class MyActor : Actor, IMyActor
{
    public MyActor(ActorService actorService, ActorId actorId)
        : base(actorService, actorId)
    {
    }

    public Task AddCountAsync(int value)
    {
        return this.StateManager.AddStateAsync<int>("MyState", value);
    }
}
@StatePersistenceAttribute(statePersistence = StatePersistence.Persisted)
class MyActorImpl extends FabricActor implements  MyActor
{
    public MyActorImpl(ActorService actorService, ActorId actorId)
    {
        super(actorService, actorId);
    }

    public CompletableFuture addCountAsync(int value)
    {
        return this.stateManager().addOrUpdateStateAsync("MyState", value, (key, old_value) -> old_value + value);
    }
}

Você também pode adicionar estado usando um método TryAdd . Este método não é lançado quando tenta adicionar uma chave que já existe.

[StatePersistence(StatePersistence.Persisted)]
class MyActor : Actor, IMyActor
{
    public MyActor(ActorService actorService, ActorId actorId)
        : base(actorService, actorId)
    {
    }

    public async Task AddCountAsync(int value)
    {
        bool result = await this.StateManager.TryAddStateAsync<int>("MyState", value);

        if (result)
        {
            // Added successfully!
        }
    }
}
@StatePersistenceAttribute(statePersistence = StatePersistence.Persisted)
class MyActorImpl extends FabricActor implements  MyActor
{
    public MyActorImpl(ActorService actorService, ActorId actorId)
    {
        super(actorService, actorId);
    }

    public CompletableFuture addCountAsync(int value)
    {
        return this.stateManager().tryAddStateAsync("MyState", value).thenApply((result)->{
            if(result)
            {
                // Added successfully!
            }
        });
    }
}

No final de um método ator, o gestor de estado guarda automaticamente quaisquer valores que tenham sido adicionados ou modificados por uma operação de inserção ou atualização. Um "save" pode incluir persistência em disco e replicação, dependendo das configurações usadas. Os valores que não foram modificados não são persistentes ou replicados. Se nenhum valor tiver sido modificado, a operação de salvamento não fará nada. Se a gravação falhar, o estado modificado será descartado e o estado original será recarregado.

Você também pode salvar o estado manualmente chamando o SaveStateAsync método na base do ator:

async Task IMyActor.SetCountAsync(int count)
{
    await this.StateManager.AddOrUpdateStateAsync("count", count, (key, value) => count > value ? count : value);

    await this.SaveStateAsync();
}
interface MyActor {
    CompletableFuture setCountAsync(int count)
    {
        this.stateManager().addOrUpdateStateAsync("count", count, (key, value) -> count > value ? count : value).thenApply();

        this.stateManager().saveStateAsync().thenApply();
    }
}

Remover estado

Você pode remover o estado permanentemente do gerenciador de estado de um ator chamando o método Remover . Este método lança KeyNotFoundException(C#) ou NoSuchElementException(Java) quando tenta remover uma chave que não existe.

[StatePersistence(StatePersistence.Persisted)]
class MyActor : Actor, IMyActor
{
    public MyActor(ActorService actorService, ActorId actorId)
        : base(actorService, actorId)
    {
    }

    public Task RemoveCountAsync()
    {
        return this.StateManager.RemoveStateAsync("MyState");
    }
}
@StatePersistenceAttribute(statePersistence = StatePersistence.Persisted)
class MyActorImpl extends FabricActor implements  MyActor
{
    public MyActorImpl(ActorService actorService, ActorId actorId)
    {
        super(actorService, actorId);
    }

    public CompletableFuture removeCountAsync()
    {
        return this.stateManager().removeStateAsync("MyState");
    }
}

Você também pode remover o estado permanentemente usando o método TryRemover . Este método não é lançado quando tenta remover uma chave que não existe.

[StatePersistence(StatePersistence.Persisted)]
class MyActor : Actor, IMyActor
{
    public MyActor(ActorService actorService, ActorId actorId)
        : base(actorService, actorId)
    {
    }

    public async Task RemoveCountAsync()
    {
        bool result = await this.StateManager.TryRemoveStateAsync("MyState");

        if (result)
        {
            // State removed!
        }
    }
}
@StatePersistenceAttribute(statePersistence = StatePersistence.Persisted)
class MyActorImpl extends FabricActor implements  MyActor
{
    public MyActorImpl(ActorService actorService, ActorId actorId)
    {
        super(actorService, actorId);
    }

    public CompletableFuture removeCountAsync()
    {
        return this.stateManager().tryRemoveStateAsync("MyState").thenApply((result)->{
            if(result)
            {
                // State removed!
            }
        });
    }
}

Próximos passos

O estado armazenado em Reliable Actors deve ser serializado antes de ser gravado em disco e replicado para alta disponibilidade. Saiba mais sobre a serialização do tipo Ator.

Em seguida, saiba mais sobre o diagnóstico do ator e o monitoramento de desempenho.