Share via


Gestão de estado do Reliable Actors

Os Reliable Actors são objetos de thread único que podem encapsular lógica e estado. Uma vez que os atores são executados no Reliable Services, podem manter o estado de forma fiável através dos mesmos mecanismos de persistência e replicação. Desta forma, os atores não perdem o estado após falhas, após a reativação após a libertação da memória ou quando são movidos entre nós num cluster devido a balanceamento de recursos ou atualizações.

Persistência e replicação de estado

Todos os Reliable Actors são considerados com monitorização de estado porque cada instância de ator mapeia para um ID exclusivo. Isto significa que as chamadas repetidas para o mesmo ID de ator são encaminhadas para a mesma instância de ator. Por outro lado, num sistema sem estado, não é garantido que as chamadas de cliente sejam sempre encaminhadas para o mesmo servidor. Por este motivo, os serviços de ator são sempre serviços com estado.

Embora os actores sejam considerados estatais, isso não significa que tenham de armazenar o Estado de forma fiável. Os atores podem escolher o nível de persistência e replicação do estado com base nos respetivos requisitos de armazenamento de dados:

  • Estado persistente: o estado persiste no disco e é replicado para três ou mais réplicas. O estado persistente é a opção de armazenamento de estado mais durável, onde o estado pode persistir através de uma interrupção completa do cluster.
  • Estado volátil: o estado é replicado para três ou mais réplicas e apenas mantido na memória. O estado volátil proporciona resiliência contra falhas de nós e falhas de ator e durante as atualizações e o balanceamento de recursos. No entanto, o estado não é persistente no disco. Assim, se todas as réplicas forem perdidas de uma só vez, o estado também será perdido.
  • Sem estado persistente: o estado não é replicado ou escrito no disco, apenas é utilizado para atores que não precisam de manter o estado de forma fiável.

Cada nível de persistência é simplesmente um fornecedor de estado diferente e a configuração de replicação do seu serviço. Se o estado é ou não escrito no disco depende do fornecedor de estado – o componente num serviço fiável que armazena o estado. A replicação depende do número de réplicas com que um serviço é implementado. Tal como acontece com o Reliable Services, tanto o fornecedor de estado como a contagem de réplicas podem ser facilmente definidos manualmente. A arquitetura de ator fornece um atributo que, quando utilizado num ator, seleciona automaticamente um fornecedor de estado predefinido e gera automaticamente definições para a contagem de réplicas para alcançar uma destas três definições de persistência. O atributo StatePersistence não é herdado pela classe derivada. Cada tipo de Ator tem de fornecer o respetivo nível de StatePersistence.

Estado persistente

[StatePersistence(StatePersistence.Persisted)]
class MyActor : Actor, IMyActor
{
}
@StatePersistenceAttribute(statePersistence = StatePersistence.Persisted)
class MyActorImpl  extends FabricActor implements MyActor
{
}

Esta definição utiliza um fornecedor de estado que armazena dados no disco e define automaticamente a contagem de réplicas de serviço como 3.

Estado volátil

[StatePersistence(StatePersistence.Volatile)]
class MyActor : Actor, IMyActor
{
}
@StatePersistenceAttribute(statePersistence = StatePersistence.Volatile)
class MyActorImpl extends FabricActor implements MyActor
{
}

Esta definição utiliza um fornecedor de estado apenas na memória e define a contagem de réplicas como 3.

Sem estado persistente

[StatePersistence(StatePersistence.None)]
class MyActor : Actor, IMyActor
{
}
@StatePersistenceAttribute(statePersistence = StatePersistence.None)
class MyActorImpl extends FabricActor implements MyActor
{
}

Esta definição utiliza um fornecedor de estado apenas na memória e define a contagem de réplicas como 1.

Predefinições e definições geradas

Quando estiver a utilizar o StatePersistence atributo , é automaticamente selecionado um fornecedor de estado no runtime quando o serviço de ator é iniciado. No entanto, a contagem de réplicas é definida no momento da compilação pelas ferramentas de compilação do ator do Visual Studio. As ferramentas de compilação geram automaticamente um serviço predefinido para o serviço de ator no ApplicationManifest.xml. Os parâmetros são criados para o tamanho mínimo do conjunto de réplicas e o tamanho do conjunto de réplicas de destino.

Pode alterar estes parâmetros manualmente. Mas sempre que o StatePersistence atributo é alterado, os parâmetros são definidos para os valores de tamanho predefinidos do conjunto de réplicas para o atributo selecionado StatePersistence , substituindo quaisquer valores anteriores. Por outras palavras, os valores que definiu no ServiceManifest.xml são substituídos no momento da compilação quando altera o valor do StatePersistence atributo.

<ApplicationManifest xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" ApplicationTypeName="Application12Type" ApplicationTypeVersion="1.0.0" xmlns="http://schemas.microsoft.com/2011/01/fabric">
   <Parameters>
      <Parameter Name="MyActorService_PartitionCount" DefaultValue="10" />
      <Parameter Name="MyActorService_MinReplicaSetSize" DefaultValue="3" />
      <Parameter Name="MyActorService_TargetReplicaSetSize" DefaultValue="3" />
   </Parameters>
   <ServiceManifestImport>
      <ServiceManifestRef ServiceManifestName="MyActorPkg" ServiceManifestVersion="1.0.0" />
   </ServiceManifestImport>
   <DefaultServices>
      <Service Name="MyActorService" GeneratedIdRef="77d965dc-85fb-488c-bd06-c6c1fe29d593|Persisted">
         <StatefulService ServiceTypeName="MyActorServiceType" TargetReplicaSetSize="[MyActorService_TargetReplicaSetSize]" MinReplicaSetSize="[MyActorService_MinReplicaSetSize]">
            <UniformInt64Partition PartitionCount="[MyActorService_PartitionCount]" LowKey="-9223372036854775808" HighKey="9223372036854775807" />
         </StatefulService>
      </Service>
   </DefaultServices>
</ApplicationManifest>

Gestor de estado

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. Não fornece quaisquer garantias de que um serviço de ator em execução possa ser alterado de uma definição de estado volátil (apenas na memória) para uma definição de estado persistente através de uma atualização sem interrupção, preservando os dados. No entanto, é possível alterar a contagem de réplicas de um serviço em execução.

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 exemplos de gestão do estado do ator, leia Acesso, guarde e remova o estado do Reliable Actors.

Melhores práticas

Seguem-se algumas práticas sugeridas e sugestões de resolução de problemas para gerir o estado do ator.

Tornar o estado do ator o mais granular possível

Isto é fundamental para o desempenho e a utilização de recursos da sua aplicação. Sempre que existir alguma escrita/atualização para o "estado nomeado" de um ator, todo o valor correspondente a esse "estado nomeado" é serializado e enviado através da rede para as réplicas secundárias. Os secundários escrevem-no no disco local e respondem à réplica primária. Quando a primária recebe confirmações de um quórum de réplicas secundárias, escreve o estado no respetivo disco local. Por exemplo, suponha que o valor é uma classe que tem 20 membros e um tamanho de 1 MB. Mesmo que tenha modificado apenas um dos membros da classe que tem o tamanho 1 KB, acaba por pagar o custo de serialização e escritas de rede e disco para os 1 MB completos. Da mesma forma, se o valor for uma coleção (como uma lista, matriz ou dicionário), paga o custo da coleção completa, mesmo que modifique um dos membros. A interface StateManager da classe de ator é como um dicionário. Deve sempre modelar a estrutura de dados que representa o estado do ator sobre este dicionário.

Gerir corretamente o ciclo de vida do ator

Deve ter uma política clara sobre a gestão do tamanho do estado em cada partição de um serviço de ator. O seu serviço de ator deve ter um número fixo de atores e reutilizá-los o máximo possível. Se criar continuamente novos atores, tem de eliminá-los assim que terminarem o trabalho. A arquitetura de ator armazena alguns metadados sobre cada ator que existe. Eliminar todo o estado de um ator não remove metadados sobre esse ator. Tem de eliminar o ator (ver a eliminação de atores e o respetivo estado) para remover todas as informações sobre o mesmo armazenadas no sistema. Como uma verificação adicional, deve consultar o serviço de ator (ver enumerar atores) de vez em quando para se certificar de que o número de atores está dentro do intervalo esperado.

Se vir que o tamanho do ficheiro de base de dados de um Serviço de Ator está a aumentar para além do tamanho esperado, certifique-se de que está a seguir as diretrizes anteriores. Se estiver a seguir estas diretrizes e ainda estiver a ter problemas com o tamanho do ficheiro de base de dados, deve abrir um pedido de suporte junto da equipa do produto para obter ajuda.

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.