Vários Métodos de Debugging no OpenResty
API7.ai
December 16, 2022
No grupo de comunicação do OpenResty, os desenvolvedores frequentemente fazem esta pergunta: Como depurar no OpenResty? Até onde eu sei, existem algumas ferramentas no OpenResty que suportam depuração com pontos de interrupção, incluindo um plugin no VSCode, mas elas não são amplamente utilizadas até o momento. Incluindo o autor agentzh e alguns contribuidores que conheço, todos usam o mais simples ngx.log
e ngx.say
para fazer depuração.
Isso não é amigável para a maioria dos iniciantes. Isso significa que os muitos mantenedores principais do OpenResty têm apenas o método primitivo de imprimir logs quando encontram um problema difícil?
Claro que não. No mundo do OpenResty, SystemTap
e o gráfico de chamas são as ferramentas padrão para lidar com problemas difíceis e questões de desempenho. Se você tiver uma dúvida sobre isso em uma lista de discussão ou issue, o mantenedor do projeto pedirá que você envie um gráfico de chamas e solicitará uma descrição gráfica em vez de textual.
Nos próximos dois artigos, vou falar com você sobre depuração e o conjunto de ferramentas que o OpenResty criou especificamente para depuração. Hoje vamos começar vendo o que está disponível para depurar programas.
Pontos de interrupção e impressão de logs
Por muito tempo no meu trabalho, eu dependia dos recursos avançados de depuração do IDE (ambiente de desenvolvimento integrado) para rastrear programas, o que parecia natural. Para problemas que podem ser reproduzidos em um ambiente de teste, não importa o quão complexos, tenho confiança de que posso chegar à raiz do problema. A razão é que o bug pode ser reproduzido repetidamente, e a causa pode ser encontrada configurando pontos de interrupção e imprimindo logs. Tudo o que você precisa é de paciência.
Desse ponto de vista, resolver bugs que ocorrem de forma estável em um ambiente de teste é um trabalho físico. A maioria dos bugs que resolvo no meu trabalho se enquadra nessa categoria.
No entanto, observe que há dois pré-requisitos: um ambiente de teste e reprodução estável. A realidade é sempre menos do que ideal. Se o bug só for reproduzido no ambiente de produção, há uma maneira de depurá-lo?
Aqui eu recomendo uma ferramenta - Mozilla RR
. Você pode usá-la como um repetidor, gravar o comportamento do programa e depois reproduzi-lo repetidamente. Para ser franco, independentemente do ambiente de produção ou de teste, desde que você possa gravar a "evidência" do bug, ela pode ser usada como "prova em tribunal" para analisar lentamente.
Algoritmo de busca binária e comentários
No entanto, para alguns projetos grandes, por exemplo, o bug pode vir de um dos vários serviços, ou pode haver um problema com a consulta SQL no banco de dados, nesse caso, mesmo que o bug possa ser reproduzido de forma estável, você não pode ter certeza de em qual parte o bug ocorreu. Então, ferramentas de gravação como Mozilla RR
falham.
Nesse ponto, você pode se lembrar do clássico "algoritmo de busca binária". Primeiro, comentamos metade da lógica no código, e se o problema persistir, o bug está no código não comentado, então comentamos a metade restante da lógica e continuamos o loop. Dentro de algumas vezes, o problema é reduzido a um tamanho completamente gerenciável.
Essa abordagem pode parecer um pouco burra, mas é eficiente em muitos cenários. Claro, à medida que a tecnologia avança e a complexidade do sistema aumenta, recomendamos usar um padrão como OpenTracing
para rastreamento distribuído.
O OpenTracing pode ser incorporado em várias partes do sistema e relatar a cadeia de chamadas e o rastreamento de eventos composto por vários Span
s para o servidor através do Trace ID
para análise e apresentação gráfica. Isso pode ajudar os desenvolvedores a encontrar muitos problemas ocultos, e os dados históricos serão salvos para que possamos compará-los e visualizá-los a qualquer momento.
Além disso, se o seu sistema for mais complexo, como em um ambiente de microsserviços, então Zipkin
, Apache SkyWalking
são boas escolhas.
Depuração dinâmica
Os métodos de depuração que descrevi acima são suficientes para resolver a maioria dos problemas. No entanto, se você encontrar uma falha que ocorre apenas ocasionalmente na produção, levará bastante tempo para rastreá-la adicionando logs e rastreamento de eventos.
Anos atrás, eu era responsável por um sistema que ficava sem recursos do banco de dados por volta das 1:00 da manhã todos os dias e causava uma avalanche em todo o sistema. Na época, verificamos as tarefas agendadas no código durante o dia, e à noite, a equipe esperava que o bug fosse reproduzido na empresa, e então verificava o status de execução dos submódulos quando ele era reproduzido. Não encontramos a causa do bug até a terceira noite.
Minha experiência é semelhante ao contexto de vários engenheiros do sistema Solaris que criaram o Dtrace
. Na época, os engenheiros do Solaris também passaram dias e noites solucionando um problema estranho de produção, apenas para descobrir que era porque uma configuração estava escrita errada. Mas, ao contrário de mim, os engenheiros do Solaris decidiram evitar esse problema completamente e inventaram o Dtrace
, especificamente para depuração dinâmica.
Diferente de ferramentas de depuração estática como GDB
, a depuração dinâmica pode depurar serviços online. Todo o processo de depuração é não sensível e não intrusivo para o programa depurado, sem modificar o código, muito menos reiniciar. Para usar uma analogia, a depuração dinâmica é como um raio-X, que pode examinar o corpo do paciente sem a necessidade de coleta de sangue e gastroscopia.
Dtrace
foi um dos primeiros frameworks de rastreamento dinâmico, e sua influência levou ao surgimento de ferramentas de depuração dinâmica semelhantes em outros sistemas. Por exemplo, os engenheiros da Red Hat criaram o Systemtap
no Linux, que é o que vou falar a seguir.
Systemtap
Systemtap
tem sua própria DSL
, que pode ser usada para configurar pontos de sonda. Antes de entrarmos em mais detalhes, vamos instalar o Systemtap
para ir além do abstrato. Aqui, basta usar o gerenciador de pacotes do sistema para instalar.
sudo apt install systemtap
Vamos ver como é um programa hello world
escrito em Systemtap
:
# cat hello-world.stp
probe begin
{
print("hello world!")
exit()
}
Não parece fácil? Você precisa usar privilégios de sudo para executar.
sudo stap hello-world.stp
Ele imprimirá o hello world!
. Na maioria dos cenários, não precisamos escrever nossos próprios scripts stap
para fazer a análise, porque o OpenResty já tem muitos scripts stap
prontos para fazer a análise regular, e vou apresentá-los a você no próximo artigo. Então, hoje precisamos ter um breve entendimento dos scripts stap
.
Depois de alguma prática, voltando ao nosso conceito, o Systemtap
funciona convertendo o script stap
acima para C e executando o compilador C do sistema para criar o módulo do kernel
. Quando o módulo é carregado, ele ativa todos os eventos de sonda conectando-se ao kernel.
Por exemplo, begin
será executado no início da sonda, e o correspondente end
, então o programa hello world
acima também pode ser escrito da seguinte maneira:
probe begin
{
print("hello ")
exit()
}
probe end
{
print("world!")
Aqui, eu só dei uma introdução muito superficial ao Systemtap
. Frank Ch. Eigler, o autor do Systemtap
, escreveu um e-book Systemtap tutorial que introduz o Systemtap
em detalhes. Se você quiser aprender mais e entender o Systemtap
profundamente, sugiro começar com este livro como o melhor caminho de aprendizado.
Outros frameworks de rastreamento dinâmico
Systemtap
não é suficiente para engenheiros de análise de kernel e desempenho.
Systemtap
não entra no kernel do sistema por padrão.- Ele funciona de uma maneira que é lento para inicializar e pode ter um impacto no funcionamento normal do sistema.
eBPF
(extended BPF) é um novo recurso adicionado ao kernel do Linux nos últimos anos. Comparado ao Systemtap
, eBPF
tem as vantagens de suporte direto ao kernel, sem falhas e inicialização rápida. Ao mesmo tempo, ele não usa DSL
, mas a sintaxe C diretamente, então é muito mais fácil de começar.
Além das soluções de código aberto, o VTune
da Intel também é uma das melhores ferramentas. Sua interface intuitiva e apresentação de dados permitem que você analise os gargalos de desempenho sem escrever código.
Gráfico de Chamas
Finalmente, vamos relembrar o gráfico de chamas mencionado no artigo anterior. Como mencionamos anteriormente, os dados gerados por ferramentas como perf
e Systemtap
podem ser exibidos de forma mais visual usando o gráfico de chamas. O diagrama a seguir é um exemplo de um gráfico de chamas.
No gráfico de chamas, a cor e a tonalidade dos blocos de cor são sem significado, apenas para fazer uma distinção simples entre diferentes blocos de cor. O gráfico de chamas é uma sobreposição dos dados amostrados cada vez, então os dados do usuário são a largura e o comprimento dos blocos.
Para o gráfico de chamas na CPU, a largura do bloco de cor é a porcentagem do tempo de CPU ocupado pela função: quanto mais largo o bloco, maior o dreno de desempenho. Se houver um pico achatado, é aí que está o gargalo de desempenho. O comprimento do bloco de cor, por outro lado, representa a profundidade da chamada da função, com o bloco superior mostrando a função em execução e todos os abaixo sendo chamadores dessa função. Então, a função abaixo é o supertipo da função acima: quanto mais alto o pico, mais profunda é a chamada da função.
Resumo
É essencial saber que mesmo uma técnica não intrusiva como o rastreamento dinâmico não é perfeita. Ele só pode detectar um processo individual específico; em geral, só o ligamos brevemente para usar os dados amostrados durante esse tempo. Então, se você precisar detectar em vários serviços ou por longos períodos, ainda precisará de uma técnica de rastreamento distribuído como opentracing
.
Quais ferramentas e técnicas de depuração você usa no seu trabalho regular? Sinta-se à vontade para deixar um comentário e discutir comigo, também convido você a compartilhar este artigo com seus amigos, para que possamos aprender e progredir juntos.