A ligação

cuidava do sistema central de e-mail do campus, chamado Isis, na Universidade da Carolina do Norte em Chapel Hill, e também escrevia os arquivos de configuração do sendmail usados na maioria dos servidores de e-mail dos departamentos. Em algum momento entre 1994 e 1997, pelas contas que ele mesmo fez depois, o chefe do departamento de estatística ligou para ele.

O departamento estava com problema para mandar e-mail para fora. Mais exatamente: não conseguia mandar e-mail para mais longe que 500 milhas. Um pouco mais, na verdade. Digamos 520 milhas. Mas não além disso.

Harris respondeu o que qualquer um responderia: e-mail não funciona assim.

Aí veio o detalhe que transforma um chamado absurdo num relato sério. Eles tinham demorado a ligar porque ainda não tinham dados suficientes para ter certeza. Tinham pedido a uma das geoestatísticas do departamento que investigasse, e ela tinha feito um mapa mostrando o raio dentro do qual dava para mandar e-mail: pouco mais de 500 milhas. Dentro do raio havia destinos que eles não alcançavam, ou só alcançavam às vezes. Fora dele, nenhum e-mail chegava, nunca.

Era o departamento de estatística, afinal. Eles tinham feito a análise.

A causa

Harris testou por conta própria, e era verdade.

Algum tempo antes, um consultor tinha "patched the server" (aplicado patches no servidor). Nesse processo, ele atualizou o sistema operacional, o , e com isso fez um downgrade do sendmail, da versão 8 para a versão 5 do SunOS, mas deixou no lugar o arquivo de configuração da versão 8. O sendmail 5 leu uma configuração escrita para uma geração mais nova dele mesmo. Interpretou o que reconheceu. Para as opções que não reconheceu, o binário não tinha valores padrão compilados, e elas ficaram em zero.

Uma das opções que ficaram em zero era o timeout (tempo limite) de conexão com um servidor de e-mail remoto.

Um timeout zero não quer dizer "espere para sempre", nem quer dizer "falhe imediatamente". Naquela máquina específica, com a carga de costume, ele fazia a chamada de conexão ser abortada depois de pouco mais de três milissegundos.

Aí entra a rede do campus. Ela era toda baseada em switches, então um pacote que saía não sofria nenhum atraso de roteador até deixar o ponto de presença () do campus e encontrar um roteador do outro lado. Para um host com pouca carga numa rede próxima, o tempo para estabelecer a conexão dependia, portanto, menos de fila e de processamento e mais da distância que a luz tinha de percorrer.

O relato do próprio Harris mostra o que ele digitou em seguida, e é nesse momento que tudo se esclarece:

$ units
You have: 3 millilightseconds
You want: miles
        * 558.84719

Quinhentas milhas, ou um pouco mais. A conta é a da luz no vácuo, só de ida; perguntado depois se a resposta da conexão não faria disso seis milissegundos, Harris respondeu: "Of course. This is one of the details I skipped in the story" (claro, esse é um dos detalhes que eu deixei de fora da história).

Harris toma cuidado ao contar a história, e quem a reconta deveria fazer o mesmo. Numa nota, ele avisa que a história foi levemente alterada para proteger os culpados, pular detalhes irrelevantes e deixá-la mais divertida. Quando perguntaram depois se aquilo tinha mesmo acontecido, a resposta foi: sim, aconteceu.

Por que é mais do que uma boa história

Acredite no relato que você não consegue explicar. O chefe do departamento descrevia algo que não podia ser verdade, e era. O artigo sobre o Therac-25 mostra a mesma coisa, a um custo muito maior: o sinal mais forte de toda aquela sequência foi uma paciente insistindo que tinha sido queimada por uma máquina que, segundo o fabricante, não podia queimar ninguém. Um relato que contradiz o seu modelo do sistema é uma informação sobre o seu modelo. O instinto de arranjar uma explicação para descartá-lo é justamente o modo de falha.

Um upgrade mudou o sentido de uma configuração sem ninguém perceber. Ninguém colocou o timeout em zero. Um programa mais antigo leu um arquivo mais novo, não entendeu partes dele e preencheu as lacunas com nada, e esse nada, ali, significava três milissegundos. É a falha da Knight Capital em miniatura, e a do Ariane 5 também: um componente que se comporta corretamente diante de entradas escritas para outra versão do mundo. E isso continua totalmente atual. Uma imagem de container cujos defaults mudaram de uma tag para outra, um equipamento que aceita uma configuração antiga e descarta em silêncio as diretivas que não suporta mais, um módulo de infraestrutura em que a variável não definida não fica "sem valor", e sim zero: o mecanismo não envelheceu nada.

O sintoma estava numa camada que ninguém estava olhando. A reclamação era sobre e-mail. O defeito estava num timeout. O padrão visível era geográfico. Nada em "não conseguimos mandar e-mail para Seattle" aponta para um timeout de conexão, e por mais logs de e-mail que alguém lesse na camada de aplicação, não chegaria à resposta. É o argumento que o artigo sobre pontos de captura defende sobre posição: a camada em que um problema aparece raramente é a camada em que ele está.

E latência é distância. É a parte que a gente esquece até ela dar problema, e ela dá problema o tempo todo: numa replicação que funciona entre dois sites, mas não com um terceiro; num timeout de banco de dados que só estoura para a filial; num serviço de voz que funciona bem dentro de um país e fica inutilizável do outro lado de um oceano. A luz na fibra viaja a cerca de dois terços da velocidade da luz no vácuo, e nenhum aumento de banda muda isso. Quando uma falha acompanha um mapa, e não uma configuração, o mapa está dizendo alguma coisa.

Configure seus timeouts. É a última instrução, e a menos glamorosa. Todo timeout que não foi configurado explicitamente acaba definido por alguma coisa: um default que você não leu, um arquivo herdado ou um zero. Saber qual é o valor é o que separa um sistema que degrada de um sistema que se comporta como a física manda.

Fontes