Experimentar um grupo do central no Docker¶
Redundância explica como um grupo do central é construído, e Um grupo do central em servidores separados explica como implantá-lo. Esta página trata de vê-lo funcionar com os próprios olhos: numa única máquina, a partir de contêineres, em dez minutos e sem alugar um único servidor.
O banco é descartável. Nele se pode — e se deve — fazer o que não se faz numa instalação em serviço: matar processos em pleno voo e ver o que sai disso.
O que é necessário¶
- Docker com compose — não há mais nada a instalar.
- Uma chave de licença. Cada processo precisa de uma: os dois central e os dois streamers.
- Uma imagem com o grupo do central. O laboratório precisa de uma compilação cujo console tenha a seção Cluster → Central. Se essa seção não estiver lá, a imagem é anterior ao grupo do central e o banco não se monta.
- As portas 8081 e 8082 livres na máquina local.
De que é feito o banco¶
Cinco contêineres:
- postgres — um banco para todo o grupo.
- central-a e central-b — duas instâncias do plano de controle sobre esse banco, com consoles nas portas 8081 e 8082.
- streamer-1 e streamer-2 — dois streamers divididos entre as instâncias: o primeiro vai ao central-a, o segundo ao central-b.
Dividir os streamers entre instâncias não é enfeite, é o sentido do banco. A imagem do «agora mesmo» é uma só para o grupo, e todo o parque tem de ser visível a partir de qualquer um dos dois endereços, embora as máquinas reportem a instâncias diferentes.
Baixe o docker-compose.yaml para um diretório vazio. Abaixo estão as partes por causa das quais ele foi escrito; o resto é encanamento comum.
A primeira instância declara os quatro papéis, migrate incluído:
central:
admin_keys:
- lab-admin-key
roles: [run, migrate, layouter, stats]
advertise_url: http://central-a
A segunda é a mesma sem migrate: o esquema é aplicado por um único processo, ou dois lançam as migrações em disputa.
central:
admin_keys:
- lab-admin-key
roles: [run, layouter, stats]
advertise_url: http://central-b
Os papéis layouter e stats são declarados pelas duas, e isso não é partida dupla: um papel é uma declaração, e o executor é escolhido por um mandato.
A um streamer não se dá o endereço de uma instância, e sim a lista de endereços do grupo; a ordem é a ordem de preferência:
managed_by:
name: streamer-1
url:
- http://central-a
- http://central-b
join_token: ${JOIN_TOKEN}
O segundo streamer tem a mesma lista em ordem inversa.
Subindo¶
O banco não se monta com um único docker compose up: a janela de adesão é aberta por um central vivo, e o token de adesão só existe depois que ele parte.
Primeiro o banco e as duas instâncias do plano de controle:
export CATENA_VERSION=latest
export LICENSE_KEY='sua chave'
docker compose up -d postgres central-a central-b
Espere o console abrir em http://127.0.0.1:8081 e entre como admin com a senha pass. No primeiro login o console pede para criar uma conta nominal — crie-a.
Abra Cluster → Streamers, clique em Permitir adesão e copie o token de adesão. Suba os streamers com ele:
JOIN_TOKEN=jt-... docker compose up -d streamer-1 streamer-2
As duas máquinas aparecem na lista de streamers em segundos. Feche a janela de adesão depois — o parque está montado.
Crie alguns streams para que o cluster tenha o que alocar. A entrada syntetic é o gerador embutido; o banco não precisa de nenhuma fonte externa:
for i in 1 2 3 4 5 6; do
curl -s -X PUT -H 'Authorization: Bearer lab-admin-key' \
-H 'Content-Type: application/json' \
-d '{"inputs":[{"syntetic":{}}]}' \
"http://127.0.0.1:8081/central/api-v4/streams/configs/cam$i"
done
O grupo inteiro¶
Abra Cluster → Central.

A tabela tem duas linhas — o grupo inteiro — e qualquer instância a mostra igual: o registro está no banco comum.
- Os papéis reivindicados são quase iguais nas duas:
migratesó é declarado pelocentral-a, todo o resto é declarado pelas duas máquinas. - Os mandatos detidos só estão preenchidos numa linha. Essa é a resposta a «quem manda aqui»: ninguém manda, há titulares de mandatos específicos.
- A segunda linha diz nenhum — apenas atende pedidos. Uma instância assim não é reserva nem está dormindo: ela responde por completo ao console, à API e aos streamers; simplesmente não é ela quem faz o trabalho de fundo agora.
No seu banco os mandatos podem ficar de outro jeito — os dois numa máquina ou um em cada. Os mandatos são independentes e o arranjo deles depende de quem chegou primeiro; aqui não existe arranjo errado.
O parque é visível de qualquer endereço¶
Sem sair da instância, abra Cluster → Streamers.

As duas máquinas estão no ar, embora a esta instância apenas uma delas reporte. A outra manda sua sincronização ao vizinho e é vista aqui porque a imagem do «agora mesmo» é uma só para o grupo: uma instância sem o mandato stats chega a ela pela rede, justamente por aquele endereço anunciado.
Abra a mesma página em http://127.0.0.1:8082 e verá o mesmo. É essa a verificação para a qual os streamers estão divididos entre instâncias.
Matamos o titular do mandato¶
Agora aquilo por que o banco é descartável. Mate a instância que tem os mandatos — nas capturas acima é o central-b:
docker compose stop central-b
Volte a Cluster → Central na instância viva e espere alguns segundos.

Três coisas mudaram:
- A linha da instância matada não sumiu, ela está marcada: «em silêncio — o processo provavelmente morreu». O grupo lembra sua composição, não apenas os vivos.
- Os mandatos se mudaram para a instância viva. Ninguém os entregou: um mandato vive numa conexão própria com o PostgreSQL e é liberado com a morte dessa sessão, e o vizinho vem buscar o liberado por conta própria.
- O número da época cresceu. Ele cresce a cada troca de titular e viaja com cada escrita: uma instância que acorda já sem ser a titular recebe uma recusa na escrita, em vez de estragar a alocação depois do fato.
A mudança leva segundos. Não é preciso confirmá-la à mão, nem há com o quê.
O ar não percebeu¶
Abra Streams.

Os seis streams seguem. Metade vive no streamer que reportava à instância matada: ele passou ao segundo endereço da sua lista após uma requisição malsucedida, e o central nem chegou a dá-lo por perdido.
É exatamente por isso que o segundo endereço da lista é obrigatório. Remova-o, repita o experimento e um minuto e meio depois verá o layouter mover streams de uma máquina viva, porque ela deixou de dar sinais de vida.
Devolvemos a instância¶
docker compose start central-b
A linha acende de novo, mas não há mudança de volta — e isso é uma decisão, não algo por terminar.
- Os mandatos ficam na instância viva. Não há nada a ganhar tirando-os: o titular está trabalhando, e uma troca de titular custa uma nova encarnação da imagem do «agora mesmo».
- O streamer fica no endereço para o qual foi. Enquanto esse endereço responder, não há nada a ganhar trocando-o; a ordem da lista é uma preferência de partida, não uma vinculação permanente.
Dá para devolver o arranjo original com um reinício — é para isso que o banco é descartável —, mas em produção não é preciso: o grupo funciona em qualquer arranjo.
Retiramos o banco¶
docker compose down -v
A opção -v retira também os volumes: o banco, o estado dos streamers e a identidade deles no cluster. Sem ela a próxima subida herda um estado meio alheio.
O que este banco não mostra¶
- Uma falha do banco de dados. Aqui ele é único e sem réplica: mate-o e a gestão para por completo enquanto o ar segue. É verdade, mas a redundância do banco é tarefa do próprio banco.
- A rede. Todos os contêineres estão numa mesma rede do docker, sem perdas nem latência entre eles.
- A carga. Seis streams sintéticos não dizem nada sobre como o grupo se comporta num parque real.
- O ponto de entrada do operador. No banco há dois, um por instância; em produção é preciso um único endereço com comutação.