A última coisa que você deseja ver durante a depuração de código é o caos . Mas e se esse caos for controlado e lançado pelas mãos do próprio desenvolvedor? Por que deliberadamente organizar turbulência no bom funcionamento do seu aplicativo, como obter tranqüilidade ao liberar recursos importantes e onde exatamente a prática da engenharia do caos é útil , leia PavelOsipov na conversa entre o principal podcast da AppsCast e Pavel Osipov.
Alexey Kudryavtsev: Olá pessoal! Hoje, nosso convidado é Pavel Osipov, do Mail.ru Cloud, com quem falaremos sobre engenharia do caos.
Pavel Osipov: Olá pessoal! Por seis anos, eu tenho gerenciado o desenvolvimento do Mail.ru Cloud. Durante esse período, acumulamos muitas práticas de testes econômicos, e uma delas é a engenharia do caos. Essa prática permite realizar uma série de experimentos controlados para identificar a integridade do seu sistema em um ambiente hostil. Com base nos resultados dessas experiências, você obtém informações úteis. Por exemplo, é improvável que você veja regularmente como o sistema se comporta em uma rede instável. Se o usuário costuma viajar no metrô ou descansar em um ambiente wifi de hotel, a rede não é tão estável quanto no local de trabalho do programador. Após cada uma das minhas férias no mar, trago um "portfólio" inteiro de logs sobre o que deu errado com o aplicativo.
Pessoalmente, criar o caos manual me permite obter uma dose adicional de confiança de que tudo vai correr bem, mesmo que tudo esteja ruim fora do aplicativo.
Há situações em que confio no caos manual mais do que em testes automáticos.
Vendo a raiz do caos
Alexei Kudryavtsev: De onde vieram as raízes dessa prática?
Pavel Osipov: Essa é uma prática de servidor, onde há muitos outros problemas. Estamos acostumados com o conceito de dívida técnica, e no Ocidente também existe
uma dívida sombria - uma dívida oculta que inevitavelmente surge em sistemas complexos. Diferentemente da dívida técnica, onde conscientemente tomamos emprestada a hora do futuro do presente, a dívida oculta é invisível na fase de criação do sistema. Ocorre na junção de componentes ou hardware e software e pode levar a uma cascata de problemas: algo quebra em um componente, se sobrepõe a outro e agora todo o sistema está.
Por exemplo, em 2016, devido ao desligamento em cascata do banco de dados, o Facebook tinha 2,5 horas. Em seguida, o sistema que verificou a validade dos arquivos de configuração começou a excluí-los por engano, não apenas no subsistema de armazenamento em cache, mas também no banco de dados que era a fonte principal.
Gosto muito da entrevista com Oleg Anastasiev, de Odnoklassniki, sobre a realização de exercícios para evitar acidentes de infraestrutura. Eles têm três datacenters, que devem estar alertas 24 horas por dia, 7 dias por semana, mas a cada trimestre ocorre algum tipo de falha. Eles conduzem esses exercícios de produção. Por um lado, isso parece assustador, porque se algo imprevisível acontecer, todo o data center cairá e não estará disponível no produto. Mas, por outro lado, esse processo é controlado e, se algo der errado, você o verá imediatamente, o interromperá e tudo será restaurado. Se isso acontecer em condições de vida em combate, ligá-lo novamente não funcionará e a análise dos motivos do desligamento se prolongará por um longo tempo.
Os benefícios do caos no desenvolvimento móvel
Daniil Popov: Até agora, estamos falando sobre desenvolvimento de servidores, onde os microsserviços são populares e interrupções em cascata são possíveis. Você pode dar mais exemplos do que verificar na engenharia do caos no desenvolvimento móvel?
Pavel Osipov: Meu exemplo favorito é o log de aplicativos. Nas condições de teste, nossas ações podem ser muito brandas com relação ao aplicativo: entramos nas configurações da conta, clicamos no botão "exit", o aplicativo saiu e, ao visualizar a tela de login, tudo parece estar bem. Os usuários geralmente têm situações mais exóticas. Por exemplo, o cliente alterou a senha por meio da interface da web ou ocorreu um grande número de logs em outros dispositivos e o token de atualização foi substituído. Esse log ocorre não na janela com a conta do usuário, mas, por exemplo, no momento do visualizador de fotos em tela cheia.
Encontramos muitas situações em que o registro em locais diferentes do aplicativo leva a consequências como vazamentos de memória. O mesmo visualizador com um bloco de conclusão pode pegar um serviço vital, que eventualmente vazou.
Simulamos condições usando a engenharia do caos. O sistema possui um serviço que, de forma transparente para serviços de aplicativos de alto nível, atualiza o token de acesso ao aplicativo usando o token de atualização do aplicativo. Introduzimos o caos no qual o serviço, em vez de atualizar o token, com um certo grau de probabilidade, o estraga, e cada desenvolvedor encontra um log várias vezes ao dia em um local inesperado.
Graças a isso, descobrimos um comportamento interessante do UIKit no iOS: se, quando um ViewController raiz estiver realçado, outra janela for bloqueada da janela, o ViewController raiz vazará e permanecerá no sistema para sempre. Se ao mesmo tempo o ViewController tiver um link para serviços que, de acordo com a lógica da arquitetura, devem existir no sistema em uma instância, os problemas não poderão ser evitados. Por exemplo, a nuvem tem um serviço de carregamento automático de fotos e, se dois desses serviços permanecerem no sistema, eles farão muito trabalho desnecessário e colocarão a bateria do dispositivo duas vezes mais rápido do que deveria.
Outro caso curioso. Quando o iOS 8 apareceu, houve problemas com extensões: em alguns dispositivos, quando todas as permissões nas configurações do aplicativo foram concedidas, no início, o sistema afirmou que o aplicativo não tem acesso ao grupo de aplicativos compartilhados.
Tipologia do caos
Daniil Popov: O caos é introduzido no sistema automaticamente com base no interesse ou na configuração, mas uma pessoa precisa de uma olhada para entender o que deu errado?
Pavel Osipov: O caos é diferente: manual e automático. No caso do sistema operacional, que dizia que o aplicativo não tinha acesso ao grupo de aplicativos compartilhados e que as extensões não podiam acessar recursos compartilhados e banco de dados, foi utilizado o caos manual, que foi ativado usando uma marca de seleção nas configurações do sistema do aplicativo. Isso poderia ser facilmente modelado pelos caras da equipe de controle de qualidade.
Há um caos automatizado. Em particular, são erros modelados nos microsserviços de nosso back-end e o caos associado à atualização do token. As consequências são diferentes. O layout percorrido pode ser determinado através da observação visual. Existem locais que permitem detectar anomalias no modo automático. Por exemplo, em nosso aplicativo, vazamentos de memória são detectados automaticamente. Existem dois contêineres de IoC no sistema. Um gerente é o tempo de vida dos serviços globais, que coincide com o tempo de vida do aplicativo, outro contêiner é o gerente de serviços que coincide com o tempo do usuário. Cada contêiner de IoC, criando um serviço, verifica se ele existe em uma instância.
Vamos voltar ao exemplo com os logs. Em algum lugar, ocorreu um login repentino e o desenvolvedor voltou a entrar na conta para continuar trabalhando. Nesse ponto, o contêiner de IoC relata que ocorreu um vazamento de memória e o serviço, que em teoria deveria existir em uma instância, é detectado novamente.
Quando é a hora do caos?
Alexei Kudryavtsev: O que serviu de gatilho para a implementação da prática?
Pavel Osipov: Chegamos a isso através da necessidade de reduzir o custo dos testes. Como lidar com os mesmos problemas do razlogin? Você pode escrever testes de unidade para vazamentos, pode ficar confuso e escrever testes de interface do usuário.
A engenharia do caos é a prática mais barata, pois não está vinculada a casos de usuários, mas atua automaticamente para todos os casos de usuários juntos.
O segundo gatilho - antes da introdução da prática, em nosso relatório de falha, falhas semelhantes com a mesma causa raiz eram frequentemente observadas. Por exemplo, a falha ocorreu não por causa do log do sistema no perfil, mas porque o usuário estava percorrendo a galeria de fotos naquele momento. As situações são diferentes e é impossível testar todas as combinações de razlogins. Então, eu queria criar algo que automatize o processo.
A engenharia do caos tem uma prática relacionada -
testes mutacionais . Nesta prática, modificamos pequenos pedaços de código e vemos como isso afeta os testes. Se, após a alteração, os testes forem executados corretamente, significa que, para esses fragmentos de código, os testes não serão suficientes.
A diferença entre a engenharia do caos e os testes de mutação é que não alteramos automaticamente o código de produção, mas o ambiente.
Alexei Kudryavtsev: Seria possível localizar a causa e corrigi-la sem a engenharia do caos?
Pavel Osipov: Não há uma única razão que provoque acidentes. Cada caso é único à sua maneira. Por exemplo, o botão modal apareceu na parte superior da janela, e isso levou o ViewController ruinoso a vazar durante o razlog. Não é possível prever todas as combinações de hierarquias de janelas que você possui durante o registro. Caos que cria padrões localizados nos quais ocorrem vazamentos e falhas.
Alexei Kudryavtsev: Há quanto tempo você usa essa prática?
Pavel Osipov: Começamos a usá-lo no início do projeto em 2012, porque era necessário desenvolvê-lo rapidamente e não havia tempo para testes em larga escala. Além disso, isso não é apenas impressionante, mas também uma experiência positiva.
Daniil Popov: Se algo falhou no meu aplicativo e eu preciso iniciar uma tarefa no JIRA, o que posso corrigir no futuro, como posso reproduzir esta situação?
Pavel Osipov: Não existe uma receita universal. A engenharia do caos é ativada quando o aplicativo é depurado e desativada quando a versão do release é criada, para que essas situações possam ser vistas através dos logs no console do ambiente de desenvolvimento, a partir do qual você pode descobrir como colocar a tarefa no JIRA.
Alexei Kudryavtsev: Você está tentando criar um comportamento reproduzível para que seu sistema de caos o notifique de problemas e sugira inseri-lo na configuração no início para repetir esse estado?
Pavel Osipov: Parece cósmico e possivelmente em arquiteturas como Redux. Se a arquitetura permitir que você registre todas as ações que precederam eventos críticos, isso é possível. Isso não é assim conosco. Isso foi praticado quando eu estava trabalhando como programador de servidor em telecomunicações. Houve testes que randomizaram a entrada do subsistema e verificaram uma saída adequada. Conseguimos que, quando o teste com entrada aleatória travasse o sistema e no programa responsável por testar a automação, todos os parâmetros necessários da solicitação de entrada fossem adiados para que pudessem ser reproduzidos.
Aplique o caos no aplicativo
Daniil Popov: É correto que esse caos seja introduzido no código manualmente?
Pavel Osipov: Sim, nosso cliente de rede possui uma funcionalidade embutida na qual você pode enviar uma configuração, que descreve o parâmetro caos que deve ser reproduzido. Com base na configuração, ele decide fazer proxy de uma solicitação do cliente para o servidor ou responder por conta própria. A camada para trabalhar com a rede é tal que você pode personalizar o caos introduzido pelo microsserviço no back-end. Não faz sentido modelar erros na validade dos dados de autorização se as solicitações de microsserviço não exigirem autorização.
Não apenas selecionamos aleatoriamente tudo, reproduzimos o código perfeito, mas selecionamos aleatoriamente o que o usuário pode reproduzir na vida real.
Alexei Kudryavtsev: O que você seleciona aleatoriamente além da rede e dos arquivos?
Pavel Osipov: Depuramos a prática de respostas aleatórias de endpoints específicos para modelar o comportamento e o caos de cada microsserviço separadamente. Concluímos o trabalho de mover o sistema de arquivos para subsistemas separados e estou tentando modelar vários tipos de erros quando um aplicativo tenta gravar ou ler um arquivo. Simulei manualmente o acesso ao grupo de aplicativos compartilhados no aplicativo e eu realmente quero começar a modelar o comportamento do aplicativo quando ele começar com um espaço em disco extremamente pequeno, no qual é impossível criar um banco de dados.
Alexei Kudryavtsev: Isso é tudo que você faz?
Pavel Osipov: Em princípio, sim. Ainda não corrigimos todos os bugs que foram encontrados usando o caos existente. Obviamente, é interessante aumentar o caos e transferir para outros subsistemas, mas não teremos tempo para consertar o máximo possível.
Onde é o lugar do caos? Você sempre pode encontrar um local onde possa criar outra turbulência para o aplicativo. É importante desenvolver problemas. Causamos caos porque registramos um grande número de problemas semelhantes.
Se o monitoramento mostrar que em outros subsistemas não há problemas especiais, não faz sentido gastar tempo modelando circunstâncias imprevistas.
Isso não se aplica ao faturamento, onde a operação correta é importante.
Alexei Kudryavtsev: Por outro lado, não sabemos o que está acontecendo com os usuários - isso é um caos por si só, porque você não sabe onde colocá-lo ou não e apenas precisa simulá-lo.
Pavel Osipov: Você sempre precisa olhar para o ROI. Obviamente, você pode reproduzir os casos mais exóticos, mas, se forem solteiros, talvez não sejam críticos, e não há sentido em modelá-los.
Desafios da introdução do caos
Alexei Kudryavtsev: O que já foi feito foi fácil para você e o que causou dificuldades?
Pavel Osipov: Acostumar-se ao caos é incomum para um iniciante, pois essa não é uma prática comumente usada. É difícil se adaptar ao fato de você ter vários erros. Em quase todas as telas, você pode obter um pacote de "quinhentos" ou incompreensíveis "404", o servidor responde uma vez. Somente com o tempo você se acostuma ao fato de que tudo isso é chato e as respostas do servidor são modeladas pelo próprio sistema.
É difícil quando você tem um recurso crítico que já está pegando fogo e precisa finalizá-lo o mais rápido possível, e o razlogin aparece de repente no lugar do acúmulo de solicitações. Por exemplo, você precisa compilar corretamente a tela e todas as solicitações para concluir com êxito, e isso é tão improvável que você precise executar algumas dezenas de vezes para atingir o estado desejado. Nesses casos, desabilitar o caos se torna uma contramedida, e é importante não esquecer de ativá-lo novamente.
Outro ponto que causa insatisfação é o uso do caos em serviços de infraestrutura com um grande número de efeitos colaterais.
Daniil Popov: Então, os desenvolvedores sempre têm o caos ativado por padrão?
Pavel Osipov: Absolutamente. Às vezes, quando você nem se importa com o caos e as situações exóticas que ele pode reproduzir para você, isso é irritante. Você precisa suportar, mas sempre pode ajustar o nível de caos se sua tela estiver trabalhando intensamente com a rede. Por outro lado, o caos pode revelar um problema distante do local em que você está procurando, e não do desenvolvedor que desenvolve esse recurso. Acontece que seu recurso, no qual o caos é adicionado, leva a consequências que afetam o recurso de seu colega. Você não saberá se o caos será incluído apenas em um momento específico de desenvolvimento.
O significado do caos é identificar consequências imprevistas na interação de um grande número de componentes.
Se você incluir o caos de maneira controlada e precisa, essas cenas raras, porém bem direcionadas, serão invisíveis.
Daniil Popov: O caos impede a legibilidade do código?
Pavel Osipov: Quando o caos é introduzido fora do sistema, adere ao acabado e, sim, parece confuso. Em nós, devido a uma longa experiência de uso, o caos é tecido organicamente no sistema e tão isolado que você não percebe isso no código.
Alexei Kudryavtsev: Você pega muitos casos raros, os corrige e o código é cercado por muletas. Isso complica a lógica do aplicativo?
Pavel Osipov: Essa é sempre uma grande parte do nosso código, mas, de outra forma, grandes aplicativos de produção não são gravados. Obviamente, tudo depende da habilidade do desenvolvedor, que sabe como consertar o código para que não incomode os olhos.
Profissionais da introdução do caos
Daniil Popov: Existem indicadores quantitativos que melhoraram após a introdução da engenharia do caos?
Pavel Osipov: Para mim, a métrica mais importante é a tranqüilidade interior quando envio um recurso para lançamento.
Alexey Kudryavtsev: A paz não pode ser vendida para as empresas. Como argumentar a introdução da engenharia do caos na empresa?
Pavel Osipov: a engenharia do caos libera tempo para os testadores, pois há testes automáticos. O mesmo acidente com o razlogin após a introdução da prática do caos quase desapareceu do nosso JIRA.
A engenharia do caos tem um efeito benéfico no ciclo de lançamento, à medida que você obtém um feedback rápido. Uma coisa é quando o recurso finalizado entra em teste e, após um longo tempo, você é informado sobre o número de bugs encontrados, é completamente diferente quando você tem um testador de robô que funciona durante todo o programa de depuração.
Tenho uma sensação de confiança, pois os resultados dos testes de unidade são muito menores do que o caos causado em 50% ao baixar milhares de arquivos. Com essa carga, todas as combinações mais incríveis serão definitivamente corrigidas.
Quem aprender e por onde começar?
Alexei Kudryavtsev: Quais ferramentas você usou para isso? Tomou bibliotecas abertas ou escreveu e postou em código aberto?
Pavel Osipov: Publicamos uma
biblioteca de rede em código aberto, mas não existem ferramentas especializadas. O único que eu conheço é o
Netflix Chaos Monkey , que "aleatoriamente" executa a instância da AWS e os encerra, parece ver se tudo correu bem se um certo número de contêineres for extinto. Acredito que escrever configurações onde você entra em contato com sistemas adjacentes não requer automação profunda.
Daniil Popov: Onde posso ler mais sobre a engenharia do caos?
Pavel Osipov: Primeiramente,
o site dos Princípios do Caos , ao qual estão vinculados todos os recursos deste tópico. Em segundo lugar, os livros
Learning Chaos Engineering e
Chaos Engineering Observability .
Em geral, a engenharia do caos é a prática do senso comum e o conhecimento fundamental não existe. Você sempre precisa entender onde incutir o caos. Ao mesmo tempo, o caos é único para cada aplicação? e você deve primeiro entender o que precisa ser implementado com você.
Alexei Kudryavtsev: Por onde começar, se você ainda decidir introduzir o caos?
Pavel Osipov: Comece analisando os problemas no sistema, que travam e por que eles surgem. Depois de identificar a raiz do mal, você deve entender como modelar situações que levam a problemas. E o terceiro passo é introduzir cuidadosamente o caos e mantê-lo sob controle.
Alexei Kudryavtsev: Muitas coisas podem prejudicar o aplicativo, mas como priorizar? Onde é melhor não se intrometer?
Pavel Osipov: Não há coisas irreais. A relação preço e exaustão é importante. Se houver uma API de sistema rica, envolvê-la com seus próprios wrappers é caro. Se você não entender completamente algo, começará a provocar o caos, que é de natureza impossível e levará a uma luta fútil. Por exemplo, se toda a API do UIKit ou do Shopping estiver coberta pelo caos.
O caos não é um puxão aleatório, mas uma compreensão clara das situações simuladas.
Alexei Kudryavtsev: Quanto você recomenda implementar esta prática?
Pavel Osipov: Eu geralmente recomendo começar com a introdução da engenharia do caos, em vez de testes de unidade, pois essa é a prática mais barata.
Interessado em engenharia do caos? Assista a Pavel Osipov no AppsConf de outono em São Petersburgo, de 21 a 21 de outubro, onde ele apresentará seu novo relatório sobre bancos de dados de valores-chave .