
Este é um segundo artigo de uma série "Citymobil - um manual para melhorar a disponibilidade em meio ao crescimento dos negócios para startups". Você pode ler a primeira parte
aqui . Vamos continuar falando sobre a maneira como conseguimos melhorar a disponibilidade dos serviços Citymobil. No primeiro artigo, aprendemos a contar as viagens perdidas. Ok, estamos contando eles. E agora? Agora que estamos equipados com uma ferramenta compreensível para medir as viagens perdidas, podemos passar para a parte mais interessante - como diminuímos as perdas? Sem abrandar o nosso crescimento atual! Como nos pareceu que a maior parte dos problemas técnicos que causavam a perda de viagens tinha algo a ver com o back-end, decidimos voltar nossa atenção para o processo de desenvolvimento do back-end. Pulando à minha frente, vou dizer que estávamos certos - o back-end se tornou o principal local da batalha pelas viagens perdidas.
1. Como o processo de desenvolvimento funciona
Os problemas geralmente são causados pela implantação do código e outras ações manuais. Os serviços que nunca são alterados e tocados manualmente às vezes também apresentam mau funcionamento; no entanto, essa é uma exceção que apenas prova a regra.
Na minha experiência, a exceção mais interessante e incomum foi a seguinte. Em 2006, quando eu trabalhava em um dos pequenos serviços de webmail, havia um gateway que fazia proxy de todo o tráfego e fazia com que os endereços IP não estivessem nas listas negras. O serviço funcionou no FreeBSD e funcionou bem. Mas um dia simplesmente parou de funcionar. Adivinha por que? O disco nesta máquina falhou (blocos ruins estavam se formando há algum tempo e o inevitável aconteceu) e aconteceu três anos antes da falha do serviço. Tudo estava vivo com o disco com falha. E então o FreeBSD, por razões conhecidas apenas por si mesmo, decidiu repentinamente resolver o disco que falhou e parou como resultado.
Quando eu era criança, de 10 a 12 anos, fui caminhar na floresta com meu pai e ouvi uma frase dele que nunca esqueci: "tudo o que você precisa fazer para manter a fogueira acesa é não tocá-la". Acredito que a maioria de nós consegue se lembrar de uma situação em que alimentamos um pouco de lenha com o fogo já aceso e ele se apagou sem motivo.
A conclusão é que os problemas são criados pelas ações manuais dos seres humanos; por exemplo, quando você alimenta a madeira para a fogueira que já está queimando, cortando o oxigênio e matando o fogo ou implantando o código com bugs na produção. Portanto, para entender o que causa os problemas de serviços, precisamos entender como o processo de implantação e desenvolvimento funciona.
No Citymobil, o processo foi totalmente orientado para o desenvolvimento rápido e organizado da seguinte maneira:
- 20 a 30 lançamentos por dia.
- Os desenvolvedores realizam a implantação sozinhos.
- Teste rápido no ambiente de teste pelo desenvolvedor.
- Testes mínimos automatizados / de unidade, revisão mínima.
Os desenvolvedores trabalharam em condições difíceis, sem suporte ao controle de qualidade, com um enorme fluxo de tarefas muito importantes da equipe de produto e experimentos; eles trabalharam da maneira mais intensa e consistente possível, resolveram tarefas difíceis de uma maneira simples, certificaram-se de que o código não se transformasse em espaguete, entenderam as problemáticas dos negócios, trataram as alterações com responsabilidade e revertem rapidamente o que não funcionava. Não há nada novo aqui. Houve uma situação semelhante no serviço Mail.Ru há 8 anos, quando comecei a trabalhar lá. Iniciamos o
Mail.ru Cloud de maneira rápida e fácil, sem prelúdio. Estaríamos mudando nosso processo no caminho para obter melhor disponibilidade.
Aposto que você percebeu isso sozinho: quando não há restrições, quando é apenas você e a produção, quando você carrega um fardo pesado de responsabilidade - está fazendo maravilhas. Eu tive uma experiência assim. Há muito tempo, eu era praticamente o único desenvolvedor no serviço de webmail Newmail.Ru (foi adquirido há um tempo atrás e depois retirado); Realizei a implantação sozinho e realizei os testes de produção também via
if (!strcmp(username, "danikin")) { … some code… }
. Então, eu estava familiarizado com esta situação.
Não ficaria surpreso ao descobrir que essa abordagem "rápida e suja" foi utilizada por muitas startups, tanto bem-sucedidas quanto não, mas todas motivadas por uma paixão - desejo de crescimento rápido dos negócios e participação de mercado.
Por que a Citymobil teve esse processo? Havia muito poucos desenvolvedores para começar. Eles trabalhavam para a empresa há um tempo e conheciam muito bem o código e os negócios. O processo funcionou idealmente nessas condições.
2. Por que a ameaça de disponibilidade surgiu?
O crescimento dos investimentos em desenvolvimento de produtos fez com que nossos planos de produtos se tornassem mais agressivos e começamos a contratar mais desenvolvedores. O número de implementações por dia estava aumentando, mas naturalmente sua qualidade diminuiu, pois os novos funcionários tiveram que mergulhar no sistema e nos negócios em condições de campo. O aumento no número de desenvolvedores resultou em não apenas linear, mas em uma queda quadrática na disponibilidade (o número de implantações estava crescendo linearmente e a qualidade de uma implantação média estava diminuindo linearmente, portanto, "linear" * "linear" = "quadrático").
Obviamente, não podíamos continuar assim. O processo simplesmente não foi construído para essas novas condições. No entanto, tivemos que modificá-lo sem comprometer o tempo de comercialização; ou seja, mantendo de 20 a 30 lançamentos por dia (considerando que o número aumentaria à medida que a equipe crescesse). Estávamos crescendo rapidamente, realizamos muitos experimentos, avaliamos prontamente os resultados e realizamos novos experimentos. Testamos rapidamente hipóteses de produtos e negócios, aprendemos com elas e criamos novas hipóteses que prontamente testamos novamente e assim por diante. Sob nenhuma circunstância desaceleraríamos. Além disso, queríamos acelerar e contratar desenvolvedores mais rapidamente. Portanto, nossas ações voltadas para o crescimento dos negócios criaram uma ameaça à disponibilidade, mas não tínhamos absolutamente nenhuma intenção de modificar essas ações.
3. Ok, a tarefa está definida, o processo é claro. O que vem a seguir?
Ter uma experiência de trabalho no serviço de email Mail.Ru e no Mail.Ru Cloud, em que a disponibilidade em algum momento havia se tornado a prioridade número um, onde as implantações aconteciam uma vez por semana, onde tudo era coberto por testes automatizados e de unidade, e o código foi revisado pelo menos uma vez, mas às vezes até três vezes, eu enfrentava uma situação totalmente diferente.
Você pensaria que tudo era bem simples: poderíamos replicar o processo de email / nuvem Mail.Ru no Citymobil, aumentando assim a disponibilidade do serviço. No entanto, como eles dizem - o diabo está nos detalhes:
- as implantações no email / cloud Mail.Ru são realizadas uma vez por semana, não 30 vezes por dia; na Citymobil, não queríamos sacrificar a quantidade de lançamentos;
- no e-mail / nuvem Mail.Ru, o código é coberto pelo teste automático / unitário e não tivemos tempo nem recursos para isso na Citymobil; lançamos todo o nosso esforço de desenvolvimento de back-end em hipóteses e testes de melhoria de produto.
Dito isso, fomos contratados em termos de desenvolvedores de back-end, apesar de serem contratados rapidamente (um agradecimento especial aos recrutadores da Citymobil - os melhores recrutadores do mundo! Acho que haverá um artigo separado sobre nosso processo de recrutamento) , então não havia como resolver problemas de teste e revisão sem diminuir a velocidade.
4. Quando você não sabe o que fazer, aprenda com os erros
Então, o que é tão mágico que fizemos na Citymobil? Decidimos aprender com os erros. O método de melhoria do serviço Aprenda com os Erros é tão antigo quanto o tempo. Se o sistema funcionar bem, é bom. Se o sistema não funcionar bem, também é bom, pois podemos aprender com os erros. Mais fácil dizer do que ... Na verdade, isso também pode ser feito facilmente. A chave é definir uma meta.
Como aprendemos? Primeiro, começamos a escrever religiosamente as informações de todas as interrupções, grandes e pequenas. Para ser sincero, realmente não senti vontade de fazer isso, pois esperava um milagre e pensei que as interrupções parariam sozinhas. Obviamente, nada estava parando. A nova realidade impiedosamente exigiu algumas mudanças.
Começamos a registrar todas as interrupções em uma tabela do Google Docs. Para cada interrupção, havia as seguintes informações breves:
- data, hora, duração;
- a causa raiz;
- o que foi feito para corrigir o problema;
- impacto nos negócios (número de viagens perdidas, outros resultados);
- takeaways.
Para cada grande interrupção, criaríamos um arquivo grande separado com descrição detalhada a cada minuto, desde o momento em que a interrupção começou até o momento em que terminou: o que fizemos, que decisões foram tomadas. Geralmente é chamado de post-mortem. Nós adicionaríamos os links para esses post-mortems na tabela geral.
Havia uma razão para criar esse arquivo: chegar a conclusões que visassem diminuir o número de viagens perdidas. Era muito importante ser muito específico sobre o que é "a causa raiz" e o que são "os tópicos". O significado dessas palavras é claro; no entanto, todos podem entendê-los de maneira diferente.
5. Exemplo de uma interrupção que aprendemos com
A causa raiz é um problema que precisa ser corrigido para evitar esses acidentes no futuro. E conclusões - as maneiras de eliminar a causa raiz ou reduzir a probabilidade de seu ressurgimento.
A causa raiz é sempre mais profunda do que parece ser. Os tópicos são sempre mais complicados do que parecem ser. Você nunca deve estar satisfeito com a causa raiz supostamente encontrada e nunca com as declarações alegadas, para não relaxar e parar no que parece certo. Essa insatisfação cria uma faísca para uma análise mais aprofundada.
Deixe-me dar um exemplo do mundo real: implantamos código, tudo caiu, revertemos, tudo estava funcionando novamente. Qual é a causa raiz do problema? Você diria:
Implantação. Se você não tivesse implantado o código, não haveria um acidente. Então, qual é o objetivo: não há mais implantações? Essa não é uma proposta muito boa. Então, provavelmente, essa não foi a causa raiz, precisamos cavar mais fundo.
Implantação com um bug. Essa é a causa raiz? Tudo bem. Como consertamos isso? Você diria testando. Que tipo de teste? Por exemplo - teste de regressão completo de todas as funcionalidades. Esta é uma boa ideia, vamos lembrar. Mas precisamos aumentar a disponibilidade aqui e agora antes de implementar o teste de regressão completo. Precisamos cavar ainda mais fundo.
Implantação com um bug causado pela impressão de depuração na tabela do banco de dados; sobrecarregamos o banco de dados e ele caiu sob a carga. Isso soa melhor. Agora ficou claro que nem mesmo o teste de regressão completo nos salvará desse problema. Como não haverá carga de trabalho no banco de dados de teste semelhante à carga de trabalho de produção.
Qual é a causa raiz desse problema, se aprofundarmos ainda mais? Tivemos que conversar com engenheiros para descobrir isso. Acabou que o engenheiro se acostumou ao banco de dados, capaz de lidar com qualquer carga de trabalho. No entanto, devido ao rápido crescimento da carga de trabalho, o banco de dados não podia naquele momento lidar com o que tratava no dia anterior. Poucos de nós tiveram a chance de trabalhar nos projetos com uma taxa de crescimento de 50% mensalmente. Para mim, por exemplo, esse foi o primeiro projeto como esse. Tendo mergulhado em um projeto como esse, você começa a compreender novas realidades. Você nunca saberá que está lá fora até se deparar com isso.
O engenheiro apresentou a maneira correta de corrigi-lo: a impressão de depuração deve ser feita em um arquivo que deve ser gravado por meio de um script cron no banco de dados em um thread. Caso exista muita impressão de depuração, o banco de dados não será desativado; os dados de depuração simplesmente aparecerão mais cedo ou mais tarde. Obviamente, esse engenheiro aprendeu com seu erro e não cometerá novamente. Mas outros engenheiros também devem saber disso. Como Eles precisam ser informados. Como fazê-los ouvir? Contando a eles toda a história do começo ao fim, expondo as conseqüências e propondo uma maneira correta de fazê-lo; e também, ouvindo e respondendo suas perguntas.
6. O que mais podemos aprender com esse erro ou "faça e não faça".
Ok, vamos continuar analisando essa interrupção. A empresa está crescendo rapidamente, novos engenheiros estão chegando. Como eles vão aprender com esse erro? Devemos contar a cada novo engenheiro sobre isso? Obviamente, haverá mais e mais erros - como fazemos com que todos aprendam com eles? A resposta é quase clara: crie um arquivo de fazer e não fazer. Nós estaremos escrevendo todos os tópicos neste arquivo. Mostramos esse arquivo para todos os nossos novos engenheiros e também para todos os nossos engenheiros atuais em um bate-papo em grupo de trabalho toda vez que o que fazer e o que não fazer é atualizado, incentivando fortemente todos a lê-lo novamente (para atualizar as informações antigas e ver as novo).
Você pode dizer que nem todo mundo lerá com atenção. Você pode dizer que a maioria vai esquecer logo após a leitura. E você estaria certo nas duas contas. No entanto, você não pode negar o fato de que algo ficará na cabeça de alguém. E isso é bom o suficiente. Na experiência do Citymobil, os engenheiros levam esse arquivo muito a sério e as situações em que algumas lições foram esquecidas ocorreram muito raramente. O próprio fato de a lição ter sido esquecida pode ser visto como um problema; devemos tirar uma conclusão e analisar os detalhes para descobrir o caminho para mudar alguma coisa no futuro. Esse tipo de escavação leva a formulações mais precisas e exatas do que se deve ou não.
A explicação da interrupção descrita acima: crie um arquivo de fazer e não fazer; escreva tudo o que aprendemos nele, mostre o arquivo para toda a equipe, solicite a todos os novatos que o estudem e incentive as pessoas a fazer perguntas.
Conselho geral que derivamos da revisão de interrupção: não devemos usar uma combinação de palavras "merda acontece". Assim que você diz em voz alta, todo mundo decide que nada precisa ser feito, nenhuma conclusão é necessária, já que os humanos sempre cometeram erros, estão cometendo erros agora e serão cometidos no futuro. Portanto, em vez de dizer essa frase, você deve fazer
uma conclusão específica. Uma conclusão - talvez seja um pequeno, mas ainda assim, um passo na direção da melhoria do processo de desenvolvimento, sistemas de monitoramento e ferramentas automatizadas. Pequenos passos resultam em um serviço mais estável!
7. Em vez de epílogo
Em outras partes, vou falar sobre os tipos de interrupções na experiência do Citymobil e entrar em detalhes sobre cada tipo de interrupção; Também vou falar sobre as conclusões que tiramos sobre as interrupções, como modificamos o processo de desenvolvimento, que automação introduzimos. Fique atento!