Ciclo de vida dos Reliable Services

O Reliable Services é um dos modelos de programação disponíveis no Azure Service Fabric. Ao saber mais sobre o ciclo de vida do Reliable Services, é mais importante compreender os eventos básicos de ciclo de vida. A ordenação exata dos eventos depende dos detalhes de configuração.

Em geral, o ciclo de vida do Reliable Services inclui os seguintes eventos:

  • Durante o arranque:
    • Os serviços são construídos.
    • Os serviços têm a oportunidade de construir e devolver zero ou mais serviços de escuta.
    • Todos os serviços de escuta devolvidos são abertos para comunicação com o serviço.
    • O método do runAsync serviço é chamado, pelo que o serviço pode realizar trabalhos em segundo plano ou de execução prolongada.
  • Durante o encerramento:
    • O token de cancelamento que foi transmitido é runAsync cancelado e os serviços de escuta estão fechados.
    • O objeto de serviço em si é estruturado.

A ordem dos eventos no Reliable Services pode mudar ligeiramente consoante o serviço fiável seja sem estado ou com estado.

Além disso, para serviços com estado, tem de abordar o cenário de troca primária. Durante esta sequência, a função primária é transferida para outra réplica (ou volta) sem que o serviço seja encerrado.

Por fim, tem de pensar nas condições de erro ou falha.

Arranque do serviço sem estado

O ciclo de vida de um serviço sem estado é bastante simples. Eis a ordem dos eventos:

  1. O serviço é construído.
  2. StatelessService.createServiceInstanceListeners() é invocado e todos os serviços de escuta devolvidos são abertos. CommunicationListener.openAsync() é chamado a cada serviço de escuta.
  3. Em seguida, em paralelo:
    • O método do runAsync serviço (StatelessService.runAsync()) é chamado.
    • Se estiver presente, o próprio onOpenAsync método do serviço é chamado. Especificamente, StatelessService.onOpenAsync() é chamado. Esta é uma substituição invulgar, mas está disponível.

Encerramento do serviço sem estado

Ao encerrar um serviço sem estado, é seguido o mesmo padrão, mas ao contrário:

  1. Todos os serviços de escuta abertos estão fechados. CommunicationListener.closeAsync() é chamado a cada serviço de escuta.
  2. O token de cancelamento que foi transmitido é runAsync() cancelado. A verificação da propriedade do token de isCancelled cancelamento devolve truee, se for chamado, o método do throwIfCancellationRequested token gera um CancellationException.
  3. Quando runAsync() terminar, o método do StatelessService.onCloseAsync() serviço é chamado, se estiver presente. Mais uma vez, esta não é uma substituição comum, mas pode ser utilizada para fechar recursos de forma segura, parar o processamento em segundo plano, terminar de guardar o estado externo ou fechar as ligações existentes.
  4. Após StatelessService.onCloseAsync() a conclusão, o objeto de serviço é estruturado.

Arranque do serviço com estado

Os serviços com estado têm um padrão semelhante aos serviços sem estado, com algumas alterações. Eis a ordem dos eventos para iniciar um serviço com estado:

  1. O serviço é construído.
  2. StatefulServiceBase.onOpenAsync() é chamado. Esta chamada não é geralmente substituída no serviço.
  3. StatefulServiceBase.createServiceReplicaListeners() é invocado.
    • Se o serviço for um serviço primário, todos os serviços de escuta devolvidos serão abertos. CommunicationListener.openAsync() é chamado a cada serviço de escuta.
    • Se o serviço for um serviço secundário, apenas os serviços de escuta marcados como listenOnSecondary = true estão abertos. Ter serviços de escuta abertos em secundários é menos comum.
  4. Em seguida, em paralelo:
    • Se o serviço for atualmente um principal, o método do StatefulServiceBase.runAsync() serviço é chamado.
    • StatefulServiceBase.onChangeRoleAsync() é chamado. Esta chamada não é geralmente substituída no serviço.

Nota

Para uma nova réplica secundária, StatefulServiceBase.onChangeRoleAsync() é chamada duas vezes. Uma vez após o passo 2, quando se torna uma Secundária Inativa e novamente durante o passo 4, quando se torna uma Secundária Ativa. Para obter mais informações sobre o ciclo de vida da réplica e da instância, leia Ciclo de Vida da Réplica e da Instância.

Encerramento do serviço com estado

Tal como os serviços sem estado, os eventos de ciclo de vida durante o encerramento são os mesmos que durante o arranque, mas invertidos. Quando um serviço com estado está a ser encerrado, ocorrem os seguintes eventos:

  1. Todos os serviços de escuta abertos estão fechados. CommunicationListener.closeAsync() é chamado a cada serviço de escuta.
  2. O token de cancelamento que foi transmitido é runAsync() cancelado. Uma chamada para o método do token de isCancelled() cancelamento devolve truee, se for chamado, o método do throwIfCancellationRequested() token gera um OperationCanceledException. O Service Fabric aguarda pela runAsync() conclusão.

Nota

A aguardar pela runAsync conclusão só é necessária se esta réplica for uma réplica primária.

  1. Após runAsync() a conclusão, o método do StatefulServiceBase.onCloseAsync() serviço é chamado. Esta chamada é uma substituição invulgar, mas está disponível.
  2. Após StatefulServiceBase.onCloseAsync() a conclusão, o objeto de serviço é estruturado.

Trocas primárias de serviço com estado

Enquanto um serviço com estado está em execução, os serviços de comunicação são abertos e o runAsync método é chamado apenas para as réplicas primárias desses serviços com estado. As réplicas secundárias são construídas, mas não vê mais chamadas. Enquanto um serviço com estado está em execução, a réplica que é atualmente a primária pode ser alterada. Os eventos de ciclo de vida que uma réplica com estado pode ver dependem se é a réplica a ser despromoviada ou promovida durante a troca.

Para a primária despromoida

O Service Fabric precisa da réplica primária que é despromoviada para parar o processamento de mensagens e parar qualquer trabalho em segundo plano. Este passo é semelhante ao momento em que o serviço é encerrado. Uma diferença é que o serviço não está desestruído ou fechado, porque permanece como secundário. Ocorrerem os seguintes eventos:

  1. Todos os serviços de escuta abertos estão fechados. CommunicationListener.closeAsync() é chamado a cada serviço de escuta.
  2. O token de cancelamento que foi transmitido é runAsync() cancelado. Uma verificação do método do token de isCancelled() cancelamento devolve true. Se for chamado, o método do throwIfCancellationRequested() token lança um OperationCanceledException. O Service Fabric aguarda pela runAsync() conclusão.
  3. Os serviços de escuta marcados como listenOnSecondary = true são abertos.
  4. O serviço StatefulServiceBase.onChangeRoleAsync() é chamado. Esta chamada não é geralmente substituída no serviço.

Para o secundário promovido

Da mesma forma, o Service Fabric precisa da réplica secundária promovida para começar a escutar mensagens no fio e iniciar quaisquer tarefas em segundo plano que precise de concluir. Este processo é semelhante ao momento em que o serviço é criado. A diferença é que a réplica em si já existe. Ocorrerem os seguintes eventos:

  1. CommunicationListener.closeAsync() é chamado para todos os serviços de escuta abertos (marcados com listenOnSecondary = true)
  2. Todos os serviços de comunicação estão abertos. CommunicationListener.openAsync() é chamado a cada serviço de escuta.
  3. Em seguida, em paralelo:
    • O método do StatefulServiceBase.runAsync() serviço é chamado.
    • StatefulServiceBase.onChangeRoleAsync() é chamado. Esta chamada não é geralmente substituída no serviço.

Nota

createServiceReplicaListeners é chamado apenas uma vez e não é chamado novamente durante o processo de promoção ou despromoção da réplica; as mesmas ServiceReplicaListener instâncias são utilizadas, mas são criadas novas CommunicationListener instâncias (chamando o ServiceReplicaListener.createCommunicationListener método) depois de as instâncias anteriores serem fechadas.

Problemas comuns durante o encerramento do serviço com estado e a despromoção primária

O Service Fabric altera o principal de um serviço com estado por vários motivos. Os motivos mais comuns são o reequilíbrio do cluster e aatualização da aplicação. Durante estas operações, é importante que o serviço respeite o cancellationToken. Isto também se aplica durante o encerramento normal do serviço, como se o serviço tivesse sido eliminado.

Os serviços que não lidam com o cancelamento de forma limpa podem ter vários problemas. Estas operações são lentas porque o Service Fabric aguarda que os serviços parem corretamente. Isto pode, em última análise, levar a atualizações falhadas que excedem o tempo limite e a reversão. O não cumprimento do token de cancelamento também pode causar clusters desequilibrados. Os clusters ficam desequilibrados porque os nós ficam quentes. No entanto, os serviços não podem ser reequilibrados porque demora muito tempo a movê-los para outro local.

Uma vez que os serviços têm estado, é provável que os serviços utilizem Coleções Fiáveis. No Service Fabric, quando uma primária é despromoviada, uma das primeiras coisas que acontece é que o acesso de escrita ao estado subjacente é revogado. Isto leva a um segundo conjunto de problemas que podem afetar o ciclo de vida do serviço. As coleções devolvem exceções com base na temporização e se a réplica está a ser movida ou encerrada. É importante processar estas exceções corretamente.

As exceções emitidas pelo Service Fabric são permanentes (FabricException) ou transitórias (FabricTransientException). As exceções permanentes devem ser registadas e emitidas. As exceções transitórias podem ser repetidas com base na lógica de repetição.

Uma parte importante do teste e validação do Reliable Services é processar as exceções provenientes da utilização em ReliableCollections conjunto com os eventos de ciclo de vida do serviço. Recomendamos que execute sempre o seu serviço sob carga. Também deve realizar atualizações e testes de caos antes de implementar na produção. Estes passos básicos ajudam a garantir que o seu serviço é implementado corretamente e que processa corretamente os eventos de ciclo de vida.

Notas sobre o ciclo de vida do serviço

  • Tanto o runAsync() método como as createServiceInstanceListeners/createServiceReplicaListeners chamadas são opcionais. Um serviço pode ter um, ambos ou nenhum dos dois. Por exemplo, se o serviço fizer todo o seu trabalho em resposta a chamadas de utilizador, não é necessário implementar runAsync(). Apenas os serviços de escuta de comunicação e o respetivo código associado são necessários. Da mesma forma, criar e devolver serviços de escuta de comunicação é opcional. O serviço pode ter apenas trabalho em segundo plano para fazer, pelo que só precisa de implementar runAsync().
  • É válido para um serviço ser concluído runAsync() com êxito e regressar do mesmo. Esta não é considerada uma condição de falha. Representa o trabalho em segundo plano da conclusão do serviço. Para Serviços Fiáveis com estado, runAsync() seria novamente chamado se o serviço fosse despromovido do primário e, em seguida, promovido de volta para o primário.
  • Se um serviço sair de runAsync() ao lançar alguma exceção inesperada, isto é uma falha. O objeto de serviço é encerrado e é comunicado um erro de estado de funcionamento.
  • Embora não exista um limite de tempo para regressar destes métodos, perde imediatamente a capacidade de escrever. Por conseguinte, não pode concluir nenhum trabalho real. Recomendamos que regresse o mais rapidamente possível ao receber o pedido de cancelamento. Se o seu serviço não responder a estas chamadas à API num período de tempo razoável, o Service Fabric poderá terminar o serviço à força. Normalmente, isto só acontece durante as atualizações da aplicação ou quando um serviço está a ser eliminado. Por predefinição, este tempo limite é de 15 minutos.
  • As falhas no onCloseAsync() caminho resultam na onAbort() chamada. Esta chamada é uma oportunidade de última oportunidade e melhor esforço para o serviço limpar e libertar todos os recursos que tenham reclamado. Geralmente, isto é chamado quando é detetada uma falha permanente no nó ou quando o Service Fabric não consegue gerir de forma fiável o ciclo de vida da instância de serviço devido a falhas internas.
  • OnChangeRoleAsync() é chamada quando a réplica de serviço com estado está a mudar de função, por exemplo, para primária ou secundária. As réplicas primárias recebem o estado de escrita (têm permissão para criar e escrever em Reliable Collections). As réplicas secundárias recebem o estado de leitura (só podem ser lidas a partir de Coleções Fiáveis existentes). A maioria do trabalho num serviço com estado é efetuada na réplica primária. As réplicas secundárias podem executar validação só de leitura, geração de relatórios, extração de dados ou outras tarefas só de leitura.

Passos seguintes