Um broker interrompido e um broker isolado são falhas diferentes. Quando o processo para, ele não atende chamadas. Numa partição de rede, o processo pode continuar executando sem conseguir falar com outros membros do quorum. Um broker em minoria pode aceitar login AMQP enquanto sua fila quorum não progride. Este laboratório amplia o teste de três membros com desconexão e reconexão reais de uma rede bridge do Docker, sem parar o processo RabbitMQ isolado [1][2].
Contrato: cortar comunicação sem encerrar o processo#
Começamos com fila quorum de três membros e evento confirmado real. O laboratório já verifica que dois membros recuperam o evento após parada do nó inicial e que a minoria de um membro não confirma nova publicação. Na nova etapa, segundo e terceiro brokers permanecem ligados, enquanto o primeiro segue parado. Em seguida o terceiro é desconectado da rede bridge. O segundo não consegue mais falar com ele; nenhum forma maioria dos três votantes originais.
A asserção é específica: não ocorrer confirmação positiva de publicação dentro de prazo limitado. Erro ou timeout não comprova que mensagem foi rejeitada ou perdida. O produtor pode precisar repetir o mesmo evento lógico depois da recuperação; a ambiguidade integra a semântica de publisher confirms do RabbitMQ [2].
Verifique identidade do processo antes da separação#
O teste obtém estado Docker `RestartCount` e informação de execução do container que será isolado. Depois desconecta a rede e exige que o mesmo container permaneça em execução e sua contagem de restarts seja idêntica. Isso importa porque trocar silenciosamente por `docker stop` apenas repetiria experimento de falha de nó, não perda de comunicação.
A sequência didática é:
docker inspect --format '{{.State.Running}}' <isolated-node>
docker inspect --format '{{.RestartCount}}' <isolated-node>
docker network disconnect <test-bridge> <isolated-node>
docker inspect --format '{{json .NetworkSettings.Networks}}' <isolated-node>
Os comandos usam placeholders. A implementação reproduzível preenche os nomes efêmeros reais; veja verify_rabbitmq_quorum.py. O script só modifica seu próprio cluster de teste, nunca infraestrutura compartilhada de produção.
Observe quorum com processos ainda vivos#
O teste abre conexão AMQP nova no broker acessível. Login bem-sucedido estabelece acessibilidade do endpoint, não disponibilidade da fila replicada. Em seguida inicia subprocesso para executar uma publicação obrigatória com publisher confirms. O processo possui limite de tempo: uma fila sem maioria pode manter a operação bloqueada. Resposta positiva confirmada durante a minoria causa falha do teste.
A distinção entre resposta negativa e resultado desconhecido é essencial. A tentativa pode ter chegado ao broker local antes do timeout; sua conclusão não pode ser inferida somente pela exceção. O sistema deve manter event ID estável, consumidor idempotente e estratégia de reconciliação ou retentativa, sem tratar timeout como prova de que nada aconteceu [2].
Restaure rede sem substituir servidor#
A recuperação executa `docker network connect` para ligar o mesmo container ainda em execução à bridge original. Informa alias DNS do nó para que os brokers resolvam novamente o nome Erlang e compara estado de execução e reinícios com os valores anteriores [1].
Depois tenta publicar um evento novo com identidade própria até o RabbitMQ confirmar ou ultrapassar deadline. A verificação positiva após reconexão é tão importante quanto a negativa: um cluster definitivamente quebrado também passaria num teste que só exigisse ausência de confirmações.
Modele quorum e presença de processos#
Para fila de três membros, a maioria mínima é dois. Um grupo isolado com apenas um não alcança maioria estrita, mesmo que o processo esteja vivo. Um modelo puro demonstra a diferença:
def pode_formar_maioria(membros, alcançaveis):
if membros < 1 or not (0 <= alcançaveis <= membros):
raise ValueError("composicao invalida")
return alcançaveis >= membros // 2 + 1
assert pode_formar_maioria(3, 3)
assert pode_formar_maioria(3, 2)
assert not pode_formar_maioria(3, 1)
assert not pode_formar_maioria(3, 0)
A função não implementa Raft. Presume votantes fixos e comunicação mútua adequada. Não verifica termo do líder, posição das réplicas ou entrega de confirmação. Por isso há um teste real de broker complementando o modelo estático [3].
O que uma partição real acrescenta#
O teste anterior com nó parado demonstrava resistência à parada do container inteiro. O novo experimento muda a fronteira: processo em execução enquanto desaparecem conexões com pares. É relevante ao risco de split brain e a monitoramento que confunde uptime ou portas abertas com disponibilidade de escrita.
Desligar a conexão bridge ainda é uma interrupção grosseira. Afeta todo tráfego da interface, não apenas portas de distribuição Erlang nem perda assimétrica de pacotes. O script não injeta latência arbitrária, reordena pacotes, replica uma pane de roteamento cloud nem isola hosts independentes. Todos os containers compartilham o mesmo runner.
Segurança de escrita não garante entrega da aplicação#
Publisher confirm significa que broker aceitou mensagem conforme o contrato da fila. Não significa que consumidor externo atualizou estoque, cobrou cartão ou concluiu webhook. Fluxo at-least-once continua exigindo IDs lógicos estáveis e deduplicação por inbox na autoridade do negócio. Partição também pode perder resposta de uma publicação já confirmada; retries podem gerar duplicatas.
Cliente de produção precisa lidar com reconexão, DNS antigo, endpoints alterados, canais perdidos e redelivery. O teste abre conexões AMQP novas; pools de uma aplicação real podem reagir de forma diferente.
Evidências e limites#
| Propriedade | Evidência executada | O que não prova |
|---|---|---|
| Conexão com bridge removida | Inspeção do Docker | Toda falha de rede possível |
| Broker isolado permanece ligado | State e RestartCount | Progresso interno do broker |
| Endpoint AMQP de outro nó responde | Login com cliente novo | Commit de quorum disponível |
| Minoria não confirma | Publicação em subprocesso limitado | Perda definitiva de evento incerto |
| Rede restaurada | Mesmo container reconectado | Roteamento automático de aplicação |
| Maioria publica novamente | Novo publisher confirm | Exactly once no efeito externo |
O resultado do CI vale para a sequência executada. Teste negativo exige asserções fortes: deve verificar que endpoint alvo é acessível e que o cliente tentou a publicação específica na fila quorum, não só que uma porta TCP qualquer estava indisponível.
Exercícios e verificação#
- Por que conexão AMQP saudável com nó em partição minoritária não demonstra que a fila é gravável?
- Meça intervalo entre reconexão da bridge e primeira confirmação positiva. Quais parcelas vêm do cliente?
- Repita com três brokers executando e isole apenas um, deixando a outra dupla com maioria. Preveja qual lado progride.
- Compare bridge desconectada, bloqueio das portas de distribuição Erlang e perda assimétrica de pacotes.
- Explique por que repetir publicação ambígua com event ID novo pode quebrar contrato idempotente.
Capítulos relacionados: Perda de maioria, modelo de partições, inbox transacional e consenso Raft fundamentam garantias [1][2][3].