Fazer cópia de segurança e restaurar o Reliable Services e o Reliable Actors

O Azure Service Fabric é uma plataforma de elevada disponibilidade que replica o estado em vários nós para manter esta elevada disponibilidade. Assim, mesmo que um nó no cluster falhe, os serviços continuam disponíveis. Embora esta redundância incorporada fornecida pela plataforma possa ser suficiente para alguns, em certos casos é desejável que o serviço faça uma cópia de segurança dos dados (para um arquivo externo).

Nota

É fundamental fazer uma cópia de segurança e restaurar os seus dados (e testar se funcionam conforme esperado) para que possa recuperar de cenários de perda de dados.

Nota

A Microsoft recomenda utilizar a cópia de segurança e o restauro periódicos para configurar a cópia de segurança de dados de serviços Reliable Stateful e Reliable Actors.

Por exemplo, um serviço pode querer fazer uma cópia de segurança dos dados para proteger contra os seguintes cenários:

  • Em caso de perda permanente de um cluster completo do Service Fabric.
  • Perda permanente de uma maioria das réplicas de uma partição de serviço
  • Erros administrativos em que o estado é eliminado ou danificado acidentalmente. Por exemplo, isto pode acontecer se um administrador com privilégios suficientes eliminar erroneamente o serviço.
  • Erros no serviço que causam danos nos dados. Por exemplo, isto pode acontecer quando uma atualização do código de serviço começa a escrever dados com falhas numa Coleção Fiável. Nesse caso, tanto o código como os dados podem ter de ser revertidos para um estado anterior.
  • Processamento de dados offline. Pode ser conveniente ter o processamento offline de dados para business intelligence que ocorre separadamente do serviço que gera os dados.

A funcionalidade Cópia de Segurança/Restauro permite que os serviços criados na API reliable Services criem e restaurem cópias de segurança. As APIs de cópia de segurança fornecidas pela plataforma permitem cópias de segurança do estado de uma partição de serviço, sem bloquear operações de leitura ou escrita. As APIs de restauro permitem que o estado de uma partição de serviço seja restaurado a partir de uma cópia de segurança escolhida.

Tipos de Cópia de Segurança

Existem duas opções de cópia de segurança: Completa e Incremental. Uma cópia de segurança completa é uma cópia de segurança que contém todos os dados necessários para recriar o estado da réplica: pontos de verificação e todos os registos. Uma vez que tem os pontos de verificação e o registo, uma cópia de segurança completa pode ser restaurada por si só.

O problema com as cópias de segurança completas surge quando os pontos de verificação são grandes. Por exemplo, uma réplica com 16 GB de estado terá pontos de verificação que somam aproximadamente 16 GB. Se tivermos um Objetivo de Ponto de Recuperação de cinco minutos, a réplica tem de ser efetuada uma cópia de segurança a cada cinco minutos. Sempre que faz uma cópia de segurança, tem de copiar 16 GB de pontos de verificação para além de 50 MB (configuráveis com CheckpointThresholdInMB) de registos.

Exemplo de Cópia de Segurança Completa.

A solução para este problema são as cópias de segurança incrementais, em que a cópia de segurança contém apenas os registos alterados desde a última cópia de segurança.

Exemplo de Cópia de Segurança Incremental.

Uma vez que as cópias de segurança incrementais são apenas alterações desde a última cópia de segurança (não inclui os pontos de verificação), tendem a ser mais rápidas, mas não podem ser restauradas por conta própria. Para restaurar uma cópia de segurança incremental, é necessária toda a cadeia de cópias de segurança. Uma cadeia de cópias de segurança é uma cadeia de cópias de segurança que começa com uma cópia de segurança completa e seguida de várias cópias de segurança incrementais contíguas.

Cópia de Segurança de Serviços Fiáveis

O autor do serviço tem controlo total sobre quando efetuar cópias de segurança e onde as cópias de segurança serão armazenadas.

Para iniciar uma cópia de segurança, o serviço tem de invocar a função BackupAsyncde membro herdado .
As cópias de segurança só podem ser efetuadas a partir de réplicas primárias e exigem a concessão do estado de escrita.

Conforme mostrado abaixo, BackupAsync recebe um BackupDescription objeto, onde se pode especificar uma cópia de segurança completa ou incremental, bem como uma função de chamada de retorno, Func<< BackupInfo, CancellationToken, Task<bool>>> que é invocada quando a pasta de cópia de segurança foi criada localmente e está pronta para ser movida para algum armazenamento externo.


BackupDescription myBackupDescription = new BackupDescription(BackupOption.Incremental,this.BackupCallbackAsync);

await this.BackupAsync(myBackupDescription);

O pedido para efetuar uma cópia de segurança incremental pode falhar com FabricMissingFullBackupException. Esta exceção indica que está a acontecer uma das seguintes coisas:

  • a réplica nunca fez uma cópia de segurança completa, uma vez que se tornou primária,
  • alguns dos registos desde a última cópia de segurança foram truncados ou
  • réplica passou o MaxAccumulatedBackupLogSizeInMB limite.

Os utilizadores podem aumentar a probabilidade de poderem fazer cópias de segurança incrementais ao configurar MinLogSizeInMB ou TruncationThresholdFactor. Aumentar estes valores aumenta a utilização do disco por réplica. Para obter mais informações, veja Reliable Services Configuration (Configuração de Serviços Fiáveis)

BackupInfo fornece informações sobre a cópia de segurança, incluindo a localização da pasta onde o runtime guardou a cópia de segurança (BackupInfo.Directory). A função de chamada de retorno pode mover o BackupInfo.Directory para um arquivo externo ou outra localização. Esta função também devolve um valor bool que indica se foi capaz de mover a pasta de cópia de segurança com êxito para a localização de destino.

O código seguinte demonstra como o BackupCallbackAsync método pode ser utilizado para carregar a cópia de segurança para o Armazenamento do Azure:

private async Task<bool> BackupCallbackAsync(BackupInfo backupInfo, CancellationToken cancellationToken)
{
    var backupId = Guid.NewGuid();

    await externalBackupStore.UploadBackupFolderAsync(backupInfo.Directory, backupId, cancellationToken);

    return true;
}

No exemplo anterior, ExternalBackupStore está a classe de exemplo que é utilizada para interagir com o armazenamento de Blobs do Azure e UploadBackupFolderAsync é o método que comprime a pasta e a coloca no arquivo de Blobs do Azure.

Tenha em atenção que:

  • Só pode haver uma operação de cópia de segurança em voo por réplica a qualquer momento. Mais do que uma BackupAsync chamada de cada vez será emitida FabricBackupInProgressException para limitar as cópias de segurança de voo a uma.
  • Se uma réplica efetuar a ativação pós-falha enquanto uma cópia de segurança estiver em curso, a cópia de segurança poderá não ter sido concluída. Assim, uma vez concluída a ativação pós-falha, é da responsabilidade do serviço reiniciar a cópia de segurança invocando BackupAsync conforme necessário.

Restaurar Serviços Fiáveis

Em geral, os casos em que poderá ter de executar uma operação de restauro enquadram-se numa destas categorias:

  • A partição do serviço perdeu dados. Por exemplo, o disco de duas em cada três réplicas de uma partição (incluindo a réplica primária) fica danificado ou apagado. O novo primário poderá ter de restaurar dados a partir de uma cópia de segurança.
  • Todo o serviço é perdido. Por exemplo, um administrador remove todo o serviço e, por conseguinte, o serviço e os dados têm de ser restaurados.
  • O serviço replicou dados de aplicações danificados (por exemplo, devido a um erro da aplicação). Neste caso, o serviço tem de ser atualizado ou revertido para remover a causa dos danos e os dados não danificados têm de ser restaurados.

Embora muitas abordagens sejam possíveis, oferecemos alguns exemplos sobre como utilizar RestoreAsync para recuperar dos cenários acima.

Perda de dados de partição no Reliable Services

Neste caso, o runtime detetaria automaticamente a perda de dados e invocaria a OnDataLossAsync API.

O autor do serviço tem de efetuar o seguinte para recuperar:

  • Substitua o método OnDataLossAsyncde classe base virtual .
  • Localize a cópia de segurança mais recente na localização externa que contém as cópias de segurança do serviço.
  • Transfira a cópia de segurança mais recente (e descomprima a cópia de segurança para a pasta de cópia de segurança se tiver sido comprimida).
  • O OnDataLossAsync método fornece um RestoreContext. Chame a RestoreAsync API no fornecido RestoreContext.
  • Devolver verdadeiro se a restauração foi um sucesso.

Segue-se um exemplo de implementação do OnDataLossAsync método:

protected override async Task<bool> OnDataLossAsync(RestoreContext restoreCtx, CancellationToken cancellationToken)
{
    var backupFolder = await this.externalBackupStore.DownloadLastBackupAsync(cancellationToken);

    var restoreDescription = new RestoreDescription(backupFolder);

    await restoreCtx.RestoreAsync(restoreDescription);

    return true;
}

RestoreDescription transmitido para a RestoreContext.RestoreAsync chamada contém um membro chamado BackupFolderPath. Ao restaurar uma única cópia de segurança completa, esta BackupFolderPath ação deve ser definida para o caminho local da pasta que contém a cópia de segurança completa. Ao restaurar uma cópia de segurança completa e várias cópias de segurança incrementais, BackupFolderPath deve ser definido para o caminho local da pasta que contém não só a cópia de segurança completa, mas também todas as cópias de segurança incrementais. RestoreAsync a chamada pode ser emitida FabricMissingFullBackupException se o BackupFolderPath fornecido não contiver uma cópia de segurança completa. Também pode ser lançado ArgumentException se BackupFolderPath tiver uma cadeia quebrada de cópias de segurança incrementais. Por exemplo, se contiver a cópia de segurança completa, o primeiro incremental e a terceira cópia de segurança incremental, mas não a segunda cópia de segurança incremental.

Nota

A RestorePolicy está definida como Segura por predefinição. Isto significa que a RestoreAsync API falhará com ArgumentException se detetar que a pasta de cópia de segurança contém um estado mais antigo ou igual ao estado contido nesta réplica. RestorePolicy.Force pode ser utilizado para ignorar esta verificação de segurança. Esta ação é especificada como parte de RestoreDescription.

Serviço eliminado ou perdido

Se um serviço for removido, primeiro tem de recriar o serviço antes de os dados poderem ser restaurados. É importante criar o serviço com a mesma configuração, por exemplo, esquema de criação de partições, para que os dados possam ser restaurados de forma totalmente integrada. Quando o serviço estiver em funcionamento, a API para restaurar dados (OnDataLossAsync acima) tem de ser invocada em todas as partições deste serviço. Uma forma de o fazer é utilizar FabricClient.TestManagementClient.StartPartitionDataLossAsync em cada partição.

A partir deste ponto, a implementação é igual ao cenário acima. Cada partição tem de restaurar a cópia de segurança relevante mais recente a partir do arquivo externo. Uma ressalva é que o ID da partição pode ter sido alterado, uma vez que o runtime cria IDs de partição dinamicamente. Assim, o serviço tem de armazenar as informações de partição adequadas e o nome do serviço para identificar a cópia de segurança mais recente correta a partir de cada partição.

Nota

Não é recomendado utilizar FabricClient.ServiceManager.InvokeDataLossAsync em cada partição para restaurar todo o serviço, uma vez que isso pode danificar o estado do cluster.

Replicação de dados de aplicações danificados

Se a atualização da aplicação recentemente implementada tiver um erro, isso poderá causar danos nos dados. Por exemplo, uma atualização da aplicação pode começar a atualizar todos os registos de números de telefone num Dicionário Fiável com um código de área inválido. Neste caso, os números de telefone inválidos serão replicados, uma vez que o Service Fabric não tem conhecimento da natureza dos dados que estão a ser armazenados.

A primeira coisa a fazer depois de detetar um erro tão grave que causa danos nos dados é congelar o serviço ao nível da aplicação e, se possível, atualizar para a versão do código da aplicação que não tem o erro. No entanto, mesmo depois de o código de serviço ser corrigido, os dados podem ainda estar danificados, pelo que os dados podem ter de ser restaurados. Nestes casos, pode não ser suficiente restaurar a cópia de segurança mais recente, uma vez que as cópias de segurança mais recentes também podem estar danificadas. Assim, tem de encontrar a última cópia de segurança que foi feita antes de os dados serem danificados.

Se não tiver a certeza de que cópias de segurança estão danificadas, poderá implementar um novo cluster do Service Fabric e restaurar as cópias de segurança das partições afetadas, tal como no cenário "Serviço eliminado ou perdido" acima. Para cada partição, comece a restaurar as cópias de segurança do mais recente para o mínimo. Depois de encontrar uma cópia de segurança que não tenha danos, mova/elimine todas as cópias de segurança desta partição que foram mais recentes (do que essa cópia de segurança). Repita este processo para cada partição. Agora, quando OnDataLossAsync for chamada na partição no cluster de produção, a última cópia de segurança encontrada no arquivo externo será a escolhida pelo processo acima.

Agora, os passos na secção "Serviço eliminado ou perdido" podem ser utilizados para restaurar o estado do serviço para o estado antes de o código do buggy danificar o estado.

Tenha em atenção que:

  • Quando restaura, existe a possibilidade de a cópia de segurança ser restaurada ser mais antiga do que o estado da partição antes de os dados serem perdidos. Por este motivo, deve restaurar apenas como último recurso para recuperar o máximo de dados possível.
  • A cadeia que representa o caminho da pasta de cópia de segurança e os caminhos dos ficheiros dentro da pasta de cópia de segurança podem ter mais de 255 carateres, consoante o caminho FabricDataRoot e o comprimento do nome do Tipo de Aplicação. Isto pode fazer com que alguns métodos .NET, como Directory.Move, lancem a PathTooLongException exceção. Uma solução é chamar diretamente as APIs kernel32, como CopyFile.

Criar cópias de segurança e restaurar o Reliable Actors

O Reliable Actors Framework baseia-se no Reliable Services. O ActorService, que aloja o(s) ator(s) é um serviço fiável com monitorização de estado. Assim, todas as funcionalidades de cópia de segurança e restauro disponíveis no Reliable Services também estão disponíveis para o Reliable Actors (exceto comportamentos específicos do fornecedor de estado). Uma vez que as cópias de segurança serão criadas por partição, os estados de todos os atores nessa partição serão efetuados cópias de segurança (e o restauro é semelhante e ocorrerá numa base por partição). Para efetuar a cópia de segurança/restauro, o proprietário do serviço deve criar uma classe de serviço de ator personalizado que deriva da classe ActorService e, em seguida, fazer uma cópia de segurança/restauro semelhante ao Reliable Services, conforme descrito acima nas secções anteriores.

class MyCustomActorService : ActorService
{
    public MyCustomActorService(StatefulServiceContext context, ActorTypeInformation actorTypeInfo)
          : base(context, actorTypeInfo)
    {
    }
    
    //
    // Method overrides and other code.
    //
}

Quando cria uma classe de serviço de ator personalizado, também tem de o registar ao registar o ator.

ActorRuntime.RegisterActorAsync<MyActor>(
    (context, typeInfo) => new MyCustomActorService(context, typeInfo)).GetAwaiter().GetResult();

O fornecedor de estado predefinido do Reliable Actors é KvsActorStateProvider. A cópia de segurança incremental não está ativada por predefinição para KvsActorStateProvider. Pode ativar a KvsActorStateProvider cópia de segurança incremental ao criar com a definição adequada no respetivo construtor e, em seguida, transmiti-la para o construtor ActorService, conforme mostrado no seguinte fragmento de código:

class MyCustomActorService : ActorService
{
    public MyCustomActorService(StatefulServiceContext context, ActorTypeInformation actorTypeInfo)
          : base(context, actorTypeInfo, null, null, new KvsActorStateProvider(true)) // Enable incremental backup
    {
    }
    
    //
    // Method overrides and other code.
    //
}

Após a ativação da cópia de segurança incremental, efetuar uma cópia de segurança incremental pode falhar com FabricMissingFullBackupException por um dos seguintes motivos e terá de fazer uma cópia de segurança completa antes de fazer cópias de segurança incrementais:

  • A réplica nunca fez uma cópia de segurança completa desde que se tornou primária.
  • Alguns dos registos foram truncados desde a última cópia de segurança.

Quando a cópia de segurança incremental está ativada, KvsActorStateProvider não utiliza a memória intermédia circular para gerir os registos e trunca-a periodicamente. Se não for feita qualquer cópia de segurança pelo utilizador durante um período de 45 minutos, o sistema trunca automaticamente os registos. Este intervalo pode ser configurado ao especificar logTruncationIntervalInMinutes no KvsActorStateProvider construtor (semelhante ao ao ativar a cópia de segurança incremental). Os registos também podem ficar truncados se a réplica primária precisar de criar outra réplica ao enviar todos os dados.

Ao efetuar o restauro a partir de uma cadeia de cópia de segurança, semelhante ao Reliable Services, o BackupFolderPath deve conter subdiretórios com um subdiretório que contenha cópia de segurança completa e outros subdiretórios que contenham cópias de segurança incrementais. A API de restauro emitirá FabricException com a mensagem de erro adequada se a validação da cadeia de cópias de segurança falhar.

Nota

KvsActorStateProvider atualmente ignora a opção RestorePolicy.Safe. O suporte para esta funcionalidade está planeado numa versão futura.

Testar Cópia de Segurança e Restauro

É importante garantir que estão a ser efetuadas cópias de segurança de dados críticos e que podem ser restaurados a partir de. Isto pode ser feito ao invocar o Start-ServiceFabricPartitionDataLoss cmdlet no PowerShell que pode induzir a perda de dados numa determinada partição para testar se a funcionalidade de cópia de segurança e restauro de dados para o seu serviço está a funcionar conforme esperado. Também é possível invocar programaticamente a perda de dados e o restauro a partir desse evento.

Nota

Pode encontrar um exemplo de implementação da funcionalidade de cópia de segurança e restauro na Aplicação de Referência Web no GitHub. Veja o Inventory.Service serviço para obter mais detalhes.

Abaixo dos bastidores: mais detalhes sobre a cópia de segurança e o restauro

Eis mais alguns detalhes sobre a cópia de segurança e o restauro.

Backup

O Reliable State Manager permite criar cópias de segurança consistentes sem bloquear operações de leitura ou escrita. Para tal, utiliza um mecanismo de persistência de registo e ponto de verificação. O Reliable State Manager utiliza pontos de verificação difusos (leves) em determinados pontos para aliviar a pressão do registo transacional e melhorar os tempos de recuperação. Quando BackupAsync é chamado, o Reliable State Manager indica a todos os objetos reliable para copiarem os ficheiros de ponto de verificação mais recentes para uma pasta de cópia de segurança local. Em seguida, o Reliable State Manager copia todos os registos, começando do "ponteiro de início" para o registo mais recente para a pasta de cópia de segurança. Uma vez que todos os registos até ao registo mais recente estão incluídos na cópia de segurança e o Reliable State Manager preserva o registo de escrita antecipada, o Reliable State Manager garante que todas as transações consolidadas (CommitAsync devolvidas com êxito) estão incluídas na cópia de segurança.

Qualquer transação consolidada após ter BackupAsync sido chamada pode ou não estar na cópia de segurança. Assim que a pasta de cópia de segurança local tiver sido preenchida pela plataforma (ou seja, a cópia de segurança local é concluída pelo runtime), a chamada de retorno de cópia de segurança do serviço é invocada. Esta chamada de retorno é responsável por mover a pasta de cópia de segurança para uma localização externa, como o Armazenamento do Azure.

Restauro

O Reliable State Manager permite restaurar a partir de uma cópia de segurança com a RestoreAsync API.
O RestoreAsync método em RestoreContext só pode ser chamado dentro do OnDataLossAsync método . O bool devolvido por OnDataLossAsync indica se o serviço restaurou o estado a partir de uma origem externa. Se o devolver verdadeiro, o OnDataLossAsync Service Fabric irá reconstruir todas as outras réplicas desta primária. O Service Fabric garante que as réplicas que receberão OnDataLossAsync a primeira transição de chamadas para a função primária, mas que não recebem o estado de leitura ou de escrita. Isto implica que, para os implementadores do StatefulService, RunAsync não serão chamados até OnDataLossAsync serem concluídos com êxito. Em seguida, OnDataLossAsync será invocado na nova primária. Até que um serviço conclua esta API com êxito (devolvendo verdadeiro ou falso) e conclua a reconfiguração relevante, a API continuará a ser chamada uma de cada vez.

RestoreAsync primeiro, remove todo o estado existente na réplica primária em que foi chamada. Em seguida, o Reliable State Manager cria todos os objetos Reliable que existem na pasta de cópia de segurança. Em seguida, os objetos Reliable são instruídos a restaurar a partir dos respetivos pontos de verificação na pasta de cópia de segurança. Por fim, o Reliable State Manager recupera o seu próprio estado a partir dos registos na pasta de cópia de segurança e efetua a recuperação. Como parte do processo de recuperação, as operações a partir do "ponto de partida" que têm registos consolidados na pasta de cópia de segurança são reproduzidas para os objetos Reliable. Este passo garante que o estado recuperado é consistente.

Passos seguintes