
Com este artigo, abro um ciclo curto de dois artigos, nos quais descreverei em detalhes como conseguimos aumentar a estabilidade dos serviços Citymobil várias vezes ao longo de vários meses. O artigo começa com uma história sobre nossos negócios, sobre a tarefa, sobre o motivo do surgimento do problema de aumentar a estabilidade e sobre limitações. Citymobil é um agregador de táxis em rápido crescimento. Em 2018, cresceu mais de 15 vezes no número de viagens bem-sucedidas. Em alguns meses, o crescimento excedeu 50% em relação ao mês anterior.
Os negócios cresceram aos trancos e barrancos (e ainda estão crescendo): a carga nos servidores, o tamanho da equipe e a frequência de lançamentos aumentaram. Junto com isso, novas ameaças à estabilidade do serviço apareceram. A empresa enfrentou a tarefa mais importante - não interromper o crescimento dos negócios para aumentar a estabilidade. Neste artigo, mostrarei como conseguimos realizar essa tarefa em pouco tempo.
1. Declaração do problema: o que exatamente queremos melhorar
Antes de melhorar algo, você precisa aprender como medi-lo para entender claramente se há uma melhoria. Quanto mais próximo o valor medido estiver dos termos favoráveis aos negócios, melhor. Porque quanto maior a probabilidade de melhorarmos o que os negócios realmente precisam. Do ponto de vista de seu sucesso, o parâmetro mais importante para nós é o número de viagens concluídas com sucesso (daqui em diante brevemente - o número de viagens). É precisamente por esse parâmetro que os investidores nos avaliam quando tomam uma decisão sobre investimentos. Quanto mais viagens, mais cara a empresa é.
Algumas viagens dão lucro, outras - uma perda. Mas todas as viagens são igualmente importantes para nós, mesmo que não sejam lucrativas, porque nos permitem aumentar a participação de mercado (de fato, a perda de viagens é uma taxa pelo aumento da participação de mercado). Portanto, cada viagem adicional recebida é boa e cada viagem perdida é ruim. Todas as viagens são iguais em termos de sucesso nos negócios.
A partir daqui, obtivemos um critério compreensível para medir a estabilidade: o número de viagens perdidas são viagens que claramente perdemos devido a problemas técnicos. Um problema técnico significa, por exemplo, um bug no código, um 500º erro, uma falha na infraestrutura, uma integração interrompida com um serviço de parceiro (por exemplo, mapas do Google).
2. Como contar as viagens perdidas?
Às vezes, as viagens perdidas são fáceis de calcular, outras difíceis. Por exemplo, no caso de uma negação de serviço completa, quando nada funciona (pah-pah-pah), é muito fácil calcular as viagens perdidas. Conhecemos o gráfico de tendências do número de viagens antes do outono, vemos a tendência deste gráfico após o outono, estamos completando a linha entre o ponto em que ele começou simples e o ponto em que terminou. A área do gráfico do número de viagens nesta linha concluída é de viagens perdidas.
No gráfico a seguir, a linha preta mostra viagens em um determinado dia e a linha verde mostra viagens há uma semana. O eixo X é o tempo. No eixo Y, o número de disparos em um determinado intervalo de tempo em torno do ponto X. Um pico claro é visto abaixo na forma de um triângulo agudo. A área desse triângulo é o número de viagens perdidas. Claro, esse é um valor aproximado, porque o gráfico está flutuando, mas entendemos que até 10 a 20% de precisão é suficiente para estimar a escala do acidente de uma empresa.

Se simples não estiver completo, mas parcial (também, pah-pah-pah), o cálculo será um pouco mais complicado. Por exemplo, se houver um erro devido ao qual 10% dos pedidos nunca são distribuídos de carro, vemos uma falha no cronograma da viagem e, em seguida, uma recuperação (após a correção do bug). Em uma situação semelhante, viagens perdidas são a área delimitada acima pela linha de tendência; da parte inferior - a programação real do número de viagens, para a esquerda - a linha vertical do início do tempo de inatividade, para a direita - a linha vertical do final do tempo de inatividade.
O gráfico abaixo mostra que o pico de queda não é tão óbvio, mas a presença de viagens para a semana anterior sem um pico de queda ajuda a entender que um pico de queda é uma perda. Além disso, uma comparação de viagens para o dia atual e o mesmo dia da semana com a semana anterior deixa claro que o pico mais baixo à direita não é a perda de viagens, mas uma falha usual a essa hora do dia, porque está correlacionado com a semana anterior.

Geralmente é difícil construir uma linha de tendência, porque o gráfico dente de serra. Nesse caso, a comparação semana a semana nos ajuda. Se você desenhar duas linhas no mesmo gráfico - a última semana e a atual -, as curvas mais ou menos são semelhantes em forma, mas diferem apenas porque uma está acima da outra (a semana atual usual é maior que a anterior, embora exista exceções). A comparação semana a semana é importante, porque cada dia da semana, devido a circunstâncias diferentes, tem um formulário de agendamento diferente. Observando o gráfico semanal, você pode entender onde pode estar a linha de tendência das viagens de hoje.
Obviamente, uma viagem perdida em si é um problema muito maior do que apenas uma viagem perdida. Um cliente que deseja sair de um jeito ou de outro deixará, por exemplo, um serviço competitivo e, posteriormente, poderá não retornar para nós, ou retornar apenas quando um concorrente o desapontar, o que é improvável, porque concorrentes são muito fortes. Além disso, mesmo que um concorrente desaponte o cliente, não é fato que ele retornará, porque tudo parecerá em sua mente para que todos tenham um serviço ruim e não há sentido em saltar sobre os concorrentes.
Ou seja, uma viagem perdida devido a problemas técnicos significa, de fato, algumas viagens perdidas.
Para não se confundir em termos, chamamos viagens perdidas diretamente devido a um problema técnico,
viagens perdidas primárias e viagens perdidas por deixar o competidor,
viagens perdidas secundárias .
Idealmente, para calcular o dano total a uma empresa a partir de uma viagem perdida primária, você precisa entender o quanto isso gerou a viagem perdida secundária. I.e. é necessário multiplicar o número de viagens perdidas iniciais por um certo coeficiente
K , que pode ser calculado com base na frequência média de uso do serviço e no tempo médio que o usuário retorna após deixar o concorrente.
Supondo que o coeficiente
K não mude muito ao longo do tempo, para entender a tendência de perda de viagens, basta considerar as viagens perdidas primárias e tentar reduzir seu número, uma vez que a proporção de viagens perdidas primárias período a período será a mesma que a proporção de viagens perdidas secundárias período a período período. Exemplo: se perdemos 1000 viagens primárias no mês passado, as viagens secundárias perdemos 1000 *
K e, no total, perdemos 1000 * (1+
K ). Se, além disso, no mês atual perdemos 500 viagens primárias, depois viagens secundárias perdemos 500 *
K e, no total, perdemos 500 * (1+
K ). Nesse caso, independentemente do valor do coeficiente
K, começamos a perder viagens 1000 * (1+
K ) / (500 * (1+
K )) = 2 vezes menos.
Mesmo que o coeficiente
K mude com o tempo, ou seja, é uma função do tempo K (t), então ainda estamos interessados em reduzir o número de viagens perdidas primárias. Porque se K (t) cresce com o tempo, somos ainda mais obrigados a fazer esforços para perder menos viagens primárias, porque o dano de perder cada um é cada vez mais alto. Por outro lado, se K (t) diminui com o tempo, isso significa que, por algum motivo, os usuários são cada vez mais leais a nós, apesar do mau serviço, o que significa que simplesmente devemos atender às suas expectativas!
Total: estamos lutando por uma diminuição constante nas viagens perdidas primárias.
3. Ok, consideramos as viagens perdidas. O que vem a seguir?
Munidos de uma ferramenta compreensível para medir viagens perdidas, passamos à parte mais interessante - como fazer isso para reduzir as perdas? E enquanto não abrandar o crescimento atual! Como subjetivamente nos pareceu que a maior parte dos problemas técnicos que causam a perda de viagens está relacionada ao back-end, decidimos antes de tudo prestar atenção ao processo de desenvolvimento do back-end. Olhando para o futuro, direi que acabou assim - o back-end se tornou o principal campo de batalha para viagens perdidas.
4. Como o processo funciona
Os problemas geralmente ocorrem devido à rolagem do código e outras ações manuais. Serviços que nunca mudam e nunca tocam, às vezes também falham, mas essa exceção é apenas uma regra de confirmação.
A exceção mais engraçada da minha experiência foi o seguinte serviço. Quando eu trabalhei na RBC em 2006 (Deus, quantos anos eu tenho!), Então em um dos serviços de correio da RBC havia um gateway através do qual todo o tráfego passava e que verificava os endereços IP para serem incluídos na lista negra. O serviço funcionou no FreeBSD e funcionou corretamente. Mas um dia ele parou de trabalhar. Adivinha por que? Um disco desintegrou-se nesta máquina (blocos ruins acumulados, acumulados e acumulados). Desintegrou-se 3 anos antes da negação de serviço no serviço (!). E tudo vivia com um disco disperso. E então o "frach", por qualquer motivo desconhecido para ela pelos motivos de Phryakh, decidiu repentinamente virar um disco em ruínas e, eventualmente, congelar. Tenho certeza que o Linux não faria isso. Mas este é um holivar separado.
Para resumir o exposto, os problemas se devem à intervenção manual. Uma vez na minha infância, entre 10 e 12 anos, em uma de minhas viagens à floresta, ouvi de meu pai uma frase que lembrei por toda a vida: "para que a fogueira não se apague, você não precisa tocá-la". Acho que muitos de nós se lembram dos momentos em que jogamos lenha em um fogo já aceso e apagou por algum motivo desconhecido.
Conclusão: os problemas são criados por ações manuais de uma pessoa, por exemplo, jogando lenha em um fogo já bem queimado, que corta o oxigênio e apaga um incêndio, ou implementando códigos com bugs na produção. Portanto, para entender a causa dos problemas nos serviços, você precisa entender exatamente como a implementação ocorre e como o processo de desenvolvimento funciona.
O processo foi totalmente focado no desenvolvimento rápido e foi organizado da seguinte maneira:
- 20 a 30 lançamentos por dia;
- desenvolvedores se lançam;
- teste rápido em um ambiente de teste pelo desenvolvedor;
- testes automáticos / de unidade mínimos, revisões mínimas.
Os desenvolvedores nas condições mais difíceis, de fato, sem áreas traseiras cobertas em face do controle de qualidade, com um enorme fluxo de tarefas produtivas e experimentos importantes para os negócios, trabalharam o mais focado e coordenado possível, resolveram problemas complexos de maneiras simples, não permitiram que o código “crescesse”, problemas comerciais bem compreendidos , com muita responsabilidade para as mudanças, reverteu rapidamente o modo inativo. Citymobil não é único aqui. Há 8 anos, no Mail.ru Mail, quando cheguei ao trabalho lá, havia uma situação semelhante. E também iniciamos o Mail.ru Cloud de maneira rápida e simples, sem reverência. E já alterou os processos posteriormente para obter maior estabilidade.
Certamente, você percebeu isso por conta própria: quando ninguém cobre suas costas, quando apenas você está sozinho com a produção, quando um enorme fardo de responsabilidade é esmagado - você faz milagres. Eu mesmo tive essa experiência (ainda mais grave). Era uma vez, no século passado (acho que a Internet já estava no século passado, fico surpresa quando me lembro), trabalhei como o único desenvolvedor do serviço de correio newmail.ru, implantei ele mesmo e também testei a produção
if (!strcmp(username, “danikin”)) { … some new code… }
mesmo através de
if (!strcmp(username, “danikin”)) { … some new code… }
:-) Portanto, essa situação está próxima de mim.
Não me surpreenderia se soubesse que, com uma abordagem tão simples "no joelho", muitas empresas iniciantes começaram, bem-sucedidas e mal sucedidas, mas impulsionadas pela mesma paixão - foco no rápido crescimento dos negócios e na captura de mercado.
Por que o processo foi especificamente no Citymobil? Inicialmente, havia poucos desenvolvedores. Eles trabalharam na empresa por um longo tempo e tinham um bom entendimento de código e negócios. Lançamentos foram várias vezes ao dia. Erros eram extremamente raros. O processo funcionou perfeitamente para essas condições.
5. Por que um bom processo ameaçou a estabilidade?
Com o aumento do investimento no projeto, tornamos nossos planos de produtos mais agressivos e começamos a contratar muitos desenvolvedores. O número de lançamentos na produção aumentou, mas era esperado que a qualidade caísse, porque os novos caras mergulharam no sistema e na essência dos negócios em condições de combate. Com um aumento no número de desenvolvedores, a estabilidade começou a cair não linearmente, mas quadraticamente (o número de lançamentos cresceu linearmente e a qualidade da distribuição média também caiu linearmente; "linearmente" * "linearmente" == "quadraticamente").
Era óbvio que era impossível deixar o processo dessa forma. Simplesmente não foi preso sob novas condições. Mas foi necessário alterá-lo sem prejuízo do tempo de colocação no mercado, ou seja, com a preservação de 20 a 30 lançamentos por dia (e com um aumento no número proporcional ao tamanho da equipe). De fato, foi em um grande número de lançamentos que todo o argumento foi feito. Crescemos rapidamente, montamos muitos experimentos, avaliamos rapidamente seus resultados e montamos novos experimentos. Testamos rapidamente hipóteses de produtos e negócios, estudamos sobre elas e apresentamos novas hipóteses, que testamos rapidamente rapidamente etc. Não queríamos reduzir essa taxa em nenhum caso. Além disso, eles queriam aumentá-lo e aumentar a velocidade de contratação de desenvolvedores. I.e. nossas ações destinadas ao crescimento dos negócios criaram uma ameaça à estabilidade, mas não queríamos corrigi-las de nenhuma maneira.
6. Ok, a tarefa é clara, o processo é claro. O que vem a seguir?
Com experiência no Mail.ru Mail e Mail.ru Cloud, onde a estabilidade em algum momento foi colocada em primeiro plano, onde lançamentos uma vez por semana, funcionalidade detalhada e casos de teste descritos em detalhes, tudo é coberto com testes automáticos e unitários, o código é revisado pelo menos uma vez e, às vezes, três vezes, me deparei com uma situação completamente nova.
Parece que tudo é simples: repita o processo no Citymobil como no Mail ou na Cloud e aumente a estabilidade do serviço. Mas, como nessa piada obscena, existem nuances: a) lançamentos no Mail / Cloud são realizados uma vez por semana, e não 30 vezes por dia, e no Citymobil não queríamos sacrificar a frequência dos lançamentos, b) no Mail / Cloud todo o código cobertos por testes automáticos / unitários, e no Citymobil não dispomos de tempo e recursos para isso, todas as forças do desenvolvimento de back-end foram dedicadas ao teste de hipóteses e aprimoramentos de produtos. Ao mesmo tempo, os desenvolvedores de back-end estavam fisicamente ausentes, mesmo em altas velocidades de contratação (agradecimentos especiais ao RH Citymobil - estes são os melhores RH do mundo! Acho que haverá um artigo separado sobre o nosso processo de RH), ou seja, não havia como participar de perto de testes e análises sem diminuir a velocidade.
7. Quando você não sabe o que fazer, aprenda com os erros
Então, o que fizemos magicamente no Citymobil? Decidimos aprender com os erros. O método de melhorar o serviço aprendendo com os erros é tão antigo quanto o mundo. Se o sistema funcionar bem, é bom. Se o sistema funcionar com erros, isso também será bom, porque você pode aprender com esses erros. Isso parece fácil. Fazer ... também é simples. O principal é definir uma meta.
Como estudamos? Começamos registrando escrupulosamente informações sobre cada acidente maior e menor. Francamente, inicialmente eu realmente não queria fazer isso, porque esperava um milagre e pensei que os acidentes parariam sozinhos. Claro, nada parou. Novas realidades exigiam implacavelmente mudanças.
Começamos a registrar todos os acidentes em uma tabela comum do Google. Para cada acidente, foram fornecidas as seguintes informações breves:
- data, hora, duração;
- causa raiz
- o que eles fizeram para resolver o problema;
- impacto nos negócios (número de viagens perdidas, outros efeitos);
- conclusões.
Para acidentes grandes, criamos arquivos grandes separados com descrições detalhadas minuto a minuto, desde o momento em que o acidente começou até o momento da conclusão: o que fizemos, que decisões foram tomadas (geralmente essas descrições são chamadas de análise post-mortem). E na tabela geral, adicionamos links para esse post-mortem.
O objetivo deste arquivo era o seguinte: tirar conclusões, cuja implementação reduzirá as perdas de viagens. Além disso, era muito importante formular com precisão o que é a "causa raiz" e quais são as "conclusões". Essas palavras são compreensíveis em si mesmas. Mas todo mundo entende à sua maneira.
8. Um exemplo de erro no qual eles aprenderam
A causa raiz é a eliminação da qual evitará acidentes semelhantes no futuro. E as conclusões são como eliminar a causa raiz (ou reduzir a probabilidade de sua ocorrência).
A causa raiz é sempre mais profunda do que parece. As conclusões são sempre mais complicadas do que parecem. Para não se acalmar e refletir sobre o que parece ser, é preciso sempre estar insatisfeito com a causa raiz supostamente encontrada e sempre estar insatisfeito com as supostas conclusões. Esse descontentamento cria fervor para uma análise mais aprofundada.
Deixe-me dar um exemplo: lançou o código - tudo caiu, reverteu - tudo funcionou. Qual é a causa raiz?
Role para fora , você diz. Se ela não estivesse, não haveria acidente. Então, qual é a conclusão: não lançar? Má conclusão (prejudicial aos negócios, para ser mais preciso). Ou seja, essa provavelmente não é a causa raiz, você precisa ir mais fundo.
Abra com um bug . A causa raiz? Vamos dizer. Como consertar isso? Por testes, você diz. Quais testes? Por exemplo, uma regressão completa de todas as funcionalidades. Esta é uma boa conclusão, lembre-se. Mas a estabilidade deve ser melhorada aqui e agora, embora não haja uma regressão completa. Precisa cavar ainda mais fundo.
Lançamento com um bug que ocorreu devido ao fato de termos feito a depuração da impressão em uma tabela no banco de dados, carregada além da medida e o banco de dados foi interrompido sob carga . Isso já é mais interessante. Torna-se imediatamente claro que mesmo um teste de regressão completo não o salvará desse problema. Afinal, a base de teste não terá a mesma carga que a produção.
Qual é a causa raiz desse problema, se você se aprofundar ainda mais? Para descobrir, conversamos com o desenvolvedor. Aconteceu que ele estava acostumado com o fato de que a base lida com as cargas. Mas, nas condições de rápido crescimento do projeto, a base foi gerenciada ontem, mas hoje não está mais lá. Poucos de nós já trabalhamos em projetos que crescem 50% mês a mês. Por exemplo, para mim, este é o primeiro projeto desse tipo. Depois de mergulhar nesse projeto, você começa a tomar consciência de novas realidades. Até a primeira vez que você encontrar algo, nunca saberá o que acontece.
O desenvolvedor sugeriu imediatamente a solução correta para a causa da queda: faça a depuração da impressão em um arquivo, escreva o arquivo offline pelo cron no banco de dados em um fluxo com deslizamentos. Se houver muita impressão de depuração, o banco de dados não ficará parado, apenas as informações de depuração aparecerão fora de tempo. Obviamente, esse desenvolvedor já aprendeu com seu erro e não o repetirá no futuro. Mas outros desenvolvedores também precisam descobrir isso. Como Precisa contar a eles. Como fazê-lo ouvir? Conte a eles toda a história do começo ao fim, explique o que levou e sugira imediatamente como fazê-lo, bem como ouça suas perguntas e responda-as.
9. O que mais você pode aprender com esse erro, ou faça e não faça
Então, continuamos a analisar esse acidente. A empresa está crescendo rapidamente, novos funcionários vêm. Como eles aprenderão com esse erro? Diga a todos os novos funcionários? Obviamente, haverá mais e mais erros - como fazer com que todos aprendam com eles? A resposta é quase óbvia: faça um arquivo de fazer e não fazer (leia como "faça e faça")! Em uma tradução gratuita para o russo, o idioma "faça e não faça" significa "o que é bom e o que é ruim". Neste arquivo, escrevemos todas as conclusões sobre o tema do desenvolvimento. Mostramos o arquivo para todos os novos funcionários e também no bate-papo geral dos desenvolvedores toda vez que o arquivo é atualizado, e pedimos a todos que o leiam novamente (para atualizar o conhecimento antigo e o novo).
Você dirá que nem todo mundo lerá com atenção. Você dirá que muitos esquecerão imediatamente após a leitura. E você estará certo nas duas vezes. Mas você não negará que alguém tenha algo na cabeça. E isso já é bom. De acordo com a experiência do Citymobil, os desenvolvedores levam esse arquivo muito a sério, e os casos em que algumas lições foram esquecidas eram extremamente raros. A propósito, o próprio fato de a lição ter sido esquecida pode ser considerado um problema e dela é possível tirar uma conclusão, ou seja, entender os detalhes e entender como mudar o processo para o futuro. Muitas vezes, essa escavação leva a uma redação mais precisa e clara do que fazer e não fazer.
Conclusão do acidente descrito acima: crie um arquivo de fazer e não fazer, escreva o que aprendeu nele, mostre o arquivo para toda a equipe e peça a todos os novatos que o estudem.
A partir do conselho geral que entendemos na análise de acidentes: não use a frase “fator humano”. Assim que você diz isso, todos entendem imediatamente, para que nada precise ser feito, não sejam necessárias conclusões, as pessoas estavam erradas, erradas e estarão erradas. Portanto, em vez de pronunciar esta frase, é necessário tirar uma
conclusão específica . Conclusão - este é pelo menos um pequeno, mas pequeno, passo na mudança do processo, aprimorando o monitoramento, aprimorando as ferramentas automáticas. A partir de pequenos passos, o tecido do serviço estável é costurado!
10. Em vez de um epílogo
Na
segunda parte, vou falar sobre os tipos de acidentes de acordo com a experiência da Citymobil e mergulhar nos detalhes de cada tipo de acidente, além de dizer quais conclusões tiramos dos acidentes, como mudamos o processo, que introduziu a automação. O mais interessante na segunda parte! Fique atento!