Introdução ao Reliable Services

Um aplicativo do Azure Service Fabric contém um ou mais serviços que executam seu código. Este guia mostra como criar aplicativos do Service Fabric sem e com monitoração de estado com Serviços Confiáveis.

Verifique esta página para um vídeo de treinamento que também mostraria como criar um serviço confiável sem monitoração de estado.

Conceitos básicos

Para começar a usar os Serviços Confiáveis, você só precisa entender alguns conceitos básicos:

  • Tipo de serviço: Esta é a sua implementação de serviço. Ele é definido pela classe que você escreve que se estende StatelessService e qualquer outro código ou dependências usadas nele, juntamente com um nome e um número de versão.
  • Instância de serviço nomeada: para executar o serviço, você cria instâncias nomeadas do seu tipo de serviço, da mesma forma que cria instâncias de objeto de um tipo de classe. Uma instância de serviço tem um nome na forma de um URI usando o esquema "fabric:/", como "fabric:/MyApp/MyService".
  • Host de serviço: as instâncias de serviço nomeadas que você cria precisam ser executadas dentro de um processo de host. O host de serviço é apenas um processo onde as instâncias do seu serviço podem ser executadas.
  • Registo de serviços: O registo reúne tudo. O tipo de serviço deve ser registrado com o tempo de execução do Service Fabric em um host de serviço para permitir que o Service Fabric crie instâncias dele para execução.

Criar um serviço sem estado

Um serviço sem estado é um tipo de serviço que é atualmente a norma em aplicativos em nuvem. É considerado apátrida porque o serviço em si não contém dados que precisam ser armazenados de forma confiável ou altamente disponíveis. Se uma instância de um serviço sem estado for encerrada, todo o seu estado interno será perdido. Nesse tipo de serviço, o estado deve ser persistido para um armazenamento externo, como Tabelas do Azure ou Banco de Dados SQL, para que ele seja altamente disponível e confiável.

Inicie o Visual Studio 2017 ou Visual Studio 2019 como administrador e crie um novo projeto de aplicativo do Service Fabric chamado HelloWorld:

Use a caixa de diálogo Novo Projeto para criar um novo aplicativo do Service Fabric

Em seguida, crie um projeto de serviço sem estado usando o .NET Core 2.0 chamado HelloWorldStateless:

Na segunda caixa de diálogo, crie um projeto de serviço sem estado

Sua solução agora contém dois projetos:

  • HelloWorld. Este é o projeto de aplicativo que contém seus serviços. Ele também contém o manifesto do aplicativo que descreve o aplicativo, bem como vários scripts do PowerShell que ajudam você a implantar seu aplicativo.
  • HelloWorldStateless. Este é o projeto de serviço. Ele contém a implementação do serviço sem monitoração de estado.

Implementar o serviço

Abra o arquivo HelloWorldStateless.cs no projeto de serviço. No Service Fabric, um serviço pode executar qualquer lógica de negócios. A API de serviço fornece dois pontos de entrada para o seu código:

  • Um método de ponto de entrada aberto, chamado RunAsync, onde você pode começar a executar quaisquer cargas de trabalho, incluindo cargas de trabalho de computação de longa duração.
protected override async Task RunAsync(CancellationToken cancellationToken)
{
    ...
}
  • Um ponto de entrada de comunicação onde você pode conectar sua pilha de comunicação de escolha, como ASP.NET Core. É aqui que você pode começar a receber solicitações de usuários e outros serviços.
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
    ...
}

Neste tutorial, vamos nos concentrar no método de RunAsync() ponto de entrada. É aqui que você pode começar imediatamente a executar seu código. O modelo de projeto inclui uma implementação de exemplo que RunAsync() incrementa uma contagem contínua.

Nota

Para obter detalhes sobre como trabalhar com uma pilha de comunicação, consulte Comunicação de serviço com o ASP.NET Core

RunAsync

protected override async Task RunAsync(CancellationToken cancellationToken)
{
    // TODO: Replace the following sample code with your own logic
    //       or remove this RunAsync override if it's not needed in your service.

    long iterations = 0;

    while (true)
    {
        cancellationToken.ThrowIfCancellationRequested();

        ServiceEventSource.Current.ServiceMessage(this.Context, "Working-{0}", ++iterations);

        await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
    }
}

A plataforma chama esse método quando uma instância de um serviço é colocada e está pronta para ser executada. Para um serviço sem estado, isso significa simplesmente quando a instância de serviço é aberta. Um token de cancelamento é fornecido para coordenar quando sua instância de serviço precisa ser fechada. No Service Fabric, esse ciclo de abertura/fechamento de uma instância de serviço pode ocorrer muitas vezes ao longo do tempo de vida do serviço como um todo. Isso pode acontecer por vários motivos, incluindo:

  • O sistema move suas instâncias de serviço para balanceamento de recursos.
  • Ocorrem falhas no seu código.
  • O aplicativo ou sistema é atualizado.
  • O hardware subjacente sofre uma interrupção.

Essa orquestração é gerenciada pelo sistema para manter seu serviço altamente disponível e devidamente equilibrado.

RunAsync() não deve bloquear de forma síncrona. Sua implementação de RunAsync deve retornar uma tarefa ou aguardar em quaisquer operações de longa execução ou bloqueio para permitir que o tempo de execução continue. Observe que no while(true) loop no exemplo anterior, um retorno de await Task.Delay() tarefa é usado. Se sua carga de trabalho precisar ser bloqueada de forma síncrona, você deverá agendar uma nova Tarefa com Task.Run() em sua RunAsync implementação.

O cancelamento da sua carga de trabalho é um esforço cooperativo orquestrado pelo token de cancelamento fornecido. O sistema aguardará que a sua tarefa termine (por conclusão bem-sucedida, cancelamento ou falha) antes de prosseguir. É importante honrar o token de cancelamento, terminar qualquer trabalho e sair RunAsync() o mais rápido possível quando o sistema solicitar o cancelamento.

Neste exemplo de serviço sem estado, a contagem é armazenada em uma variável local. Mas como esse é um serviço sem monitoração de estado, o valor armazenado existe apenas para o ciclo de vida atual de sua instância de serviço. Quando o serviço é movido ou reiniciado, o valor é perdido.

Criar um serviço com monitoração de estado

O Service Fabric introduz um novo tipo de serviço com monitoração de estado. Um serviço com estado pode manter o estado de forma confiável dentro do próprio serviço, colocalizado com o código que o está usando. O estado é disponibilizado altamente pelo Service Fabric sem a necessidade de persistir o estado em um armazenamento externo.

Para converter um valor de contador de stateless em altamente disponível e persistente, mesmo quando o serviço é movido ou reiniciado, você precisa de um serviço com monitoração de estado.

No mesmo aplicativo HelloWorld , você pode adicionar um novo serviço clicando com o botão direito do mouse nas referências de Serviços no projeto de aplicativo e selecionando Adicionar -> Novo Serviço do Service Fabric.

Adicionar um serviço ao seu aplicativo do Service Fabric

Selecione .NET Core 2.0 -> Stateful Service e nomeie-o HelloWorldStateful. Clique em OK.

Use a caixa de diálogo Novo Projeto para criar um novo serviço com estado do Service Fabric

Seu aplicativo agora deve ter dois serviços: o serviço sem estado HelloWorldStateless e o serviço stateful HelloWorldStateful.

Um serviço com monitoração de estado tem os mesmos pontos de entrada que um serviço sem monitoração de estado. A principal diferença é a disponibilidade de um provedor de estado que pode armazenar o estado de forma confiável. O Service Fabric vem com uma implementação de provedor de estado chamada Coleções Confiáveis, que permite criar estruturas de dados replicadas por meio do Gerenciador de Estado Confiável. Um Serviço Confiável com monitoração de estado usa esse provedor de estado por padrão.

Abra HelloWorldStateful.cs em HelloWorldStateful, que contém o seguinte método RunAsync:

protected override async Task RunAsync(CancellationToken cancellationToken)
{
    // TODO: Replace the following sample code with your own logic
    //       or remove this RunAsync override if it's not needed in your service.

    var myDictionary = await this.StateManager.GetOrAddAsync<IReliableDictionary<string, long>>("myDictionary");

    while (true)
    {
        cancellationToken.ThrowIfCancellationRequested();

        using (var tx = this.StateManager.CreateTransaction())
        {
            var result = await myDictionary.TryGetValueAsync(tx, "Counter");

            ServiceEventSource.Current.ServiceMessage(this.Context, "Current Counter Value: {0}",
                result.HasValue ? result.Value.ToString() : "Value does not exist.");

            await myDictionary.AddOrUpdateAsync(tx, "Counter", 0, (key, value) => ++value);

            // If an exception is thrown before calling CommitAsync, the transaction aborts, all changes are
            // discarded, and nothing is saved to the secondary replicas.
            await tx.CommitAsync();
        }

        await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
    }

RunAsync

RunAsync() opera de forma semelhante em serviços com e sem estado. No entanto, em um serviço com monitoração de estado, a plataforma executa trabalho adicional em seu nome antes de ser executada RunAsync(). Esse trabalho pode incluir a garantia de que o Reliable State Manager e o Reliable Collections estejam prontos para uso.

Coleções confiáveis e o gestor de estado confiável

var myDictionary = await this.StateManager.GetOrAddAsync<IReliableDictionary<string, long>>("myDictionary");

IReliableDictionary é uma implementação de dicionário que você pode usar para armazenar de forma confiável o estado no serviço. Com o Service Fabric e as Coleções Confiáveis, você pode armazenar dados diretamente em seu serviço sem a necessidade de um armazenamento persistente externo. Coleções confiáveis tornam seus dados altamente disponíveis. O Service Fabric faz isso criando e gerenciando várias réplicas do seu serviço para você. Ele também fornece uma API que abstrai as complexidades do gerenciamento dessas réplicas e suas transições de estado.

As Coleções Confiáveis podem armazenar qualquer tipo .NET, incluindo seus tipos personalizados, com algumas ressalvas:

  • O Service Fabric torna seu estado altamente disponível replicando o estado entre nós, e as Coleções Confiáveis armazenam seus dados no disco local em cada réplica. Isso significa que tudo o que é armazenado em coleções confiáveis deve ser serializável. Por padrão, as Coleções Confiáveis usam DataContract para serialização, portanto, é importante garantir que seus tipos sejam suportados pelo Serializador de Contrato de Dados quando você usa o serializador padrão.

  • Os objetos são replicados para alta disponibilidade quando você confirma transações em Coleções Confiáveis. Os objetos armazenados em Coleções Confiáveis são mantidos na memória local em seu serviço. Isso significa que você tem uma referência local ao objeto.

    É importante que você não mute instâncias locais desses objetos sem executar uma operação de atualização na coleção confiável em uma transação. Isso ocorre porque as alterações em instâncias locais de objetos não serão replicadas automaticamente. Você deve reinserir o objeto novamente no dicionário ou usar um dos métodos de atualização no dicionário.

O Gestor de Estado Fiável gere Coleções Fiáveis para si. Você pode simplesmente pedir ao Gestor de Estado Confiável uma coleção confiável pelo nome a qualquer momento e em qualquer lugar em seu serviço. O Reliable State Manager garante que você receba uma referência de volta. Não recomendamos que você salve referências a instâncias de coleta confiáveis em variáveis ou propriedades de membros de classe. Cuidados especiais devem ser tomados para garantir que a referência seja definida para uma instância em todos os momentos do ciclo de vida do serviço. O Reliable State Manager lida com esse trabalho para você e é otimizado para visitas repetidas.

Operações transacionais e assíncronas

using (ITransaction tx = this.StateManager.CreateTransaction())
{
    var result = await myDictionary.TryGetValueAsync(tx, "Counter-1");

    await myDictionary.AddOrUpdateAsync(tx, "Counter-1", 0, (k, v) => ++v);

    await tx.CommitAsync();
}

As Coleções Confiáveis têm muitas das mesmas operações que suas System.Collections.Generic e System.Collections.Concurrent suas contrapartes, exceto para Language Integrated Query (LINQ). As operações em coleções confiáveis são assíncronas. Isso ocorre porque as operações de gravação com Coleções Confiáveis executam operações de E/S para replicar e persistir dados no disco.

As operações de Coleta Confiável são transacionais, para que você possa manter o estado consistente em várias Coleções e operações Confiáveis. Por exemplo, você pode retirar um item de trabalho da fila de uma fila confiável, executar uma operação nela e salvar o resultado em um dicionário confiável, tudo dentro de uma única transação. Isso é tratado como uma operação atômica e garante que toda a operação será bem-sucedida ou toda a operação será revertida. Se ocorrer um erro depois de retirar o item da fila, mas antes de salvar o resultado, toda a transação será revertida e o item permanecerá na fila para processamento.

Executar a aplicação

Voltamos agora à aplicação HelloWorld . Agora você pode criar e implantar seus serviços. Quando você pressiona F5, seu aplicativo será criado e implantado no cluster local.

Depois que os serviços começarem a ser executados, você poderá exibir os eventos gerados do Rastreamento de Eventos para Windows (ETW) em uma janela Eventos de Diagnóstico . Observe que os eventos exibidos são do serviço stateless e do serviço stateful no aplicativo. Você pode pausar o fluxo clicando no botão Pausar . Em seguida, você pode examinar os detalhes de uma mensagem expandindo essa mensagem.

Nota

Antes de executar o aplicativo, verifique se você tem um cluster de desenvolvimento local em execução. Consulte o guia de introdução para obter informações sobre como configurar o seu ambiente local.

Exibir eventos de diagnóstico no Visual Studio

Próximos passos

Depurar seu aplicativo do Service Fabric no Visual Studio

Introdução: Serviços de API Web do Service Fabric com auto-hospedagem OWIN

Saiba mais sobre Coleções confiáveis

Implementar uma aplicação

Atualização da aplicação

Referência do desenvolvedor para serviços confiáveis