Partilhar via


Aceder, guardar e remover o estado do Reliable Actors

Os Reliable Actors são objetos de thread único que podem encapsular lógica e estado e manter o estado de forma fiável. Cada instância de ator tem o seu próprio gestor de estado: uma estrutura de dados semelhante a um dicionário que armazena pares chave/valor de forma fiável. O gestor de estado é um wrapper em torno de um fornecedor de estado. Pode utilizá-la para armazenar dados, independentemente da definição de persistência utilizada.

As chaves do gestor de estado têm de ser cadeias. Os valores são genéricos e podem ser de qualquer tipo, incluindo tipos personalizados. Os valores armazenados no gestor de estado têm de ser serializáveis por contratos de dados, uma vez que podem ser transmitidos através da rede para outros nós durante a replicação e podem ser escritos no disco, dependendo da definiçã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 Dicionário Fiável.

Para obter informações, veja melhores práticas na gestão do estado do ator.

Estado de acesso

O estado é acedido através do gestor de estado por chave. Os métodos do gestor de estado são todos assíncronos porque podem exigir E/S do disco quando os atores têm o estado persistente. Após o primeiro acesso, os objetos de estado são colocados em cache na memória. Repita as operações de acesso para aceder a objetos diretamente a partir da memória e devolva de forma síncrona sem incorrer na sobrecarga de E/S do disco ou comutação de contexto assíncrona. Um objeto de estado é removido da cache nos seguintes casos:

  • Um método de ator gera uma exceção não processada depois de obter um objeto do gestor de estado.
  • Um ator é reativado após ser desativado ou após a falha.
  • O fornecedor de estado páginas estado para disco. Este comportamento depende da implementação do fornecedor de estado. O fornecedor de estado predefinido para a Persisted definição tem este comportamento.

Pode obter o estado com 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");
    }
}

Também pode obter o estado com um método TryGet que não é apresentado se não existir uma entrada 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;
            });
    }
}

Guardar estado

Os métodos de obtenção do gestor de estado devolvem uma referência a um objeto na memória local. Modificar este objeto apenas na memória local não faz com que seja guardado de forma duradoura. Quando um objeto é obtido do gestor de estado e modificado, tem de ser reinserido no gestor de estado para ser guardado de forma duradoura.

Pode inserir o estado através de 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);
    }
}

Pode adicionar o estado através de um método Adicionar . Este método gera 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);
    }
}

Também pode adicionar o estado com um método TryAdd . Este método não é apresentado 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 de 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 "guardar" pode incluir a persistência no disco e a replicação, consoante as definições utilizadas. Os valores que não foram modificados não são persistentes nem replicados. Se não tiverem sido modificados valores, a operação de guardar não faz nada. Se a gravação falhar, o estado modificado é eliminado e o estado original é recarregado.

Também pode guardar o estado manualmente ao chamar 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

Pode remover permanentemente o estado do gestor de estado de um ator ao chamar o método Remover . Este método gera 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");
    }
}

Também pode remover o estado permanentemente com o método TryRemove . Este método não é apresentado 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!
            }
        });
    }
}

Passos seguintes

O estado armazenado no Reliable Actors tem de ser serializado antes de ser escrito no disco e replicado para elevada disponibilidade. Saiba mais sobre a serialização do tipo Actor.

Em seguida, saiba mais sobre diagnósticos de ator e monitorização de desempenho.