Visão geral da arquitetura do Pub/Sub

O Pub/Sub é um serviço de mensagens assíncrono projetado para ser altamente confiável e escalonável. O serviço é baseado em um componente principal da infraestrutura do Google que muitos dos nossos produtos usam há mais de uma década. Os produtos do Google, incluindo Ads, Pesquisa e Gmail, usam essa infraestrutura para enviar mais de 500 milhões de mensagens por segundo, totalizando 1 TB/s de dados. Este artigo descreve os principais recursos de design que permitem ao Pub/Sub oferecer esse tipo de confiabilidade em escala.

Como julgar o desempenho de um serviço de mensagens

Um serviço de mensagens como o Pub/Sub pode ser julgado pelo desempenho em três aspectos: escalonabilidade, disponibilidade e latência. Esses três fatores geralmente entram em conflito e exigem que se façam concessões em um para melhorar os outros dois.

Os termos "escalonabilidade", "disponibilidade" e "latência" podem se referir a diferentes propriedades de um sistema. Dessa maneira, as seções a seguir descrevem como eles são definidos no Pub/Sub.

Escalonabilidade

Um serviço escalonável precisa ser capaz de lidar com aumentos de carga sem degradação perceptível de latência ou disponibilidade. "Carga" pode se referir a várias dimensões de uso no Pub/Sub:

  • Número de tópicos

  • número de editores

  • número de assinaturas

  • número de assinantes

  • número de mensagens

  • tamanho das mensagens

  • taxa de mensagens (capacidade) publicadas ou consumidas

  • tamanho do backlog de qualquer assinatura

Disponibilidade

Em um sistema distribuído, os tipos e a gravidade dos problemas podem variar muito. A disponibilidade de um sistema é medida por como ele lida com diferentes tipos de problemas realizando um failover de maneira imperceptível pelos usuários finais. Podem ocorrer falhas no hardware, como unidades de disco inoperantes ou problemas de conectividade de rede (links em inglês), e no software, além de problemas por conta da carga. Falhas devidas ao carregamento podem ocorrer quando um aumento súbito no tráfego do serviço ou em outros componentes de software em execução no mesmo hardware ou nas dependências do software resulta na escassez de recursos. A disponibilidade também pode ser afetada devido a erro humano, quando alguém cometer algum erro na criação ou implantação do software ou nas configurações.

Latência

Latência é uma medida de desempenho de um sistema baseada no tempo. Geralmente, deve-se minimizar a latência sempre que possível. Para o Pub/Sub, as duas métricas de latência mais importantes são:

  1. a quantidade de tempo que ele leva para reconhecer uma mensagem publicada;

  2. a quantidade de tempo que ele leva para entregar uma mensagem publicada para um assinante.

Arquitetura básica do Pub/Sub

Esta seção explica o design do Pub/Sub para mostrar como o serviço alcança a escalonabilidade e a baixa latência, mantendo a disponibilidade. O sistema foi projetado para ser horizontalmente escalonável. Isso significa que um aumento no número de tópicos, assinaturas ou mensagens pode ser resolvido com o aumento do número de instâncias de servidores em execução.

Os servidores do Pub/Sub são executados em todas as regiões do Google Cloud no mundo todo. Isso permite que o serviço ofereça acesso rápido e global a dados e que os usuários controlem o local em que as mensagens são armazenadas. O Cloud Pub/Sub oferece acesso global aos dados nesse editor e os clientes do assinante não estão cientes da localização dos servidores aos quais eles se conectam ou de como esses serviços roteiam os dados.

Os mecanismos de balanceamento de carga do Pub/Sub direcionam o tráfego do editor para o data center do Google Cloud mais próximo em que o armazenamento de dados é permitido, conforme definido na seção Restrição de local de recursos do console "IAM e Admin". Isso significa que os editores em várias regiões podem publicar mensagens em um único tópico com baixa latência. Qualquer mensagem individual é armazenada em uma única região. No entanto, um tópico pode ter mensagens armazenadas em várias regiões. Quando um cliente do assinante solicita mensagens publicadas neste tópico, ele se conecta ao servidor mais próximo que agrega dados de todas as mensagens publicadas no tópico para entrega ao cliente.

O Pub/Sub está dividido em duas partes principais: o plano de dados, que gerencia a movimentação de mensagens entre editores e assinantes, e o plano de controle, que gerencia a atribuição de editores e assinantes a servidores no plano de dados. Os servidores do plano de dados são chamados de encaminhadores, e os do plano de controle são chamados de roteadores. Quando editores e assinantes se conectam aos encaminhadores atribuídos a eles, nenhuma informação dos roteadores é necessária, desde que os encaminhadores permaneçam acessíveis. Portanto, é possível fazer upgrade do plano de controle do Pub/Sub sem afetar qualquer cliente já conectado e que já consegue receber ou enviar mensagens.

Plano de controle

O plano de controle do Pub/Sub distribui os clientes aos encaminhadores de modo a oferecer escalonabilidade, disponibilidade e baixa latência para todos os clientes. Qualquer encaminhador pode atender a clientes de qualquer tópico ou assinatura. Quando um cliente se conecta ao Pub/Sub, o roteador decide a quais data centers o cliente se conecta com base na menor distância de rede, uma medida da latência na conexão entre dois pontos. Em qualquer data center, o roteador tenta distribuir a carga geral pelo conjunto de encaminhadores disponíveis. O roteador precisa equilibrar duas metas diferentes ao realizar essa atribuição: (a) a uniformidade da carga (idealmente, todo encaminhador recebe a mesma carga) e (b) a estabilidade das atribuições (idealmente, uma alteração na carga ou no conjunto de encaminhadores disponíveis muda o menor número possível de atribuições existentes). O roteador usa uma variante do hash consistente desenvolvido pelo Google Research (links em inglês) para alcançar um equilíbrio ajustável entre consistência e uniformidade. O roteador fornece ao cliente uma lista ordenada de encaminhadores aos quais ele pode se conectar. Essa lista ordenada pode variar com base na disponibilidade do encaminhador e no formato da carga do cliente.

Um cliente recebe essa lista de encaminhadores e se conecta a um ou mais deles. Ele prefere se conectar aos encaminhadores mais recomendados pelo roteador, mas também considera qualquer falha ocorrida. Por exemplo, ele poderá testar encaminhadores de um data center diferente se várias tentativas de se conectar ao data center mais próximo tiverem falhado. Para abstrair os clientes do Pub/Sub desses detalhes de implementação, há um proxy de serviço entre os clientes e os encaminhadores que realiza essa otimização de conexão em nome dos clientes.

Plano de dados: a vida de uma mensagem

O plano de dados recebe as mensagens dos editores e as envia aos clientes. Talvez a melhor maneira de entender o plano de dados do Pub/Sub seja observar a vida de uma mensagem, desde o momento em que ela é recebida pelo serviço até o momento em que não está mais presente no serviço. Vamos rastrear as etapas do processamento de uma mensagem. Nesta seção, vamos supor que o tópico em que a mensagem foi publicada tenha pelo menos uma assinatura. Em geral, uma mensagem passa por estas etapas:

  1. Um editor envia a mensagem.

  2. A mensagem é gravada no armazenamento.

  3. O Pub/Sub envia uma confirmação ao editor de que recebeu a mensagem e garante a entrega dela a todos os assinantes anexados.

  4. Ao mesmo tempo que a mensagem é gravada no armazenamento, o Pub/Sub a entrega aos assinantes.

  5. Os assinantes enviam uma confirmação ao Pub/Sub de que processaram a mensagem.

  6. Assim que ao menos um assinante de cada assinatura reconhecer a mensagem, o Pub/Sub excluirá a mensagem do armazenamento.

Primeiro, um editor envia uma mensagem sobre um tópico para o Pub/Sub. Ela é criptografada pela camada do proxy e enviada para um encaminhador de publicação ao qual o editor está conectado. Para garantir a entrega, a mensagem é gravada imediatamente no armazenamento. O encaminhador inicialmente grava a mensagem em N clusters, em que N é um número ímpar, e considera que mensagem foi salva quando ela tiver sido gravada em pelo menos ⌈N/2⌉ clusters. Se uma mensagem for mantida, o encaminhador de publicação confirma ao editor que recebeu a mensagem. Nesse ponto, o Pub/Sub garante que a mensagem será entregue a todas as assinaturas anexadas.

Em cada cluster, a mensagem é gravada em M discos independentes, em que M é um número ímpar. Os dados precisam ser gravados em ⌈M/2⌉ discos para que a mensagem seja considerada persistente no cluster. No total, qualquer mensagem publicada será gravada em pelo menos ⌈M/2⌉ discos independentes em ⌈N/2⌉ clusters para que seja considerada persistente e seja replicada para N*M discos.

O encaminhador de publicação tem uma lista de todas as assinaturas vinculadas a um tópico. Ele é responsável pela persistência das mensagens publicadas e dos metadados que descrevem quais mensagens foram confirmadas por assinatura. O conjunto de mensagens recebidas e armazenadas por um encaminhador de publicação de um tópico específico e esse rastreamento de mensagens confirmadas é chamado de "origem das mensagens publicadas". Dependendo dos requisitos de capacidade do tópico, um único editor pode enviar mensagens a vários encaminhadores de publicação e armazenar mensagens em várias origens de mensagens publicadas. Diferentes editores do mesmo tópico também podem enviar mensagens para diferentes encaminhadores de publicação. Cada mensagem é enviada para apenas um encaminhador de publicação. O Pub/Sub ajusta dinamicamente o número de encaminhadores de publicação que recebem mensagens para um tópico específico conforme a capacidade é alterada.

Os assinantes recebem mensagens ao se conectarem com encaminhadores de assinatura, e a partir deles as mensagens são transmitidas dos editores para os assinantes. No caso de um assinante de pull, "conexão" significa o envio de uma solicitação pull. No caso de um assinante de push, "conexão" significa ter o ponto de extremidade de push registrado junto ao Pub/Sub. Quando uma assinatura é criada, há a garantia de que todas as mensagens publicadas após esse momento serão entregues a essa assinatura. Chamamos isso de garantia de ponto de sincronização.

Cada encaminhador de assinatura precisa solicitar mensagens dos encaminhadores de publicação que têm origens de mensagens publicadas para o tópico. Como os editores, os assinantes podem se conectar a mais de um encaminhador de assinatura para receber mensagens. Dessa maneira, nem todos os encaminhadores de assinantes precisam estar cientes ou receber mensagens de todas as fontes de publicação de um tópico, uma propriedade importante para que o Pub/Sub possa ser escalonado horizontalmente. Com base na capacidade das mensagens entregues aos assinantes, o Pub/Sub ajusta dinamicamente o número de encaminhadores de assinantes pelos quais os assinantes recebem mensagens de um tópico específico conforme a capacidade é alterada.

Um encaminhador de assinatura solicita as mensagens de que precisa para encaminhadores de publicação que têm origens de mensagens publicadas para um tópico. O encaminhador de publicação envia as mensagens não confirmadas para o encaminhador de assinatura, que então as envia para um assinante.

Quando um assinante processa a mensagem, ele envia uma confirmação para o encaminhador de assinatura. O encaminhador de assinatura transmite essa confirmação para o encaminhador de publicação, que a armazena na origem de mensagens publicadas. Quando todas as assinaturas de um tópico confirmarem o recebimento da mensagem, ela será excluída de modo assíncrono da origem de mensagens publicadas e do armazenamento.

Mensagens diferentes para um único tópico e assinatura podem fluir por vários editores, assinantes, encaminhadores de edição e encaminhadores de assinatura. Os editores podem publicar simultaneamente em vários encaminhadores, e os assinantes podem se conectar a vários encaminhadores de assinatura para receber mensagens. Portanto, o fluxo de mensagens por meio de conexões entre editores, assinantes e encaminhadores pode ser complexo. O diagrama a seguir mostra como as mensagens podem fluir para um único tópico e assinatura, em que cores diferentes indicam os diferentes caminhos que as mensagens podem seguir dos editores para os assinantes:

Mensagens de vários editores são enviadas aos assinantes por meio de encaminhadores de publicação e assinatura.

Como manter o Pub/Sub em funcionamento

Garantir o funcionamento de um sistema distribuído como o Pub/Sub de modo que ele atenda efetivamente a todos os clientes exige grande visibilidade e controle do sistema. Manter o serviço é responsabilidade dos nossos engenheiros de confiabilidade do site (SREs, na sigla em inglês). Para o Pub/Sub, esses engenheiros estão sediados em vários locais ao redor do mundo para fornecer cobertura 24 horas.

Ambientes

A primeira parte da manutenção de um sistema como o Pub/Sub é conseguir testar o software antes que ele seja usado pelos clientes. Para que isso seja possível, há três ambientes do Pub/Sub: teste, preparo e produção. Os ambientes de teste e preparo não têm tráfego de clientes. Eles abrangem apenas os testes e monitoramentos contínuos que ajudam a encontrar problemas nos lançamentos. Esses ambientes recebem novas versões de software antes da produção. A diferença entre teste e montagem é que este último é uma réplica exata do que está ou estará no ambiente de produção, inclusive a versão do software e as sinalizações de linha de comando. O primeiro pode ter recursos nos quais os desenvolvedores estão trabalhando e que planejam lançar no futuro.

Implementação

O procedimento de implementação e teste do Pub/Sub foi projetado para minimizar o impacto em potencial. Veja as etapas típicas da implementação de uma nova versão do Pub/Sub:

  1. Garantir a aprovação de todos os testes de unidade e integração.

  2. Criar uma nova versão de todos os servidores.

  3. Implantar os novos servidores nos ambientes de teste e montagem.

  4. Executar os servidores nos ambientes de teste e montagem por alguns dias.

  5. Caso não haja problemas conhecidos, lançar os servidores no Canary, um subconjunto do ambiente de produção que tem uma quantidade pequena de tráfego de clientes.

  6. Se nenhum problema for detectado no canário, implementar progressivamente os servidores em mais ambientes de produção durante vários dias até serem lançados em todo o sistema.

Como o Pub/Sub foi projetado para ser resistente a falhas, por exemplo, por meio da separação dos planos de controle e de dados, a implementação de novos servidores não interrompe o serviço dos clientes e não afeta o desempenho.

Monitoramento

A chave para manter o Pub/Sub em funcionamento é detectar e mitigar problemas automaticamente antes que eles se tornem visíveis para os usuários finais. Isso exige um monitoramento amplo do sistema. A equipe de engenharia de confiabilidade do site (SREs) mantém um conjunto de indicadores de nível de serviço (SLIs, na sigla em inglês), métricas bem definidas que descrevem o comportamento do sistema. As métricas podem incluir "tempo para a conclusão de uma solicitação CreateSubscription" ou "taxa de erros gerados por solicitações de publicação". Essas métricas são medidas de diversas maneiras. Algumas são estritamente internas aos nossos encaminhadores e roteadores. Por exemplo, elas medem o tempo para gravar mensagens no disco.

Todas essas medidas ajudam a definir objetivos de nível de serviço (SLOs) internos, metas específicas para os SLIs. Por exemplo, "uma solicitação CreateSubscription não deve levar mais de cinco segundos para ser concluída". Os SREs são alertados sobre violações de SLO e precisam atender aos alertas em até cinco minutos.

Um contrato de nível de serviço (SLA, na sigla em inglês) lista os SLOs que definem nossas garantias de desempenho para os usuários finais e as consequências do não cumprimento delas. Leia o SLA do Pub/Sub.

Mantemos um conjunto de clientes que publicam e se inscrevem de forma previsível. Eles são chamados de sondas. Há sondas nos planos de dados e de controle. Cada uma das nossas sondas realiza ações específicas como um cliente faria e mede a duração das operações. Por exemplo, temos uma sonda que cria uma nova assinatura, publica uma mensagem e analisa quanto tempo demora para criar a assinatura e receber a mensagem. Se as sondas determinarem que qualquer uma das métricas medidas não mostra o resultado esperado, os SREs são avisados.

As métricas dos nossos servidores e sondas são resumidas em vários painéis internos, o primeiro lugar que um SRE consulta para diagnosticar possíveis problemas. Essas páginas oferecem acesso rápido a estatísticas e gráficos de todo o serviço. Elas também podem ser divididas por tópico, data center ou tarefa individual.

As métricas mais interessantes para os usuários do serviço são mostradas pelo Google Cloud Monitoring.

Controles

Temos à nossa disposição vários controles para ajustar o desempenho do Pub/Sub. Alguns desses controles foram projetados para ajudar no caso de falhas de data centers ou máquinas. Podemos aplicar restrições de roteamento em alguns ou todos os tópicos, que são regras que especificam conjuntos de clientes que podem ou não se conectar a conjuntos de encaminhadores. Usamos as restrições de roteamento para drenar o tráfego para longe de tarefas de encaminhadores individuais ou data centers inteiros que não estão operando conforme o esperado.

Outro recurso ajustável é o controle de fluxo. Esse recurso nos permite maximizar a capacidade ao mesmo tempo em que evitamos a sobrecarga do serviço. O controle de fluxo é um tipo de delimitação de tráfego em que picos súbitos e inesperados no carregamento podem ser suavizados ao longo do tempo para maior estabilidade do serviço. O controle de fluxo opera no sistema inteiro por tópico ou por assinante para limitar o número de mensagens ou o número de bytes transferidos ou pendentes. Nesse caso, "pendente" significa entregue ao cliente, mas ainda sem confirmação. O controle de fluxo e as restrições de roteamento nos permitem otimizar o desempenho do Pub/Sub sem que os clientes precisem se preocupar com esses detalhes de baixo nível.

Resumo

As vantagens em escalonabilidade, disponibilidade e latência de um serviço como o Pub/Sub definem a proposta de valor para clientes que estão pensando em migrar para serviços de nuvem gerenciados. Qualquer serviço de mensagens assíncronas precisa ser criado a partir do zero com essas características em mente. Com mais de uma década de experiência na entrega confiável de muitas mensagens rapidamente, a equipe do Pub/Sub criou e mantém um serviço capaz de acompanhar as demandas da maioria dos produtos fundamentais do Google. Agora, esse mesmo serviço está disponível para todos os clientes externos que desejam enviar mensagens para o mundo inteiro sem se preocupar se o sistema de mensagens pode suportar uma carga 2, 10 ou 100 vezes maior que a carga atual.

Glossário

Termo Descrição
cluster Um agrupamento lógico de máquinas que geralmente compartilham o mesmo domínio de falha como, por exemplo, rede local compartilhada e fonte de energia compartilhada.
plano de controle A camada do Pub/Sub que lida com a atribuição de editores e assinantes aos servidores do plano de dados.
plano de dados A camada do Pub/Sub que lida com a transmissão de mensagens entre editores e assinantes.
encaminhador Um servidor no plano de dados.
acesso global a dados O editor do Pub/Sub e os clientes do assinante não estão cientes da localização dos dados. O roteamento e o armazenamento são feitos pelo próprio serviço, de acordo com a política de restrição de local.
horizontalmente escalonável A capacidade de lidar com mais carga sem interrupções com o aumento do número de instâncias dos componentes do serviço.
mensagem Os dados transferidos pelo Pub/Sub.
distância de rede Uma medida da latência da conexão entre dois pontos.
sonda Uma tarefa que atua como um cliente e, de maneira previsível, realiza uma ou mais ações nos servidores do Pub/Sub.
origem de mensagens publicadas Um conjunto de mensagens recebidas e armazenadas por um encaminhador de publicação e o conjunto dos códigos das mensagens confirmadas por todas as assinaturas vinculadas.
serviço de publicação/assinatura (Pub/Sub) Um serviço de mensagens em que os remetentes são separados dos destinatários das mensagens.
editor Um cliente do Pub/Sub que cria mensagens e as envia ou publica em um tópico específico.
roteador Um servidor no plano de controle.
restrições de roteamento Uma lista de regras que indicam quais encaminhadores podem ou não ser enviados pelos roteadores aos clientes como possíveis terminais para conexão.
contrato de nível de serviço (SLA) Uma lista de SLOs que definem as garantias de desempenho do sistema aos clientes e descreve as consequências caso elas não sejam atendidas.
indicador de nível de serviço (SLI) Uma métrica bem-definida que descreve o comportamento do sistema.
objetivo de nível de serviço (SLO) Uma meta específica para um indicador de nível de serviço.
assinante Um cliente do Pub/Sub que recebe mensagens de uma assinatura específica.
assinatura Uma entidade nomeada que representa um interesse em receber todas as mensagens sobre um tópico específico.
garantia de ponto de sincronização O momento em que uma assinatura é criada, o que significa que todas as mensagens publicadas subsequentemente serão enviadas aos assinantes.
tópico Uma entidade nomeada que representa um feed de mensagens.