Neste guia, apresentamos uma visão geral dos recursos de confiabilidade do Pub/Sub.
Por que usar o Pub/Sub?
Como um paradigma de mensagens, o modelo de publicação/assinatura foi projetado para separar os produtores das mensagens dos consumidores delas. Em vez de os produtores enviarem solicitações diretas aos consumidores com os dados, eles publicam esses dados em um serviço do Pub/Sub, como o Pub/Sub. O serviço entrega essas mensagens de forma assíncrona aos consumidores interessados que se inscreveram.
Como resultado, o serviço absorve todas as complexidades de encontrar consumidores interessados nos dados. O serviço também gerencia a taxa em que os consumidores recebem os dados, com base na capacidade deles. A separação permite que os produtores de dados gravem mensagens em grande escala com baixa latência, independentemente do comportamento dos consumidores.
O Pub/Sub oferece entrega de mensagens altamente escalonável e confiável. Embora o serviço lide com grande parte disso automaticamente, você tem controle sobre diferentes aspectos dos editores e assinantes que podem afetar a disponibilidade e o desempenho. O restante deste guia fornece alguns detalhes sobre esses aspectos.
Isolamento
Por padrão, o Pub/Sub é um serviço global: tópicos e assinaturas
não estão inerentemente vinculados a regiões específicas, e as mensagens fluem dentro do
serviço do Pub/Sub entre regiões quando necessário. Ao usar o
endpoint global,
pubsub.googleapis.com, os editores e assinantes se conectam à
região mais próxima da rede em que o Pub/Sub é executado. Ao usar os
endpoints regionais,
como pubsub.us-central1.rep.googleapis.com, ou
endpoints de local,
como us-central1-pubsub.googleapis.com, os editores e assinantes
se conectam ao Pub/Sub na região especificada. Ao executar
editores ou assinantes fora do Google Cloud, é melhor usar
endpoints regionais ou de localização para garantir que as mensagens fluam entre as
regiões esperadas de maneira consistente.
Isolamento regional
Para minimizar a infraestrutura de que as operações de publicação e assinatura dependem fora de uma única região e garantir que todos os dados permaneçam isolados nessa região, siga estas etapas:
Crie um tópico por região.
Embora o namespace do Pub/Sub seja global e não seja possível vincular tópicos e assinaturas a uma região específica, os metadados de todos os recursos são replicados para repositórios de dados locais dentro da região. Portanto, depois de criar um recurso, a configuração dele fica disponível mesmo em caso de problema em outra região. As atualizações nas configurações do tópico ou da assinatura podem não ser propagadas imediatamente em caso de interrupção.
Evite usar endpoints globais.
Em vez disso, use endpoints regionais, quando disponíveis, e endpoints de local, quando os endpoints regionais não estiverem disponíveis. Os endpoints regionais oferecem mais isolamento regional, mas ainda não estão disponíveis em todas as regiões.
Use uma política de armazenamento de mensagens e defina
enforceInTransitcomoTrue.Com a opção Aplicar em trânsito, os dados nunca saem da região, e todos os clientes que se conectam ao tópico em uma região específica definem a política de armazenamento de mensagens para essa região.
Com os tópicos configurados dessa maneira, você tem certeza de que todas as operações de publicação e assinatura gravam e leem dados exclusivamente na região. No caso de falhas do editor, do assinante ou do Pub/Sub em uma única região, a entrega de mensagens é interrompida nessa região. A entrega de mensagens em tópicos e assinaturas de outras regiões não é afetada.
Se você precisar que as operações administrativas e o namespace dos seus tópicos e assinaturas também sejam isolados regionalmente, use o Serviço Gerenciado para Apache Kafka.
Failover
Se você não precisar de isolamento regional, aproveite a capacidade do Pub/Sub de entregar mensagens de maneira eficiente em várias regiões para ter recursos de failover multirregional. O restante desta seção fala sobre como criar tópicos e assinaturas e colocar editores e assinantes para oferecer suporte a diferentes tipos de failover e redundância de dados.
Semântica de failover padrão
Considere um caso em que há um único tópico e uma única assinatura. Os editores estão localizados em regiões dos Estados Unidos e da Austrália, e os assinantes estão localizados nas regiões Google Cloud da Europa e da Austrália. No caso em que todos os assinantes têm capacidade suficiente para receber mensagens, o fluxo de mensagens é assim:
Os Ps representam os publishers, e os Ss representam os assinantes. O hexágono azul representa o serviço do Pub/Sub. Os cilindros representam os locais em que as mensagens são armazenadas (as mensagens são sempre mantidas em várias zonas na região em que são publicadas). O Pub/Sub prefere enviar mensagens na mesma região em que foram publicadas quando os assinantes estão disponíveis. Caso contrário, ele enviará as mensagens para a região mais próxima da rede com assinantes que tenham capacidade. Portanto, como mostrado na imagem anterior, as mensagens publicadas nos Estados Unidos são entregues aos assinantes na Europa, e as mensagens publicadas na Austrália permanecem na Austrália.
As seções a seguir discutem o que acontece em diferentes cenários de falha.
Inscritos na Europa não estão disponíveis
Suponha que os assinantes na Europa tenham sido recusados ou estejam falhando com frequência e não consigam manter uma conexão com o Pub/Sub. Se isso ocorresse, o serviço começaria a entregar mensagens aos assinantes na Austrália:
As assinaturas na Europa e na Austrália estão indisponíveis
Se todos os assinantes estiverem indisponíveis, o Pub/Sub vai armazenar as mensagens até o período de retenção de mensagens configurado.
Quando os assinantes se reconectam, as mensagens são entregues, a menos que a interrupção dure mais do que o período de retenção de mensagens configurado. Por padrão, a retenção de mensagens de assinatura é definida como 7 dias. Também é possível configurar a retenção de mensagens em um tópico por até 31 dias. Não escolha uma duração de retenção de mensagens menor do que a interrupção máxima que você espera ou está disposto a tolerar.
O Pub/Sub não está disponível na Europa
Embora seja raro, talvez você também queira lidar com casos em que o próprio Pub/Sub está indisponível. A indisponibilidade do Pub/Sub se manifesta como períodos prolongados de erros inesperados em solicitações de publicação ou assinatura, ou a incapacidade de entregar mensagens publicadas aos assinantes. Por exemplo, se o Pub/Sub estivesse inativo na região da Europa, o cenário seria muito semelhante ao de quando os assinantes estão inativos:
Nesse caso, os assinantes na Europa não fazem failover para outra região, mesmo que usem o endpoint global. O Pub/Sub intencionalmente não faz failover automático. Imagine que os próprios assinantes estão causando um problema inesperado no Pub/Sub que resulta em indisponibilidade. Esse problema é tratado como uma interrupção grave. No entanto, o escopo do impacto da interrupção pode ser contido na região em que os assinantes se conectaram. Se o serviço permitisse o failover para outra região, os assinantes também poderiam causar indisponibilidade nela, resultando em uma falha em cascata em todo o serviço.
Os editores na Austrália não estão disponíveis
Se os editores em uma região ficarem indisponíveis, as mensagens que já foram publicadas ainda serão entregues aos assinantes mais próximos:
Por fim, todas as mensagens são consumidas e confirmadas pelos assinantes. Ao enviar mensagens, o Pub/Sub tenta minimizar a distância da rede. Portanto, os assinantes na região da Austrália podem parar de receber mensagens se os assinantes na Europa tiverem capacidade suficiente para processar todas as mensagens publicadas nos Estados Unidos.
O Pub/Sub não está disponível nos Estados Unidos
O Pub/Sub grava mensagens de maneira síncrona em várias zonas dentro de uma região. Portanto, uma interrupção zonal não é suficiente para impedir a entrega de mensagens. Toda a região precisa estar indisponível. Se o Pub/Sub ficar indisponível em uma região em que os editores estão enviando mensagens, as mensagens nessa região poderão não ser entregues até que o serviço seja totalmente restaurado:
A mensagem ainda é entregue (supondo que o período de retenção não tenha passado), atrasada pela duração da interrupção. Assim como os assinantes, os publishers nos Estados Unidos também não fazem failover para outra região quando o serviço falha. Esse comportamento ajuda a evitar a probabilidade de falhas em cascata entre regiões devido a um editor ou assinante com falha.
Failover e redundância controlados pelo cliente
A semântica de failover padrão do Pub/Sub pode não garantir totalmente que as mensagens sempre fluam dos editores para os assinantes se houver uma interrupção em qualquer lugar entre eles. As interrupções podem ocorrer em vários lugares diferentes, incluindo seus clientes, no serviço em que os editores ou assinantes são executados, na rede ou até mesmo no próprio Pub/Sub. Se você precisar que seus serviços sejam resilientes a essas interrupções, implemente suas próprias redundâncias. Normalmente, essas redundâncias incluem o uso de várias instâncias de clientes de editor e assinante, em que cada uma usa um endpoint de local diferente.
Talvez você queira resiliência para dois escopos de impacto diferentes: zonal ou regional. Confira as opções de configuração para cada um.
Resiliência zonal
O Pub/Sub tem replicação entre zonas integrada. Não é necessário seguir etapas especiais para lidar com interrupções de zona única que afetam o serviço em si. No entanto, para ter resiliência a interrupções para seus clientes ou rede, é melhor executar editores e assinantes com capacidade suficiente em várias zonas dentro da região. Se uma única zona estiver inativa, os clientes na outra zona poderão receber o tráfego e processar as mensagens. É uma prática recomendada não publicar mudanças nesses clientes simultaneamente para que, se um bug for introduzido, as outras zonas intocadas possam continuar processando mensagens.
Resiliência regional
Para ser resistente a falhas regionais, configure redundâncias adicionais nos editores e assinantes. É possível executar publicadores e assinantes em várias regiões para lidar com a possibilidade de interrupções nesses clientes ou na rede.
Se você quiser ser resiliente contra possíveis falhas do Pub/Sub em uma região, é preciso ter um mecanismo de failover pronto para lidar com essa interrupção. As abordagens possíveis são uma compensação entre a latência de entrega de mensagens de ponta a ponta e o custo.
Para minimizar a latência no caso de o custo não ser uma preocupação, a melhor estratégia é sempre publicar e assinar simultaneamente em diferentes regiões. Primeiro, escolha o número de regiões em que você quer redundância. Em seguida, embora não seja estritamente necessário, é possível configurar um tópico e uma assinatura para cada uma dessas regiões.
Cada editor cria tantos clientes de editor quanto houver regiões (um para cada região) e usa um endpoint de local diferente para garantir que as mensagens sejam direcionadas para regiões distintas. Se você usar tópicos separados, cada cliente editor precisará publicar no tópico correspondente por região. Para cada mensagem, o editor chama publish em cada cliente. Com as publicações redundantes, não é necessário repetir as publicações se alguma delas falhar.
Da mesma forma, cada assinante cria essa quantidade de clientes de assinante, um para cada região, e usa um endpoint de local para se conectar a uma região diferente. Se você usar assinaturas diferentes para cada região, cada cliente assinante precisará usar a assinatura correspondente. As regiões usadas para publishers e assinantes não precisam ser as mesmas. Os assinantes recebem mensagens nas três assinaturas e as processam.
Essa configuração tem vários recursos e requisitos importantes:
- Uma falha em uma única região não afeta o processamento de mensagens já publicadas nem daquelas publicadas durante a falha. Como as mensagens foram publicadas em várias regiões, elas ainda estarão disponíveis em outras regiões caso uma região esteja inativa. Durante a interrupção, as chamadas de publicação falham na região afetada, mas são bem-sucedidas nas outras.
- A latência de processamento de mensagens não é afetada, desde que qualquer uma das regiões pelas quais as mensagens estão fluindo esteja disponível.
- O processamento de mensagens precisa ser idempotente. Como cada mensagem será entregue várias vezes, o processamento de mensagens precisa ser resiliente a duplicatas. No caso de uma interrupção regional, algumas dessas cópias podem chegar muito depois da primeira vez que a mensagem foi entregue. Essas cópias provavelmente vieram de uma região diferente que não estava passando por uma interrupção.
A execução com esse tipo de redundância oferece a maior resiliência a qualquer tipo de interrupção. Para serviços internos do Google que dependem do Pub/Sub e exigem a maior disponibilidade, essa configuração é preferida. No entanto, essa configuração tem a desvantagem de multiplicar o custo de entrega de mensagens pelo número de regiões usadas. Há também o custo adicional do uso da rede inter-regional para mensagens que precisam ser movidas entre regiões.
Outra abordagem para redundância é fazer o failover somente quando as solicitações falharem ou as mensagens não estiverem fluindo dos editores para os assinantes conforme o esperado. Nesse cenário, você tem uma região principal para onde direciona os editores e assinantes usando endpoints de localização. Como antes, elas não precisam ser a mesma região. Você também tem uma região de fallback para publishers e assinantes que é usada quando a região principal está indisponível.
Os editores publicam apenas na região principal (pelo endpoint de local) quando as solicitações são enviadas com sucesso. Sempre que a região é determinada como inativa, os editores começam a publicar na região de fallback. Determinar que a região está inativa e fazer o failover pode ser feito de duas maneiras. Isso pode ser feito por um processo manual, e a configuração é atualizada dinamicamente nos publishers. Os publishers também podem atualizar a configuração por conta própria se a taxa de erro nas solicitações de publicação for alta o suficiente.
Os assinantes precisam sempre se conectar à região principal pelo endpoint de localização. Você pode decidir que o assinante pode usar a região de fallback com um ou mais dos seguintes gatilhos:
- Sempre se inscrever na região de fallback. Nesse caso, o assinante mantém uma conexão com a região principal e a região de fallback o tempo todo. As mesmas regiões podem ser usadas para o principal e o substituto para editores e assinantes. Nesse caso, o assinante só vai receber mensagens pela região de backup se o editor tiver feito o failover.
- Detectar e alternar manualmente os assinantes para a região de fallback por meio de uma configuração. Se você detectar uma interrupção, poderá fazer o failover para a região de fallback e, em seguida, voltar para a região principal quando a interrupção for resolvida.
- Failover em erros de assinante. Se as solicitações do assinante estiverem retornando erros, use isso como uma indicação de que é necessário fazer o failover para a região de fallback. As bibliotecas de cliente do Pub/Sub tentam novamente as solicitações de pull de streaming internamente em erros temporários. Portanto, talvez não seja possível detectar que há longos períodos de erros inesperados. Além disso, a taxa de erro de pull de streaming deve ser de 100%, mesmo durante a operação normal.
- Faça o failover se o assinante passar um tempo inesperadamente longo sem receber mensagens. Supondo que haja uma publicação consistente de mensagens, os assinantes podem sempre receber mensagens. Se eles passarem por um longo período sem receber mensagens, pode haver um problema no lado da assinatura no Pub/Sub na região principal. Isso é corrigido pelo failover para a região de fallback.
De todas as quatro opções, a primeira é a ideal. Uma conexão de assinante não custa dinheiro se não houver mensagens fluindo nela. O único custo é o footprint da instância adicional da biblioteca de cliente do assinante, que pode ser insignificante. Você também precisa estar ciente do número de conexões de pull de streaming abertas por cota de região.
A vantagem desse segundo modelo é que não há um multiplicador no custo do Pub/Sub, já que as mensagens são publicadas apenas uma vez. No entanto, a desvantagem é que, para determinados tipos de interrupções, as mensagens publicadas antes do início da interrupção podem não estar disponíveis até que ela seja resolvida. As mensagens armazenadas na região indisponível podem não ser entregues aos assinantes, independentemente de onde eles estejam conectados. As mensagens publicadas durante a interrupção na região de fallback podem estar disponíveis. Além disso, pode haver um período de indisponibilidade com taxas de erro maiores para os editores ou assinantes. Isso depende do método usado para detectar uma interrupção e do tempo de failover para a região de fallback.
Não importa qual opção você escolha, esteja ciente de como isso pode interagir com os recursos do Pub/Sub. A entrega ordenada e a entrega exatamente uma vez oferecem garantias em uma região. Por exemplo, se você usar a técnica de redundância de failover, a entrega de mensagens só será garantida para mensagens publicadas na mesma região. O assinante pode receber mensagens publicadas na região de fallback antes das mensagens publicadas na região principal, mesmo que as mensagens tenham sido publicadas primeiro na região principal.
Editores de ajuste fino
Não importa qual das opções de failover você escolha, há algumas etapas de ajuste adicionais que você quer realizar nos próprios editores. Ajustar o comportamento do editor garante o desempenho ideal sob alta carga. Agrupar mensagens em lote é uma maneira de trocar latência por um custo reduzido, mas não é uma preocupação de confiabilidade e, portanto, não é abordada aqui. Em vez disso, concentre-se em alguns dos outros parâmetros que são úteis para ajustar a confiabilidade, incluindo configurações de repetição e de controle de fluxo.
As publicações podem falhar por diferentes motivos, incluindo os temporários, como indisponibilidade de rede, ou os que exigem intervenção do usuário, como mudanças de permissão. A biblioteca de cliente do Pub/Sub tenta novamente erros temporários usando os parâmetros especificados nas configurações de nova tentativa. Essas configurações controlam o comportamento da espera exponencial em novas tentativas de RPCs de publicação que falham por motivos temporários. Embora as configurações padrão geralmente funcionem bem na maioria dos cenários, há situações em que você pode querer ajustar esses valores.
As duas propriedades que você provavelmente vai querer ajustar são o tempo limite inicial da RPC e o tempo limite total. O tempo limite inicial da RPC é o tempo que a primeira RPC de publicação tem para ser concluída. Se alguma RPC falhar ou expirar, outra será tentada com um tempo limite maior até que o número total de solicitações ou o tempo limite total seja excedido.
O tempo limite inicial pode ser ajustado se o editor tiver restrições de rede ou estiver longe do data center do Google Cloud mais próximo que executa o Pub/Sub. As restrições de rede podem ser limitações na capacidade de processamento da máquina em que o editor está sendo executado ou podem ser o resultado de outros serviços em execução na mesma máquina que são intensivos em rede. Se o tempo limite for muito curto, as RPCs iniciais poderão falhar repetidamente, resultando em mais tentativas (com tempos limite mais longos) necessárias para a publicação. A necessidade repetida de novas tentativas aumenta a latência de publicação. Nessa situação, aumentar o tempo limite inicial pode resultar em publicações mais rápidas.
Se a conexão de rede não for confiável, aumentar o tempo limite total e o tempo limite inicial pode ajudar. Um tempo limite total maior dá à RPC de publicação mais tempo para ser concluída. Quando as RPCs de publicação falham consistentemente com erros de prazo excedido, considere ajustar esses valores.
Erros contínuos de prazo excedido na publicação também podem indicar a necessidade de ajustar o controle de fluxo do editor. Essas configurações permitem garantir que os editores sejam resilientes a picos de tráfego de entrada que geram mais mensagens a serem enviadas ao Pub/Sub. Um grande aumento nas solicitações de saída pode sobrecarregar a CPU, a memória ou a capacidade de rede do editor. Quando a publicação está sobrecarregada, ela não consegue processar solicitações ou respostas de publicação antes dos tempos limite. Isso resulta em ainda mais solicitações de publicação e, por fim, no tempo limite total. O controle de fluxo do editor limita o número de mensagens ou bytes que podem ficar pendentes sem uma resposta da solicitação de publicação. Limitar o número de solicitações dessa maneira mantém a utilização de recursos em um nível gerenciável, mesmo durante picos. Dependendo de como o editor opera, é possível permitir que as RPCs de publicação subsequentes aguardem a capacidade, permitindo que a publicação bloqueie outras solicitações. Como alternativa, é possível enviar de volta para os autores de chamada do serviço fazendo com que o controle de fluxo retorne um erro quando a capacidade for atingida. Configure como a biblioteca de cliente do editor responde com o comportamento de limite excedido.
Inscritos do ajuste fino
O ajuste do assinante também pode ser necessário para garantir que ele funcione de maneira confiável. Assim como os publishers, é possível ajustar as configurações de controle de fluxo dos assinantes para garantir que eles não fiquem sobrecarregados. A biblioteca de cliente do assinante usa o pull de streaming, em que o cliente abre um stream persistente para o servidor, e o servidor envia mensagens à medida que elas ficam disponíveis. No caso de um grande aumento nas mensagens publicadas, o assinante pode receber mais mensagens do que pode processar. Com o controle de fluxo em vigor, o número de mensagens não confirmadas pendentes para o cliente por vez é limitado. Isso reduz o número de mensagens processadas simultaneamente e distribui o processamento por um período mais longo. Ao distribuir a carga, os assinantes podem ficar abaixo de qualquer limitação de recursos que afete o processamento de mensagens, o que pode resultar em um efeito em cascata que impede o processamento de qualquer mensagem.
O controle de fluxo por si só é suficiente se você espera apenas picos na quantidade de dados a serem processados que, por fim, diminuem. Se o tráfego estiver aumentando ao longo do tempo devido ao maior uso, o controle de fluxo vai proteger os assinantes. No entanto, isso pode resultar em um backlog que continua a se acumular e faz com que as mensagens não possam ser entregues antes que o período de retenção de mensagens termine. Nesses casos, também é possível definir o escalonamento automático para aumentar o número de assinantes em resposta a um número crescente de mensagens não confirmadas. A configuração depende da plataforma de computação que você está usando para os assinantes. Por exemplo, o escalonador automático do Compute Engine permite que você faça o escalonamento com base em métricas como o número de mensagens não entregues. O uso do escalonamento automático e do controle de fluxo garante que os assinantes sejam resilientes a outros picos de curto prazo na capacidade de processamento de mensagens e ao crescimento de longo prazo que exige mais capacidade de computação. Siga as Práticas recomendadas para usar métricas do Pub/Sub como um indicador de escalonamento.
Usar a versão regional das métricas de backlog em vez das versões globais
Ao monitorar o backlog de assinaturas, configurar políticas de alertas ou
escalonar assinantes automaticamente, o Pub/Sub oferece duas versões de cada
métrica de backlog. Use as versões com o sufixo by_region:
Não use as versões globais dessas métricas
(subscription/num_undelivered_messages
e
subscription/oldest_unacked_message_age)
se quiser que o monitoramento, os alertas e o escalonamento automático sejam resilientes a
interrupções em uma única região. As versões globais dessas métricas exigem o cálculo
do backlog em todas as regiões que têm mensagens, o que significa
que a indisponibilidade em uma única região resulta em uma lacuna de dados. Por outro lado, as versões by_region das métricas calculam e informam o backlog por região. Se o backlog não puder ser calculado para uma única região, a
métrica ainda vai informar valores para as outras regiões.
Usar snapshot e busca para implantações seguras
A perda de mensagens geralmente é um evento catastrófico. O Pub/Sub oferece entrega pelo menos uma vez para todas as mensagens publicadas. No entanto, o processamento correto dessas mensagens depende do comportamento do assinante. Se as mensagens forem confirmadas, o Pub/Sub não as reenviará. Portanto, um bug introduzido no novo código de assinante que você implanta e que confirma as mensagens sem processá-las corretamente pode resultar em perda de mensagens induzida pelo assinante. O Pub/Sub oferece o recurso de snapshot e busca, que ajuda a garantir que você processe todas as mensagens corretamente, mesmo diante de bugs de assinantes.
O padrão para cada implantação de assinante precisa ser o seguinte:
O tempo de espera para determinar se o novo assinante está funcionando pode variar de acordo com o caso de uso. A única maneira de sair do fluxo de etapas é quando um assinante é considerado em funcionamento. Nesse momento, o snapshot pode ser excluído.
O uso de snapshot e busca não substitui as práticas recomendadas de executar o software primeiro em um ambiente que não seja de produção e de fazer a implantação gradual na produção. Eles oferecem um nível extra de proteção para garantir o processamento confiável de dados. A desvantagem é que buscar o snapshot pode resultar na entrega duplicada de mensagens que o assinante processou. No entanto, como o Pub/Sub tem semântica de entrega do tipo "pelo menos uma vez" por padrão, seus assinantes já são resilientes à nova entrega de mensagens.